飞鱼科技排序算法总结思想&代码实现付英奇2016-2-24In-place sort (不占用额外内存或占用常数内存):插入排序、选择排序、冒泡排序、堆排序、快速排序。
Out-place sort:归并排序、基数排序、桶排序。
Stable sort:插入排序、冒泡排序、归并排序、基数排序、桶排序。
Unstable sort:选择排序、快速排序、堆排序。
时间复杂度为O(N*logN)的算法:归并排序、快速排序、堆排序、希尔排序。
时间复杂度为O(N*N)的算法:冒泡排序,选择排序、插入排序时间复杂度为O(N)的算法【桶排序思想】:基数排序,计数排序。
空间复杂度O(1)的算法:插入排序、选择排序、冒泡排序、堆排序、希尔排序。
空间复杂度O(logN)~O(N)的算法:快速排序。
空间复杂度O(N)的算法:归并排序空间复杂度O(M)的算法:基数排序、计数排序。
插入排序:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
voidinsertionSort(intnums[],int length){inti, j, temp;for(i = 1;i < length; ++i){j = i - 1;temp = nums[i];while(j >= 0 && temp <nums[j]) //两个条件的顺序不能互换,否则数组越界{nums[j+1] = nums[j];--j;}nums[j+1] = temp; //插入数的位置}}桶排序:工作的原理是将阵列分到有限数量的桶子里。
每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序)。
voidbuctekSort(intnums[], int length){intbuc[100] = {0};inti, k;for(i = 0;i < length; ++i)buc[nums[i]]++;for(i = 0;i < 100; ++i){if(buc[i] != 0){for(k = buc[i]; k > 0; --k)cout<<i<<'\t';}}}希尔排序:插入排序的改良版。
选择排序:每一趟从待排序的记录中选择出关键字最小的记录,顺序放在已排好序的子文件的最后,直到全部记录排序完毕。
常用的选择排序有简单选择排序和堆排序。
voidshellSort(intnums[],int length) { int group, i, j, temp; for(group = length/2; group > 0; group /= 2) //增量的取值规则为第一次取总长度的一半 { for(i = group; i< length; ++i) //第二次取一半的一半,依次累推直到1为止 { for(j = i - group; j >= 0; j -= group) { if(nums[j] >nums[j + group]) { temp = nums[j]; nums[j] = nums[j + group]; nums[j + group] = temp; } } }}}堆排序:voidHeapAdjust(intnums[], inti, int size) { int temp = nums[i]; intleftChild = 2*i + 1; intrightChild = leftChild + 1; while(leftChild< size) { // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点 if(rightChild< size &&nums[rightChild] >nums[leftChild]) { leftChild++; } // 如果父结点的值已经大于孩子结点的值,则直接结束 if(nums[leftChild] <= temp) { break; }// 把孩子结点的值赋给父结点nums[i] = nums[leftChild];// 选取孩子结点的左孩子结点,继续向下筛选 i = leftChild; leftChild = 2*i + 1;rightChild = leftChild + 1;}nums[i] = temp;}voidInitHeap(intnums[], int size) { for(inti = size/2 - 1; i>= 0; i--) { HeapAdjust(nums, i, size); } }voidHeapSort(intnums[], int size) { InitHeap(nums, size); for(inti = size -1; i> 0; i--) { myswap(&nums[i], &nums[0]); HeapAdjust(nums, 0, i); } }voidmyswap(int* a, int* b){int temp = *a;*a = *b; *b = temp; }冒泡排序:原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,这样一趟过去后,最大或最小的数字被交换到了最后一位,然后再从头开始进行两两比较交换,直到倒数第二位时结束。
voidbubbleSort(intnums[],int length){inti, k, temp, iExchanged;for(i = 0; i< length - 1; ++i){iExchanged = 0; //iExchanged = 0标志位没有换过for(k = 1; k < length - i; ++k){if(nums[k-1] >nums[k]){iExchanged = 1; //iExchanged = 1标志位换过temp = nums[k];nums[k] = nums[k-1];nums[k-1] = temp;}}if(!iExchanged) //一次都没有交换,就是有序的,直接退出{return;}}}快速排序:时间复杂度O(N*logN) 最坏O(N^2) 空间复杂度:O(N*logN) intAdjustArray(intnums[], int left, int right){int base = nums[left];while(left < right){while(left < right &&nums[right] >= base){right--;}if(left < right){nums[left] = nums[right];left++;}while(left < right &&nums[left] =< base){left++;}if(left < right){nums[right] = nums[left];right--;}}nums[left] = base;return left;}voidQuickSort(intnums[], int left, int right){if(left < right){int pivot = AdjustArray(nums, left, right);QuickSort(nums,left, pivot-1);QuickSort(nums,pivot+1, right);}}基数排序:数组实现#define RADIX_10 10 //基数0--9#define KEYNUM_31 10 //关键字位数[10位数]//----------------------------------------------intGetNumInPos(intnum, intpos){int temp = 1;for(inti = 0; i< pos-1; i++){temp *= 10;}return (num/temp) % 10; //返回第Pos位置上的数据}voidRadixSort(intnums[], int length){int *radixArrays[RADIX_10];for(inti = 0; i< 10; i++){radixArrays[i] = (int*)malloc(sizeof(int) * (length + 1));radixArrays[i][0] = 0; //index为0处记录这组数据的个数}for(intpos = 1; pos<= KEYNUM_31; pos++) //从个位开始到31位{inti, j;for(i = 0; i< length; i++) //分配过程{intnum = GetNumInPos(nums[i], pos);int index = ++radixArrays[num][0];radixArrays[num][index] = nums[i];}for(i = 0, j = 0; i< RADIX_10; i++) //收集{for(int k = 1; k <= radixArrays[i][0]; k++){nums[j++] = radixArrays[i][k];}radixArrays[i][0] = 0; //复位}}}。