几种简单排序算法
最简单的排序算法——冒泡排序:
1 void bubble_sort(int *arr, int len) 2 { 3 int up, down; 4 for(up = 0; up != len; ++ up) 5 { 6 for(down = 0; down != len - up - 1; ++ down) 7 { 8 if(arr[down] > arr[down + 1]) 9 swap(arr[down], arr[down + 1]); 10 } 11 } 12 }
还有一种思路,就是从头排到尾,再从尾排到前,这样的做法与上面的做法时间复杂度是一样的,在这里就不予以实现了。
当数组元素不多时,较快捷的排序算法就是——插入排序,实现代码如下:
void insert_sort(int *arr, int len) { int pos, index, key; for(pos = 1; pos != len; ++ pos) { key = arr[pos]; for(index = pos - 1; index >= 0; -- index) { if(arr[index] > key) arr[index + 1] = arr[index]; else break; } arr[index + 1] = key; } }
插入排序是将数组从开头开始变成一小段有序序列,再将下一个元素插入适当的位置,使数组变为一个长度加1的有序序列,这样做便无需每次都遍历一边整个数组了。
同样的情况下,另一种较快捷的排序算法是——选择排序,实现代码如下:
void select_sort(int *arr, int len) { int index, pos, min; for(pos = 0; pos != len; ++ pos) { min = pos; for(index = pos + 1; index != len; ++ index) { if(arr[min] > arr[index]) min = index; } if(min != pos) swap(arr[min], arr[pos]); } }
选择排序较快捷的地方是:无需每次都交换元素,这样为系统节省了一部分交换元素的步骤。
在数组元素较多时,快速排序就是一种不错的选择。
第一种实现代码如下:
static int func1(int *arr, int low, int high) //普通方法 { int key = arr[low]; while(low < high) { while(low < high && arr[high] >= key) -- high; if(low >= high) break; else swap(arr[high], arr[low]); while(low < high && arr[low] <= key) ++ low; if(low < high) swap(arr[high], arr[low]); } return low; } void quick_sort(int *arr, int len) { if(len <= 10) insert_sort(arr, len); else { int index = func1(arr, 0, len - 1); quick_sort(arr, index + 1); quick_sort(arr + index + 1, len - index - 2); } }
该种实现,主要是依靠递归方法,每次将数组分成两部分,前面的部分都比中间元素小,后面的部分都比中间元素大,这样,递归到最后,这个数组便成为一个有序序列。
第二种实现代码如下:
static int func2(int *arr, int low, int high) //快慢指针 { int fast = low + 1, last = low; int key = arr[low]; for(; fast <= high; ++ fast) { if(arr[fast] < key) { swap(arr[last + 1], arr[fast]); ++ last; } } swap(arr[low], arr[last]); return last; } void quick_sort(int *arr, int len) { if(len <= 10) insert_sort(arr, len); else { int index = func2(arr, 0, len - 1); quick_sort(arr, index + 1); quick_sort(arr + index + 1, len - index - 2); } }
该种是先,主要是依靠快慢指针的方法,每次快指针的元素比key小时,将快指针与慢指针的下一个元素交换,这样,快指针指向的元素始终都比key大,慢指针指向的元素,始终都比key小,最后再将arr[low]与慢指针交换,这样,key又一次变成了中间值,思路与普通方法一样,实现方法有一些改进。
堆排序,就是每一次将数组建立成堆,这样最大的元素始终在最前面,然后我们将该元素与相应的后面元素交换,即可得到有序序列。
堆排序实现代码如下:
static void func(int *arr, int low, int high) { int index; int key = arr[low]; for(index = 2 * low + 1; index <= high; index = 2 * index + 1) { if(index < high && arr[index] < arr[index + 1]) ++ index; if(key > arr[index]) break; arr[low] = arr[index]; low = index; } arr[low] = key; } void heap_sort(int *arr, int len) { if(len <= 10) insert_sort(arr, len); else { int index; for(index = (len - 2) / 2; index >= 0; -- index) func(arr, index, len - 1); for(index = len - 1; index > 0; -- index) { swap(arr[0], arr[index]); func(arr, 0, index - 1); } } }
建立成堆的方法,就是将元素下标每次乘2,得到最低层的值,将低层中较大的值与父值比较,若比父值大,则将该值赋给父值,否则退出,将key保存的父值赋到当前下标的元素。
由于算法部分有些地方比较难以理解,所以目前只能简单写出这几种算法,当然也可能有不完善的地方,以后会慢慢改进。