基本排序算法总结

来源:互联网 发布:linux epoll 实例 编辑:程序博客网 时间:2024/06/02 22:02

排序算法很多,这里做个总结,最重要的是记住算法思想,而不是记住程序怎么写。程序过一段时间就会忘了,算法原理熟悉了现场写出来应该是很容易的。

时间复杂度为O(n^2)的三种排序算法:插入排序、选择排序、冒泡排序。

插入排序:插入排序是选定元素找位置。对于位置为p上的元素,假定0~p-1的元素已经排序,如果p比它前面的元素小,那么p上的元素应该向前移动,直到p前面所有的元素都比它小为止。

void InsertSort(int* a, int length){if(a == NULL || length < 1)return;for(int i = 1; i < length; ++i){int tmp = a[i];int j;for(j = i; a[j-1] > tmp && j > 0; --j)a[j] = a[j-1];a[j] = tmp;}}

选择排序:选择排序是选定位置找元素。第一个位置上应该是最小的元素,那么先把最小的元素找出来放在第一个位置上。然后再考虑第二个位置,它应该放上第二小的元素,所以遍历剩下的元素找出最小的放在第二个位置上,直到所有位置都放上了合适的元素。

void SelectSort(int* a, int length){if(a == NULL || length < 1)return;for(int i = 0; i < length; ++i){int min = a[i];int indexOfMin = i;for(int j = i + 1; j < length; ++j){if(a[j] < min){min = a[j];indexOfMin = j;}}a[indexOfMin] = a[i];a[i] = min;}}

冒泡排序:冒泡排序也是选定位置找元素。冒泡排序的实现过程是两两交换,每次从最右边开始的元素开始比较,如果右边的元素比它左边一位的元素小,那么交换两个元素。例如3,2,1交换一次变成3,1,2,再交换一次变成1,3,2。这一过程总是使最小的元素移到最左边,最左边定义为0的时候最小的元素交换到位置0上,最左边定义为1时剩下的元素中最小的元素(也就是第二小)交换到位置1上,以此类推。

冒泡排序和选择排序过程很相似,但是冒泡排序的交换过程具有盲目性。冒泡排序只要右边元素比左边小都会发生交换,而选择排序只有当前元素小于最小值时记录最小值得位置(实际上等同于交换),内层循环结束后才发生一次交换。选择排序的交换次数比冒泡排序小,性能略优于冒泡排序。

void BubbleSort(int* a, int length){if(a == NULL || length < 1)return;for(int i = 0; i < length; ++i){for(int j = length - 1; j > i; --j){if(a[j] < a[j-1]){int tmp = a[j];a[j] = a[j-1];a[j-1] = tmp;}}}}

时间复杂度为O(nlogn)的四种排序算法:希尔排序、堆排序、归并排序、快速排序。

希尔排序:希尔排序只需要记住一条:它是变间隔的插入排序!插入排序那里比较的元素都是相邻的两个元素,间隔为1。希尔排序通过设置比较间隔,然后间隔逐渐缩小直到为1,所以希尔排序的最后一趟,也就是间隔为1的时候完全等同于插入排序了。间隔序列h1,h2,h3…hn叫做增量序列,增量序列的选取也会对排序算法的性能有影响,由于希尔排序很少使用就不讨论了。

