//计数排序//时间复杂度:O(N+range)//空间复杂度:O(range)//只适合,一组数据,数据的范围比较集中,那么效率很高,局限性也在这里//并且只适合整数,如果是浮点数、字符串等等就不行了voidCountSort(int* a,int n){int max = a[0], min = a[0];for(int i =0; i < n; i++){if(a[i]> max)
max = a[i];if(a[i]< min)
min = a[i];}int range = max - min +1;int* count =malloc(sizeof(int)* range);memset(count,0,sizeof(int)*range);for(int i =0; i < n; i++){
count[a[i]- min]++;}int i =0;for(int j =0; j < range; j++){while(count[j]--){
a[i++]= j + min;}}free(count);}
Sort.c
#include"Sort.h"voidPrintArray(int* a,int n){for(int i =0; i < n; i++){printf("%d ", a[i]);}puts("\n---------------------------------");}// 插入排序//时间复杂度://最坏是O(N^2),顺序逆序//最好是O(N),顺序有序voidInsertSort(int* a,int n){//多趟排序for(int i =0; i < n -1; i++){int end = i;int tmp = a[end +1];while(end >=0){if(tmp < a[end]){
a[end +1]= a[end];
end--;}else{break;}}
a[end +1]= tmp;}}// 希尔排序//预排序->接近有序//直接插入排序//间隔为gap分成一组,对每组进行插入排序//平均O(N^1.3)//最坏:O(log3(N)*N)voidShellSort(int* a,int n){//gap > 1 的时候,预排序//gap == 1 的时候,直接插入排序 O(N)int gap = n;while(gap >1){
gap =(gap /3+1);for(int i =0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while(end >=0){if(tmp < a[end]){
a[end + gap]= a[end];
end -= gap;}else{break;}}
a[end + gap]= tmp;}}}// 选择排序voidSwap(int* p1,int* p2){int tmp =*p1;*p1 =*p2;*p2 = tmp;}voidSelectSort(int* a,int n){int left =0;int right = n -1;while(left < right){int minIndex = left, maxIndex = left;for(int i = left; i <= right; i++){if(a[i]< a[minIndex])
minIndex = i;if(a[i]> a[maxIndex])
maxIndex = i;}Swap(&a[left],&a[minIndex]);//如果max和left位置重叠,maxif(left == maxIndex){
maxIndex = minIndex;}Swap(&a[right],&a[maxIndex]);++left;--right;}}// 堆排序voidAdjustDwon(int* a,int n,int root){int parent = root;int child = parent *2+1;while(child < n){if(child+1< n && a[child +1]> a[child]){++child;}if(a[child]> a[parent]){Swap(&a[child],&a[parent]);
parent = child;
child = parent *2+1;}else{break;}}}//O(N*logN)voidHeapSort(int* a,int n){//升序 建大堆for(int i =(n -1-1)/2; i >=0; i--){AdjustDwon(a, n, i);}int end = n -1;while(end >0){Swap(&a[0],&a[end]);AdjustDwon(a, end,0);
end--;}}//冒泡和插入相比,谁更好//顺序有序,一样好//接近有序,插入好// // 冒泡排序//最坏:O(N^2)//最好:O(N)voidBubbleSort(int* a,int n){for(int end = n; end >0; end--){int exchange =0;for(int i =1; i < end; i++){if(a[i -1]> a[i]){Swap(&a[i -1],&a[i]);
exchange =1;}}if(exchange ==0)break;}}//快速排序优化//三数取中intGetMidIndex(int* a,int left,int right){int mid =(left + right)>>1;//left mid rightif(a[left]< a[mid]){if(a[mid]< a[right]){return mid;}elseif(a[left]> a[right]){return a[left];}else{return right;}}else//a[left] > a[mid]{if(a[mid]> a[right]){return mid;}elseif(a[left]< a[right]){return left;}else{return right;}}}// 快速排序递归实现// 快速排序hoare版本intPartSort1(int* a,int left,int right){int midIndex =GetMidIndex(a, left, right);Swap(&a[left],&a[midIndex]);int keyi = left;while(left < right){//找小while(left < right && a[right]>= a[keyi])--right;//找大while(left < right && a[left]<= a[keyi])++left;Swap(&a[left],&a[right]);}Swap(&a[keyi],&a[left]);return left;}// 快速排序挖坑法intPartSort2(int* a,int left,int right){int midIndex =GetMidIndex(a, left, right);Swap(&a[left],&a[midIndex]);int key = a[left];while(left < right){//找小while(left < right && a[right]>= key){--right;}//放到左边的坑位中,右边就形成新的坑
a[left]= a[right];//找大while(left < right && a[left]<= key){++left;}//放到右边的坑位中,左边就形成了新的坑
a[right]= a[left];}
a[left]= key;return left;}// 快速排序前后指针法//[begin, end]intPartSort3(int* a,int left,int right){int midIndex =GetMidIndex(a, left, right);Swap(&a[left],&a[midIndex]);int keyi = left;int prev = left;int cur = left +1;while(cur <= right){if(a[cur]< a[keyi]&&++prev != cur){Swap(&a[cur],&a[prev]);}++cur;}Swap(&a[keyi],&a[prev]);return prev;}voidQuickSort(int* a,int begin,int end){if(begin >= end)return;//int keyi = PartSort1(a, begin, end);//int keyi = PartSort2(a, begin, end);//小区间优化//1.如果这个子区间是数据较多,继续选key单趟,分割子区间分治递归//2.如果这个子区间是数据较少,再去分治递归不太划算if(end-begin >20){int keyi =PartSort3(a, begin, end);//[begin, keyi-1] meeti [keyi+1, end]QuickSort(a, begin, keyi -1);QuickSort(a, keyi +1, end);}else{InsertSort(a + begin, end - begin +1);}}// 快速排序 非递归实现//最大的问题->递归深度太深,程序本身没问题,但是栈空间不够,导致栈溢出//只能改成非递归,改成非递归有两种方式://1.直接改循环->斐波那契数列求解//2.树遍历非递归和快排非递归等等,只能用Stack存储数据模拟递归过程#include"Stack.h"voidQuickSortNonR(int* a,int begin,int end){
Stack st;StackInit(&st);StackPush(&st, begin);StackPush(&st, end);while(!StackEmpty(&st)){int left, right;
right =StackTop(&st);StackPop(&st);
left =StackTop(&st);StackPop(&st);int keyi =PartSort1(a, left, right);if(left < keyi -1){StackPush(&st, left);StackPush(&st, keyi -1);}if(keyi+1< right){StackPush(&st, keyi+1);StackPush(&st, right);}}StackDestory(&st);}void_Merge(int* a,int* tmp,int begin1,int end1,int begin2,int end2){int i = begin1;int j = begin1;while(begin1 <= end1 && begin2 <= end2){if(a[begin1]< a[begin2])
tmp[i++]= a[begin1++];else
tmp[i++]= a[begin2++];}while(begin1 <= end1)
tmp[i++]= a[begin1++];while(begin2 <= end2)
tmp[i++]= a[begin2++];//归并完成后,拷回原数组for(; j <= end2; j++){
a[j]= tmp[j];}}void_MergeSort(int* a,int left,int right,int* tmp){if(left >= right)return;int mid =(left + right)>>1;// [left, mid][mid+1,right]_MergeSort(a, left, mid, tmp);_MergeSort(a, mid +1, right, tmp);int begin1 = left, end1 = mid;int begin2 = mid +1, end2 = right;//两段有序子区间归并到tmp,并拷贝回去_Merge(a, tmp, left, mid, mid +1, right);}// 归并排序递归实现// 时间复杂度:O(N*logN)// 空间复杂度:O(N)voidMergeSort(int* a,int n){int* tmp =(int*)malloc(sizeof(int)* n);if(tmp ==NULL){printf("malloc fail\n");exit(-1);}_MergeSort(a,0, n -1, tmp);free(tmp);}// 归并排序非递归实现voidMergeSortNonR(int* a,int n){int* tmp =(int*)malloc(sizeof(int)* n);if(tmp ==NULL){printf("malloc fail\n");exit(-1);}int gap =1;while(gap < n){for(int i =0; i < n; i +=2* gap){//[i,i+gap-1][i+gap, i+2*gap-1]int begin1 = i, end1 = i + gap -1, begin2 = i + gap, end2 = i +2* gap -1;//如果第二个小区间不存在,结束本次循环if(begin2 >= n)break;//如果第二个小区间存在,但是不够gap个,结束位置越界了,修正if(end2 >= n)
end2 = n -1;_Merge(a, tmp, begin1, end1, begin2, end2);}
gap *=2;}free(tmp);}//计数排序//时间复杂度:O(N+range)//空间复杂度:O(range)//只适合,一组数据,数据的范围比较集中,那么效率很高,局限性也在这里//并且只适合整数,如果是浮点数、字符串等等就不行了voidCountSort(int* a,int n){int max = a[0], min = a[0];for(int i =0; i < n; i++){if(a[i]> max)
max = a[i];if(a[i]< min)
min = a[i];}int range = max - min +1;int* count =malloc(sizeof(int)* range);memset(count,0,sizeof(int)*range);for(int i =0; i < n; i++){
count[a[i]- min]++;}int i =0;for(int j =0; j < range; j++){while(count[j]--){
a[i++]= j + min;}}free(count);}