文章会不断的更新,有问题可以留言讨论,文章中有不对的地方欢迎大佬些及时指正,以免文章照成误人子弟的不良后果
前言
在学习一个东西前,我觉得首先明确学习目标是非常重要的,如果目标不明确,容易造成三分钟的热情,过了这几分钟兴趣就慢慢的淡了,下次在想起这个东西就不知是猴年马月了。因此我认为在学习一个东西前,我们有必要花些时间细细研究我们学习的目标,以及该学习到何种程度。 对于算法,我想作为一个程序员可能大家都大概了解其重要性,但是如果只是大概了解而能不深入理解的话,我相信这也终将成为我们不断晋升的一大阻碍,虽然以前上大学的时候,我没能真正明白数据结构和算法的重要性体现在哪儿,甚至在做了一段时间的android开发以后,还在保有我只是一个客户端开发,算法没有那么重要的心态,但是在工作中不断的深入学习之后,发现了很多时候不好的算法常常也会导致卡顿,不好的数据结构常常浪费空间的同时,也不一定带来更快的速度,现在也越来越体现到了算法和数据结果的重要性,因此我希望看到这篇文章的年轻程序员们,如果以后还想继续做一个IT工作者,一定要好好学习数据结构与算法。 本片文章介绍几种基本排序算法,及通过实验数据来展示各种算法的优缺点提示:以下是本篇文章正文内容,下面案例可供参考
一、冒泡排序
排序思路:通过对比和交换两个相邻元素,确保两个对比元素较大的在后,较小的在前,这样一趟对比所有相邻元素就能找到最大元素,依次就能找到大小顺序为1、2、…、n的元素
代码如下(示例):
public static void maoPaoSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 1; j < arr.length - i; j++) {
if (arr[j - 1] > arr[j]) {
int t = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = t;
}
}
}
}
二、选择排序
排序思路:通过n次循环,找出当轮循环中最小(最大)的数,并把它与序列中的第一(最后)位数交换
代码如下(示例):
public static void selectSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int smallestIndex = i;
for (int j = i; j < arr.length; j++) {
if (arr[smallestIndex] > arr[j]) {
smallestIndex = j;
}
}
if (smallestIndex != i) {
int t = arr[smallestIndex];
arr[smallestIndex] = arr[i];
arr[i] = t;
}
}
}
三、插入排序
代码如下(示例):public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int t = arr[i];
int j = i;
while (j > 0 && arr[j - 1] > t) {
arr[j] = arr[j - 1];
j--;
}
arr[j] = t;
}
}
四、快速排序
代码如下(示例):
private static void quickSort(int[] arr, final int start, final int end) {
if (start > end) {
return;
}
int l = start;
int r = end;
int flag = l;
while (l < r) {
while (arr[r] >= arr[flag] && l < r) {
r--;
}
if (arr[flag] > arr[r]) {
int t = arr[flag];
arr[flag] = arr[r];
arr[r] = t;
flag = r;
}
while (arr[l] <= arr[flag] && l < r) {
l++;
}
if (arr[flag] < arr[l]) {
int t = arr[flag];
arr[flag] = arr[l];
arr[l] = t;
flag = l;
}
}
sort(arr, start, l - 1);
sort(arr, l + 1, end);
}
五、希尔排序
代码如下(示例):
public static void shellSort(int[] arr) {
for (int dk = arr.length / 2; dk > 0; dk /= 2) {
for (int i = dk; i < arr.length; i++) {
int t = arr[i];
int j = i;
while (j >= dk && arr[j - dk] > t) {
arr[j] = arr[j - dk];
j -= dk;
}
arr[j] = t;
}
}
}
六、堆排序
代码如下(示例):
public static void heapSort(int[] arr) {
buildMaxHeap(arr);
for (int i = arr.length - 1; i >= 0; i--) {
swap(arr, 0, i);
forHeapify(arr, 0, i);
}
}
private static void buildMaxHeap(int[] arr) {
for (int i = (arr.length >> 1) - 1; i >= 0; i--) {
forHeapify(arr, i, arr.length);
}
}
private static void reHeapify(int[] arr, int i, int length) {
//递归实现
int left = (i << 1) + 1;
int largestIndex = i;
if ((left + 1) < length && arr[left + 1] > arr[largestIndex]) {
largestIndex = left + 1;
}
if (left < length && arr[left] > arr[largestIndex]) {
largestIndex = left;
}
if (largestIndex != i) {
swap(arr, largestIndex, i);
reHeapify(arr, largestIndex, length);
}
}
private static void forHeapify(int[] arr, int i, int length) {
//循环实现
int left = (i << 1) + 1;
int largestIndex = i;
while(left<length) {
if ((left + 1) < length && arr[left + 1] > arr[largestIndex]) {
largestIndex = left + 1;
}
if (left < length && arr[left] > arr[largestIndex]) {
largestIndex = left;
}
if (largestIndex != i) {
swap(arr, largestIndex, i);
left = largestIndex*2 +1;
i = largestIndex;
} else {
break;
}
}
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
测试数据结果分析
我们分别对上面集中排序进行两组测试,第一次随机产生5000个小于50000的数,每个排序测试10次,第二次对50000个进行10次
public class SortTest {
private int[] arr;
@Before
public void setUp() {
arr = new int[50000];
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(50000);
}
}
@Test
public void maopaoSortTest() {
//第一次length为5000 25ms 23ms 23ms 26ms 23ms 22ms 25ms 23ms 23ms 24ms
//第二次length为50000 3195ms 3123ms 3150ms 3191ms 3109ms 3139ms 3159ms 3186ms 3186ms 3134ms
long start = System.currentTimeMillis();
System.out.println("maopaoSortTest before arr = " + Arrays.toString(arr));
maoPaoSort(arr);
System.out.println("maopaoSortTest after arr = " + Arrays.toString(arr));
System.out.println("maopaoSortTest time = " + (System.currentTimeMillis() - start));
}
@Test
public void selectSortTest() {
//第一次length为5000 14ms 15ms 15ms 13ms 13ms 15ms 14ms 15ms 15ms 13ms
//第二次length为50000 785ms 810ms 774ms 789ms 785ms 797ms 814ms 772ms 807ms 787ms
long start = System.currentTimeMillis();
System.out.println("selectSortTest before arr = " + Arrays.toString(arr));
selectSort(arr);
System.out.println("selectSortTest after arr = " + Arrays.toString(arr));
System.out.println("selectSortTest time = " + (System.currentTimeMillis() - start));
}
@Test
public void insertSortTest() {
//第一次length为5000 9ms 12ms 11ms 9ms 11ms 11ms 10ms 10ms 9ms 10ms
//第二次length为50000 200ms 203ms 199ms 217ms 200ms 213ms 196ms 207ms 203ms 202ms
long start = System.currentTimeMillis();
System.out.println("insertSortTest before arr = " + Arrays.toString(arr));
insertSort(arr);
System.out.println("insertSortTest after arr = " + Arrays.toString(arr));
System.out.println("insertSortTest time = " + (System.currentTimeMillis() - start));
}
@Test
public void quickSortTest() {
//第一次length为5000 5ms 5ms 5ms 5ms 5ms 5ms 5ms 5ms 5ms 4ms
//第二次length为50000 47ms 33ms 29ms 38ms 53ms 39ms 41ms 31ms 38ms 42ms
long start = System.currentTimeMillis();
System.out.println("quickSortTest before arr = " + Arrays.toString(arr));
quickSort(arr, 0, arr.length);
System.out.println("quickSortTest after arr = " + Arrays.toString(arr));
System.out.println("quickSortTest time = " + (System.currentTimeMillis() - start));
}
@Test
public void shellSortTest() {
//第一次length为5000 5ms 6ms 6ms 6ms 6ms 6ms 6ms 7ms 6ms 6ms
//第二次length为50000 30ms 29ms 31ms 32ms 30ms 29ms 32ms 35ms 33ms 31ms
long start = System.currentTimeMillis();
System.out.println("shellSortTest before arr = " + Arrays.toString(arr));
shellSort(arr);
System.out.println("shellSortTest after arr = " + Arrays.toString(arr));
System.out.println("shellSortTest time = " + (System.currentTimeMillis() - start));
}
@Test
public void heapSortTest() {
//第一次length为5000 4ms 5ms 5ms 4ms 5ms 4ms 5ms 7ms 5ms 6ms
//第二次length为50000 31ms 32ms 30ms 29ms 31ms 30ms 32ms 37ms 30ms 30ms
long start = System.currentTimeMillis();
System.out.println("heapSortTest before arr = " + Arrays.toString(arr));
heapSort(arr);
System.out.println("heapSortTest after arr = " + Arrays.toString(arr));
System.out.println("heapSortTest time = " + (System.currentTimeMillis() - start));
}
}
从测试数据可以看出冒泡排序效率最低,其次分别为选择排序和插入排序,而快速排序在数据量为50000时效率开始明显低于希尔和堆排序,而希尔排序在数据量为5000时效率明显则低于快速排序,两次数据综合来看快速排序,希尔排序,堆排序都不稳定