经典排序算法代码
来源:互联网 发布:最好看的网络官场小说 编辑:程序博客网 时间:2024/05/29 13:34
1、插入排序
//插入排序void InsertSort(int Nums[],int Length){ for(int i=0;i<Length;i++) { int j,temp=Nums[i]; //将第i个数保存起来 for(j=i-1;Nums[j]>temp&&j>=0;j--) //依次将第i个数与前面的数比较 { Nums[j+1]=Nums[j]; //如果前面的数比第i个数大,则往后移动 } Nums[j+1]=temp; //最后将空出的位置装入上面保存的第i个数 }}
2、希尔排序
//希尔排序void ShellSort(int nums[],int Length){ for(int gap=Length/2;gap>0;gap/=2) { //根据增量gap 进行插入排序 for(int i=gap;i<Length;i+=gap) { if(temp<Nums[j-gap) Nums[j]=Nums[j-gap]; else break; } Nums[j]=temp; }}
上面代码中的gap增量叫做希尔增量,增量的使用对于算法性能有影响,当使用希尔增量时,最坏情形下的运行时间为O(N^2),Hibbard提出一个稍微不同的增量序列1,3,7….,使用Hibbard增量的希尔排序的最坏情形下的运行时间为O(N^(3/2))。
3、堆排序
#include <stdio.h>//这个函数调整对数组中第n个元素的位置void HeapAdjust(int array[],int n,int length){ int Child; for(int i=n;i*2<=length;i=Child) { Child=i*2; if(Child+1<=length&&array[Child]<array[Child+1]) Child++; //如果较大的子节点大于父节点则交换位置 if(array[i]<array[Child]) { int Temp=array[i]; array[i]=array[Child]; array[Child]=Temp; } else { break; } }}void HeapSort(int array[],int length){ //调整前半部分,保证了最大的值都在前半部分 for(int i=length/2;i>0;i--) { HeapAdjust(array,i,length); } for(int i=length-1;i>0;i--) { //将最大的书移动到尾部 int Temp=array[1]; array[1]=array[i+1]; array[i+1]=Temp; //除去尾部后,调整第一个元素位置 HeapAdjust(array,1,i); }}void HeapAdjustLittle(int array[],int num,int length){ //如果输入的数小于这些数,直接返回 if(num<array[1]) { return; } //如果输入的数大于数组中最小的数,则赋值,然后调整堆数组 array[1]=num; intt Child; for(int i=1;i*2<=length;i=Child) { Child=i*2; if(Child+1<=length&&array[Child]>array[Child+1]) Child++; //如果较小的子节点大于父节点则交换位置 if(array[i]>array[Child]) { int Temp=array[i]; array[i]=array[Child]; array[Child]=Temp; } else { break; } }}//打印输出数组内容void PrintArray(int array[],int size){ printf("最大的前%d个数:\n",size); for(int i=0;i<size;i++) { printf("%3d",array[i]); } printf("\n");}int myarray[]={0, 1, 9, 2, 8, 3, 7, 4, 6, 5 , 10};int main(){ //将前十个数进行一次堆排序,并输出结果 HeapSort(myarray,sizeof(myarray)/4-1); PrintArray(myarray+1,sizeof(myarray)/4-1); //输入数字,打印出前十个最大的数 while(1) { int num=0; scanf("%d",&num); HeapAdjustLittle(myarray,num,sizeof(myarray)/4-1); PrintArray(myarray+1,sizeof(myarray)/4-1); } return 0;}
4、归并排序
#include<stdio.h>//合并两个有序数组void Merge(int Array[],int tmpArray[],int left,int mid,int right){ int i=left; int tmpleft=left; int tmpright=mid+1; //比较左右数组元素大小,放入第三个数组中 while(tmpleft<=mid&&tmpright<=right) { if(Array[tmpleft]<Array[tmpright] tmpArray[i++]=Array[tmpleft++]; else tmpArray[i++]=Array[tmpright++]; } //右边数组用完了进入此循环拷贝左边数组到第三个数组 for(;tmpleft<=mid;tmpleft++) { tmpArray[i++]=Array[tmpleft]; } //左边数组用完了进入此循环拷贝右边数组到第三个数组 for(;tmpright<mid;tmpright++) { tmpArray[i++]=Array[tmpright]; } //合并后的数组拷贝回原数组 for(i=left;i<=right;i++) { Array[i]=tmpArray[i]; }}//归并排序void MergeSort(int Array[],int tmpArray[],int left,int right){ //基准条件,如果只有一个元素即为有序数组,直接返回 if(left>=right) return; //递归数组排序左右两边数组 int mid=(left+right)/2; MergeSort(Array,tmpArray,left,mid); MergeSort(Array,tmpArray,mid+1,right); //排序完成后进入合并数组 Merge(Array,tmpArray,left,mid,right);}int main(){ int a[]={1,0,2,9,3,8,4,7,5,6}; int tempa[10]; MergeSort(a,tempa,0,9); for(int i=0;i<10;i++) { printf("%d\n",tempa[i]); } return 0;}
归并排序以最坏情形的运行时间O(NlogN)运行,而所使用的比较次数几乎是最优的。
5、快速排序
快速排序(quicksort)是在实践中最快的一直排序算法,它的平均运行时间是O(NlogN)。该算法之所以特别快,主要是由于非常精炼和高度优化的内部循环。它的最坏情形的性能为O(N^2),但稍加努力就可避免这种情形。通过将堆排序与快速排序结合起来,就可以在堆排序的最坏运行时间下,得到对几乎所有输入的最快运行时间。
#include<stdio.h>//分为两个区,左边的数都比右边的数小//返回值为中间数所在的位置int Partition9int nums[],int left,int right){ int midNum=Nums[right]; //定数组左后一个数为中间数 int j=left; for(int i=left;i<right;i++) //循环比较第i个数和中间数 { if(Nums[i]<midNum) //如果小于中间数,j指针向后移,j指针之前的数都小于中间数 { if(i!=j) { int temp=Nums[i]; Nums[i]=Nums[j]; Nums[j]=temp; } j++; } } //收尾工作,将中间数和j指向的中间位置的数调换 int temp=Nums[j]; Nums[j]=midNum; Nums[right]=temp; return j; //返回中间数的下标}void QuickSort(int Nums[],int left,int right){ if(left<right) { int mid=Partition(Nums,left,right); //分区 QuickSort(Nums,left,mid-1); //左边递归排序 QuickSort(Nums,mid+1,right); //右边递归排序 }}int main(){ int a[]={1,0,2,9,3,8,4,7,5,6}; QuickSort(a,0,9); for(int i=0;i<10;i++) { printf("%d\n",a[i]); } return 0;}
6、计数排序
计数排序的特单是时间复杂度,与其他的排序算法不同,它的时间复杂度为O(N+K),这个时间复杂度表明了当K相对比较大时,不适合使用,比如对集合{1, 0, 100},但是对于N远大于K的情况下,是相当适合的。
#include<stdio.h>#include<stdlib.h>#include<string.h>int data[]={1,2,1,0,4,5};//计数排序参数列表//int d[]为待排序数据列表//int n为待排序数据个数//int min,max为待排序数据中最大和最小值,用来计算待排数据跨度kvoid sort_counter(int d[],int n,int k){ int i,j=0; k++; //实际申请空间比k大1 //申请辅助空间 int* counter=malloc(sizeof(int)*k); memset(counter,0,sizeof(int)*k); //计数 for(i=0;i<n;++i) { ++counter[d[i]]; } //将计数结果保存到待排序数据空间 for(i=0;i<k;++i) { while(counter[i]-->0) { d[j++]=i; } } //释放辅助空间 free(counter);}int main(void){ sort_counter(data,6,5); int i; for(i=0;i<6;++i) { printf("%d\n",data[i]); } return 0;}
7、基数排序
#include<stdio.h>//int data[]={1,100,321,121,333,586,1100};//该函数计算data中最大位数,本例中,最大位数是1100,所以结果是4int maxbit(int data[],int n){ int d=1; //保存最大的位数 int p=10; for(int i=0;i<n;++i) { while(data[i]>=p) { p*=10; ++d; } } return d;}//基数排序void sort_radix(int data[],int n){ int d=maxbit(data,n); //计算位数 int *tmp=new int[n]; //中间变量,用来存储中间排序结果 int *count=new int[10];//计数排序中的计数器 int i,j,k; int radix=1; //根据最大位数进行循环,对每一位进行基数排序 for(i=1;i<=d;i++) { //初始化计数器 for(j=0;j<10;j++) count[j]=0; //对位数进行计数排序 for(j=0;j<n;j++) { k=(data[j]/radix)%10; //注意这里进行取模 count[k]++; } for(j=1;j<10;j++) count[j]=count[j-1]+count[j]; //将排序中间结果保存到tmp for(j=0;j<n;j++) { k=(data[j]/radix)%10; tmp[count[k]-1=data[j]; count[k]--; } //将中间结果保存到data for(j=0;j<n;j++) data[j]=tmp[j]; //取模时的被除数,需要提高一位 radix=radix*10; } delete []tmp; delete []count;}int main(){ int data[]={1,100,321,121,333,586,1100}; sort_radix(data,7); for(int i=0;i<7;i++) { printf("%d\n",data[i]); } return 0;}
基数排序比较适合对取值很大的数进行排序,也可用来对字符串进行排序。但基数排序的缺点是不呈现时空局部性,因为在按位对每个数进行排序的过程中,一个数的位置可能发生巨大的变化,所以不能充分利用现代机器缓存提供的优势。同时计数排序作为中间稳定排序的话,不具有原地排序的特点,当内存容量比较宝贵的时候,还是有待商榷。
0 0
- 经典排序算法代码
- 经典排序算法代码
- 经典排序算法代码集合
- 经典排序算法总结(代码)
- 经典排序算法分析和代码-上篇
- 经典排序算法分析和代码-中篇
- 经典排序算法分析和代码-下篇
- 经典排序算法总结(代码)
- 经典排序算法总结(代码) .
- 经典排序算法原理以及代码
- 经典排序算法代码实现(持续更新... 求补充)
- 经典排序算法的详细分析及C++实现代码
- 8大经典排序算法及其实现代码
- 堆排序 经典代码
- 经典排序算法
- 【经典算法】快速排序
- 【经典算法】堆排序
- 经典排序算法集合
- bzoj 1613 dp
- svn删除已经上传的文件
- 基于DragonBoard 410c的家庭智能环保卫士——(4)A*路径搜索算法
- 高性能开发(1) Redis缓存主从配置详解
- android theme
- 经典排序算法代码
- jQuery的ajax传递时乱码解决
- Oracle用户创建及权限设置
- OGRE1.7.4显示中文字符串细节问题
- Qt字符串分离
- android adb修改build.prop
- hihoCoder 1473 小Ho的强迫症 && qdu 韬韬说蛤蛤蛤(基础gcd)
- POJ2431-Expedition(优先队列 + 贪心)
- 使用Jenkins配置自动化构建