void ShellSort(int* a, int length){if(a == NULL || length < 1)return;for(int increment = length / 2; increment > 0; increment /= 2)    //希尔建议的增量序列,但是并不好{for(int i = increment; i < length; ++i)   //<span style="color:#ff0000;">注意这里i的增量是1,而不是increment</span>{int tmp = a[i];int j;for(j = i; j >= increment && a[j-increment] > tmp; j -= increment)a[j] = a[j-increment];a[j] = tmp;}}}

堆排序:堆排序根据最大堆的堆顶总是堆上最大数的性质,每次交换堆顶和堆最后一个元素,这样堆顶元素放在了正确的位置,而由于堆顶更换了新的元素,需要下滤维护堆序。下滤完成以后可以看成比第一部大小减一的新的堆,继续交换堆顶和最后一个元素,这样第二大的数也摆在正确的位置上,重复这个过程直到堆的大小为0,即所有元素都已经摆放到合适的位置上。

#define LeftChild(i) 2*i+1void Swap(int& a, int& b){int tmp = a;a = b;b = tmp;}//最大堆下滤过程void PercDown(int* a, int n, int i){int tmp, child;for(tmp = a[i]; LeftChild(i) < n; i = child){child = LeftChild(i);if(child != n-1 && a[child] < a[child+1])  //最小堆的时候改为“>"++child;if(tmp < a[child])                         //最小堆的时候改为“>"a[i] = a[child];elsebreak;}a[i] = tmp;}void HeapSort(int* a, int n){//建堆过程for(int i = n/2 - 1; i >= 0; --i)PercDown(a,n,i);for(int i = n-1; i > 0; --i){Swap(a[0], a[i]);    //DeleteMaxPercDown(a, i, 0);}}

归并排序:归并排序假设存在两个已经排序的子数组A和B,申请一个额外的数组C,大小为n,每次从数组中A或B中取较小的数放入C中,直到其中一个子数组取完,另外一个子数组剩下的元素直接拷贝到数组C中。对于要排序的数组array,可以将array划分成两半,调用上述合并的过程,而对于各自部分的排序,递归的调用合并排序的函数。归并排序需要额外的大小为n的辅助空间,时间复杂度为O(nlogn)。

void Merge(int* array, int* TmpArray, int Lpos, int Rpos, int RposEnd){int IndexL, IndexR, index, numOfElement;IndexL = index = Lpos;IndexR = Rpos;numOfElement = RposEnd - Lpos + 1;while(IndexL < Rpos && IndexR <= RposEnd){if(array[IndexL] < array[IndexR])TmpArray[index++] = array[IndexL++];elseTmpArray[index++] = array[IndexR++];}while(IndexL < Rpos)TmpArray[index++] = array[IndexL++];while(IndexR <= RposEnd)TmpArray[index++] = array[IndexR++];for(int i = 0; i < numOfElement; ++i)array[i+Lpos] = TmpArray[i+Lpos];}void MergeSortCore(int* array, int* TmpArray, int start, int end){if(start < end){int center = (start + end) / 2;MergeSortCore(array, TmpArray, start, center);MergeSortCore(array, TmpArray, center+1, end);Merge(array, TmpArray, start, center+1, end);}}void MergeSort(int* array, int length){if(array == NULL || length <= 1)return;int* TmpArray = (int*) malloc(length*sizeof(int));if(TmpArray != NULL){MergeSortCore(array, TmpArray, 0, length-1);free(TmpArray);}else{cout << "Out of memory!" << endl;return;}}
快速排序:快速排序是实践中已知的最快的排序算法。快速排序的过程是一个分组的过程,选定基准值,从数组的前后两头同时开始遍历数组,如果左边的数小于基准值,滑过指针,如果右边的值大于或等于基准值,也滑过指针。当左边的值大于基准值而右边的值小于基准值时,交换两个数,直到两个指针交叉。这一过程使得数组中小于基准值的数都位于基准值的左边,大于基准值的数都位于基准值右边,基准值的位置已经确定不再改变,在分别排序基准值的左边和右边。

void Swap(int& p1, int& p2){int temp = p1;p1 = p2;p2 = temp;}void Qsort(int* array, int start, int end){if(start < end){int pivot = array[start];int pLeft = start + 1;int pRight = end;while(pLeft <= pRight){while(pLeft <= pRight && array[pRight] >= pivot)--pRight;while(pLeft <= pRight && array[pLeft] < pivot)++pLeft;if(pLeft < pRight)Swap(array[pRight], array[pLeft]);}Swap(array[start], array[pRight]);Qsort(array, start, pRight - 1);Qsort(array, pRight + 1, end);}}void QuickSort(int* array, int length){if(array == NULL || length <= 0)return;Qsort(array, 0, length - 1);}
排序算法性能分析:http://blog.csdn.net/cjf_iceking/article/details/7953637


0 0
原创粉丝点击