冒泡排序(Bubble Sort)的基本思想:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。时间复杂度为O(n2).
简单选择排序(Simple Selection Sort)的基本思想:通过n-i次关键字之间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i个记录交换。应该说,尽管与冒泡排序同为O(n2), 但简单选择排序的性能上还是要略优于冒泡排序。
直接插入排序(Straight Insertion Sort)的基本思想:将一个记录插入到前面已经排序好的有序表中,从而得到一个新的、记录数不断加1的有序表。直接插入排序法的时间复杂度为O(n2) 。从这里也看出,同样的O(n2)时间复杂度,直接插入排序法比冒炮和简单选择排序的性能要好一些。
希尔排序(Shell Sort)的基本思想:将相隔某个增量的记录组成一个子序列,在这些子序列内分别进行直接插入排序,得到基本有序的序列,最后在将增量为1的记录(即整个序列)的进行一次直接插入排序。其实希尔排序就是直接插入排序的改进。大量的研究表明,当增量序列为dlta[k]=2t-k+1-1 ( 0 <=k<=t <= [log2 (n+l)])时,可以获得不错的效率, 其时间复杂度为O(n3/2,要好于直接排序的o(n2)。需要注意的是, 增量序列的最后一个增量值必须等于1 才行。另外由于记录是跳跃式的移动,使得排序的效率提高,但也使得希尔排序并不是一种稳定的排序算法。
堆排序(Heap Sort) 的基本思想是:将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根结点。将官移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值) .然后将剩余的n - 1 个序列重新构造成一个堆,这样就刽寻到n 个元素中的次小值。如此反复执行, 便能得到一个有序序列了。其实,堆排序就是对简单选择排序进行的一种改进,这种改进效果是非常明显的。堆排序的时间复杂度是O(nlogn)。由于堆排序对原始记录的排序状态并不敏感,因此它无论是最好、最坏和平均时间复杂度均为O(nlogn) 。这在性能上显然要远远好过于冒泡、简单选择、直接插入的O(n2)的时间复杂度了。
快速排序(Quick Sort)的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行同样的排序,依次递归达到整个序列有序的目的。对于枢轴pivot的选取可以采用三数取中(median of three)法,即取三个关键字先进行排序,将中间作为枢轴,一般是取左端、右端和中间三个数,也可以随机选取。对于待排序列较长的,可采用九数取中的方法。此外,还可以优化一些不必要的交换。优化小数组的排序,即当序列较长时采用快排,较短时采用直接插入排序,设置一个阈值就可以了。快速排序算法经过多次的优化之后,在整体性能上,依旧是排序算法的王者。
归并排序( Merging Sort) 的基本思想是:假设初始序列含有n 个记录, 则可以看成是n 个有序的子序列,每个子序列的长度为1 ,然后两两归并,得到[n/2] <[x]表示不小于x 的最小整数)个长度为2 或1 的有序子序列;再两两归并,……,如此重复, 直至得到一个长度为n 的有序序列为止,这种排序方法称为2 路归并排序.
1 #include "stdafx.h" 2 3 #include "stdio.h" 4 #define TRUE 1 5 #define FALSE 0 6 #define MAX_LENGTH_INSERT_SORT 5 7 8 void bubblesort(int *list, int index); 9 void selectsort(int *list, int index); 10 void insertsort(int *list, int index); 11 void shellsort(int *list, int index); 12 void heapsort(int *list, int index); 13 void heapadjust(int *list, int s, int m); 14 void quicksort(int *list, int index); 15 void Qsort(int *list, int low, int high); 16 int partition(int *list, int low, int high); 17 18 typedef int status; 19 int list[20]; //默认最大长度为20 20 int temp; 21 int i, j; 22 int node; 23 status change = TRUE; 24 25 void swap(int *list, int i, int j)//交换元素 26 { 27 temp = list[i]; 28 list[i] = list[j]; 29 list[j] = temp; 30 } 31 32 void main(void) 33 { 34 int index = 0; 35 printf("Please input the value you want to sort(exit for 0): "); 36 scanf_s("%d", &node); 37 while (node != 0) 38 { 39 list[index] = node; 40 index += 1; 41 scanf_s("%d", &node); 42 } 43 //bubblesort(list, index); 44 //selectsort(list, index); 45 //insertsort(list, index); 46 //shellsort(list, index);//wrong 47 //heapsort(list, index); 48 quicksort(list, index); 49 } 50 51 void bubblesort(int *list, int index) //冒泡排序 时间复杂度O(n2) 52 { 53 for (j = 0; j<index && change; j++) 54 { 55 change = FALSE; 56 for (i = 1; i<index - j; i++) 57 { 58 if (list[i - 1]>list[i]) 59 { 60 swap(list, i - 1, i); 61 change = TRUE; 62 } 63 } 64 } 65 printf(" 冒泡排序后为: "); 66 for (i = 0; i < index; i++) 67 { 68 printf("%d ", list[i]); 69 } 70 71 } 72 73 void selectsort(int *list, int index)//简单选择排序 时间复杂度O(n2) 74 { 75 int min; 76 for (i = 0; i < index - 1; i++) 77 { 78 min = i; 79 for (j = i + 1; j < index; j++) 80 { 81 if (list[min]>list[j]) 82 { 83 min = j; 84 } 85 } 86 if (min != i) 87 { 88 swap(list, min, i); 89 } 90 } 91 printf(" 简单选择排序后为:"); 92 for (i = 0; i < index; i++) 93 { 94 printf("%d ", list[i]); 95 } 96 } 97 98 void insertsort(int *list, int index)//直接插入排序 时间复杂度O(n2) 99 { 100 for (i = 1; i < index; i++) 101 { 102 if (list[i - 1]>list[i]) 103 { 104 temp = list[i]; 105 for (j = i; j >= 1 && list[j - 1] > temp; j--) 106 { 107 list[j] = list[j - 1]; 108 } 109 list[j] = temp; 110 } 111 } 112 printf(" 直接插入排序后为:"); 113 for (i = 0; i < index; i++) 114 { 115 printf("%d ", list[i]); 116 } 117 } 118 void shellsort(int *list, int index) //希尔排序 时间复杂度为O(nr),(1<r<2) 119 { 120 int length = index; 121 while (length>1) 122 { 123 length = length / 3 + 1; //间隔长度 124 for (i = length; i < length; i++) 125 { 126 if (list[i] < list[i - length]) 127 { 128 temp = list[i]; 129 for (j = i - length; j >= 0 && list[j]>temp; j -= length) 130 { 131 list[j + length] = list[j]; //这一行的j比下一行的j大length 132 } 133 list[j + length] = temp; //这一行的j比上一行的j小length 134 } 135 } 136 } 137 printf(" 希尔排序后为: "); 138 for (i = 0; i < index; i++) 139 { 140 printf("%d ", list[i]); 141 } 142 } 143 144 void heapsort(int *list, int index)//堆排序 时间复杂度为O(nlogn) 不稳定排序 145 { 146 for (i = index / 2; i>0; i--) 147 { 148 heapadjust(list, i, index); 149 } 150 for (i = index; i > 1; i--) 151 { 152 swap(list, 0, i - 1); 153 heapadjust(list, 1, i - 1); 154 } 155 printf(" 堆排序后为: "); 156 for (i = 0; i < index; i++) 157 { 158 printf("%d ", list[i]); 159 } 160 } 161 162 void heapadjust(int *list, int s, int m) //生成大顶堆 163 { 164 temp = list[s - 1]; //数组list是从0开始,而堆是从1开始,所以要减1; 165 for (j = 2 * s; j <= m; j *= 2) 166 { 167 if (j < m && list[j - 1] < list[j]) //比较结点左孩子和右孩子的大小 168 ++j; 169 if (temp >= list[j - 1]) //比较孩子中的较大者和结点的大小 170 break; 171 list[s - 1] = list[j - 1]; //交换 172 s = j; 173 } 174 list[s - 1] = temp;//插入; 175 } 176 177 void quicksort(int *list, int index)//快速排序,冒泡排序的升级版 时间复杂度O(nlogn) 178 { 179 Qsort(list, 0, index - 1); 180 printf(" 快速排序后为: "); 181 for (i = 0; i < index; i++) 182 { 183 printf("%d ", list[i]); 184 } 185 } 186 void Qsort(int *list, int low, int high) 187 { 188 int pivot; 189 if (low < high)//if((high-low)>MAX_LENGTH_INSERT_SORT),优化,当high-low大于某个常数时用快速排序 190 { 191 pivot = partition(list, low, high); 192 193 Qsort(list, low, pivot - 1); 194 Qsort(list, pivot + 1, high); 195 } 196 //else 197 //insertsort(list, high-low); 198 } 199 int partition(int *list, int low, int high) 200 { 201 int pivotkey; 202 203 int m = low + (high - low) / 2;//三数取中法 ,对于较大的待排序列可使用九数取中 204 if (list[low] > list[high]) 205 { 206 swap(list, low, high); 207 } 208 if (list[m] > list[high])//交换中间和右端,保证中间较小 209 { 210 swap(list, m, high); 211 } 212 if (list[m] > list[low])//交换中间和左端,保证中间值放在low位置 213 { 214 swap(list, m, low); 215 } 216 217 pivotkey = list[low]; 218 while (low < high) 219 { 220 while (low < high&&list[high] >= pivotkey) 221 { 222 high--; 223 } 224 list[low] = list[high]; //采用替换而不交换,减少不必要的交换 swap(list, low, high); 225 while (low < high&&list[low] <= pivotkey) 226 { 227 low++; 228 } 229 list[high] = list[low]; //采用替换而不交换,减少不必要的交换 swap(list, low, high); 230 231 } 232 list[low] = pivotkey; 233 return low; 234 235 }