|
|
4 years ago | |
|---|---|---|
| README.md | 4 years ago | |
README.md
Initialcommit
//一、希尔排序 和插入排序的过程相似,相对于插入排序而言,比较较远距离的数据,使得数据移动跨过多个元素,进行一次比较可能会消除多个元素的交换 //最好情况是步长序列只有1,且序列几乎有序,时间复杂度为O(n)。 //希尔本人给出的步长序列,最坏情况时间复杂度是 O(n^2) //希尔排序的时间复杂度与步长序列有关 #include <stdio.h> int main() { int arr[] = {1,5, 2, 7, 6, 4, 9, 8}; int i; for (i = 0; i < 8; i++) { printf("%d ", arr[i]); } printf("\n"); int step; //步长; int key; //保护每一组数据排序时的第二个数据; int j; //该排序过程是多组数据同时进行,并不是一组一组的进行; for (step = 8 / 2; step > 0; step /= 2) { for (i = step; i < 8; i++) { key = arr[i]; //保护数据 for (j = i - step; j >= 0 && arr[j] > key; j -= step) { arr[j + step] = arr[j]; } arr[j + step] = key; //将保护的数据放到合适的位置; } } for (i = 0; i < 8; i++) { printf("%d ", arr[i]); } printf("\n"); return 0; } //结果:1 5 2 7 6 4 9 8 // 1 2 4 5 6 7 8 9
//二、插入排序:最简单常用的方法 //类似于我们打扑克牌的时对手里的牌进行排序的过程,选出一个值,将其插入在合适的排序位置。 //适用于数据量不大,对算法的稳定性有要求,且数据局部或者整体有序的情况。 //时间复杂度为O(n*n). //空间复杂度为O(1); 最好的情况下即当数据有序时可以达到O(n)的时间复杂度 #include<stdio.h> int main() { int a[] = {45,32,56,71,12}; int i,j,temp; printf("未排序前:\n"); for(i=0;i<5;i++) { printf("%d ", a[i]); } printf("\n经过直接插入排序后:\n"); for(i=1;i<5;i++) { temp = a[i]; //当前数小于前一位数时 if(a[i] < a[i-1]) { //将子序列重新排列为有序序列 for(j=i-1;temp<a[j];j--) { a[j+1] = a[j]; } a[j+1] = temp; } } for(i=0;i<5;i++) { printf("%d ", a[i]); } } //结果:未排序前: // 45 32 56 71 12 // 经过直接插入排序后: //12 32 45 56 71
//三、归并排序 时间复杂度为O(nlog),空间复杂度为O(n),其需要借助额外的存储空间,是高级排序算法中,唯一一个稳定的排序算法,当数据量较大时,要注意考虑内存空间的开销。
//原理:如果有两个已经排序好的数组{1,4,6,8},{2,7,9,12}; //我们要把这两个数组合并再排序;目标数组应该是{1,2,4,6,7,8,9,12};
//四、选择排序法(以从小到大排序为例) //算法思想: //A.在未排序序列中找到最小(大)元素,存放到排序序列的起始位置 //B.从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾 //C.以此类推,直到所有元素均排序完毕 #include<stdio.h> int main() { void sort(int a[],int n); int i,a[10];//定义数组营首地址和数组长度 printf("please input the original array:"); for(i=0;i<10;i++) scanf("%d",&a[i]);//输入十个数 sort(a,10);//调用函数sort对这十个数进行排序 for(i=0;i<10;i++) printf("%5d",a[i]);//输出排序后的十个数 printf("\n"); return 0; }
void sort(int a[],int n)//n是指数组长度 { int min,i,j,t; for(i=0;i<n-1;i++)//数组中的前n-1个数(除最后一个数外)都要进行一趟循环 { min=i;//假设此趟循环中的最小值就是当前值i for(j=i+1;j<n;j++)//第i个数要和后面的每个值比较,与i比较的值记作j if(a[min]>a[j])//若后面的数j更小,则 min=j;//记住此时j的下标 t=a[i];a[i]=a[min];a[min]=t;//将a[i]和a[j]交换位置 } }
//五、冒泡排序法(从小到大排序为例) //算法思想: //1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。 //2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后//的元素会是最大的数,然后将该数固定 //3.针对所有的元素重复以上的步骤,除了最后一个。 //4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
#include<stdio.h> int main() { void sort(int a[],int n); int i,a[10];//定义数组营首地址和数组长度 printf("please input the original array:"); for(i=0;i<10;i++) scanf("%d",&a[i]);//输入十个数 sort(a,10);//调用函数sort对这十个数进行排序 for(i=0;i<10;i++) printf("%5d",a[i]);//输出排序后的十个数 printf("\n"); return 0; }
//六、堆排序 //(一)最大堆调整(Heapify):将堆的末端子节点作调整,//使得子节点永远小于父节点 //(二)创建最大堆(CreateHeap):将堆中的所有数据重新//排序 //(三)堆排序(HeapSort):移除位在第一个数据的根节点,//并做最大堆调整的递归运算 时间复杂度及总结 1、堆排序最大的优点就是,在最坏的情况下,时间复杂度仍为 O(n*logn);
2、堆排序只需要存放一个记录的辅助空间,所以堆排序也称原地排序;
3、堆排序是不稳定的;
//七、快速排序 //先从数列中取出一个数作轴值(基准数)pivot; //根据基准数将数列进行分区,小于基准数的放左边,大于基准数的//放右边; //重复分区操作,直到各区间只有一个数为止。 #include<stdio.h> int fast(int* y,int begin,int end) { int temp=y[begin]; //将结尾位置保存一下,因为之后的运算会改变end值,end会逐渐向前移动 //,而最后递归的时候end还得是数组的尾元素,不能发生变化 int endTemp=end; //设定递归条件,左右不可相等(重合)如果相等那就return if(end>begin) { //循环条件,左右不可相等(重合),如果相等,那就一次排序分组完毕,开始将分好的两组数组再递归进行排序 while(begin<end) { //向左移动 while((begin<end)&&(temp<=y[end])) end--; y[begin]=y[end]; //向右移动 while((begin<end)&&(temp>y[begin])) begin++; y[end]=y[begin]; } //基准元素放到中间左右重合的位置上 y[begin]=temp; //分组递归,前一组数组为首元素到 fast(y,0,begin-1); fast(y,begin+1,endTemp); } return 0; } int main() { int y[]={22,12,1,33,17,5,10,89,88,30,21,11,11}; fast(y,0,(sizeof(y)/sizeof(int))-1); for(int i=0;i<sizeof(y)/sizeof(int);i++) printf("%d ",y[i]); return 0; }
1 5 10 11 11 12 17 21 22 30 33 88 89
在最好情况下,快速排序算法的时间复杂度为O(nlogn) 在最坏情况下,待排序的序列为正序或者逆序,每次划分只得到一个臂上次划分少一个记录的子序列,而且另一个序列还为空。如果递归树画出来,它就是一棵斜树。此时需要执行(n-1)次递归调用,且第i次划分需要经过i-1次关键字的比较才能找到第i个记录,即中轴元素的位置,因此比较次数为:n-1+n-2+n-3+…+1 = n*(n-1)/2 时间复杂度为O(n^2) //八、基数排序(以整形为例),将整形10进制按每位拆分,然后从低位到高位依次比较各个位。每次比较完进行排序,直到整个数组有序主要分为两个过程: //(1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中) //(2)收集,再将放置在0~9号桶中的数据按顺序放到数组中重复(1)(2)过程,从个位到最高位,直到排好序为止(比如32位无符号整形最大数4294967296,最高位10位)
#include <stdio.h> #define NUM 10 //数组元素个数
void counting_sort(int a[],int b[],int c[],int atemp[]); int main() { int i; int j;
int a[10] = {326,54,512,13,9,71,92,61,53,19}; //input array int atemp[10]; int b[10]; //output array int c[10]; //temp all element are not biger than 10
// 个位排序 for (i = 0;i < NUM;i++) atemp[i] = a[i] % 10; counting_sort(atemp,b,c,a); for (i = 0;i < NUM;i++) a[i] = b[i];
// 十位排序 for (i = 0;i < NUM;i++) atemp[i] = a[i] / 10 % 10; counting_sort(atemp,b,c,a); for (i = 0;i < NUM;i++) a[i] = b[i]; //百位排序 for (i = 0;i < NUM;i++) atemp[i] = a[i] / 100 % 10; counting_sort(atemp,b,c,a);
for (i = 0;i < NUM;i++) printf(" %d ",b[i]); printf("\n");
} //基数排序算法,a为待排序数组(一位数,要和atemp区分开),b为排序好的数组,c为中间数组,atemp为原始数组(包括三位数) void counting_sort(int a[],int b[],int c[],int atemp[]) { int i,j; for (i = 0;i < NUM;i++) c[i] = 0; for (j = 0;j < NUM;j++) c[a[j]] += 1; for (i = 1;i < NUM;i++) c[i] = c[i] + c[i-1]; for (j = 9;j >= 0;j--) { b[c[a[j]] - 1] = atemp[j]; c[a[j]] -= 1; } }
9 13 19 53 54 61 71 92 326 512