各种排序算法的实现
来源:互联网 发布:sybase数据库用户 编辑:程序博客网 时间:2024/04/19 10:22
数据类型设置
数据存储方式为顺序存储结构,待排序的一组记录存放在地址连续的一组存储单元上
typedef int KeyType; //定义关键字类型为整数类型typedef struct{ KeyType key[MAXSIZE+1]; //key[0]闲置或用作哨兵 int length; //顺序表长度}
插入排序
1.直接插入排序
主要思想:
将一个记录插入到已经排好序的有序表中,得到一个新的、长度加1的有序表
算法:
void InsertSort(SqList &l){ //插入排序 int i,j; for(i=2;i<=l.length;i++) { if(l.key[i]<l.key[i-1]) //待插入关键字l.key[i]比已排好序部分l.key[1...i-1]小时进行插入 { l.key[0]=l.key[i]; //复制哨兵 for(j=i-1;l.key[0]<l.key[j];j--) //记录后移 l.key[j+1]=l.key[j]; l.key[j+1]=l.key[0]; //插入到正确位置 } }}
直接插入排序容易实现,辅助空间只需一个。时间上,最好情况比较次数为n-1,不需要移动。最坏情况比较次数为(n+2)(n-1)/2,移动次数(n+4)(n-1)/2,时间复杂度为O(n²)
2.折半插入排序
主要思想:
插入排序的基本操作为在一个有序表中进行查找和插入,查找利用折半查找实现
算法:
void BInsertSort(SqList &l){ //折半插入排序 int i,j,low,high,mid; for(i=2;i<=l.length;i++) { l.key[0]=l.key[i]; //l.keyp[i]暂存到l.key[0] low=1; high=i-1; while(low<=high) //折半查找有序插入的位置 { mid=(low+high)/2; if(l.key[0]<l.key[mid]) high=mid-1; else low=mid+1; } for(j=i-1;j>=high+1;j--) //记录后移 l.key[j+1]=l.key[j]; l.key[high+1]=l.key[0]; //插入 }}
折半插入排序辅助空间和直接插入排序形同。时间上,折半排序减少了比较次数,记录移动次数不变,时间复杂度为O(n²)
3.希尔排序
主要思想:
将整个待排序列分割成若干个子序列分别进行直接插入排序,等到整个序列整体有序时,再对全体记录进行一次直接插入排序
算法:
void ShellSort(SqList &l,int dlta[],int t){ //希尔排序 int i,j,k; for(k=0;k<t;k++) //增量序列中的值没有除1之外的公因子 { //最后一个增量值必须为1 int dk=dlta[k]; for(i=dk+1;i<=l.length;i++) { if(l.key[i]<l.key[i-dk]) //将l.key[i]插入有序增量子表,此过程为直接插入排序 { l.key[0]=l.key[i]; //l.key[0]暂存数据 for(j=i-dk;j>0&&l.key[0]<l.key[j];j-=dk) l.key[j+dk]=l.key[j]; l.key[j+dk]=l.key[0]; } } }}
希尔排序时间效率较前两种排序方法有较大进步,时间跟所取的增量序列有关,增量序列中的的值没有除1之外的公因子,且最后一个增量值必须为1
交换排序
1.冒泡排序
主要思想:
第一趟,将关键字最大的记录安置在最后一个记录位置上;第二趟排序,将前n-1个记录中关键字最大的记录安置在第n-1个位置;以此类推
整个排序要进行k(1≤k≤n-1),当一趟排序中没有进行交换记录的操作时结束排序
算法:
void BubbleSort(SqList &l){ //冒泡排序 int i,j,temp,flag=1; for(i=1;flag==1;i++) //当在一趟排序中没有进行交换记录的操作时结束排序 { flag=0; for(j=1;j<=l.length-i;j++) { if(l.key[j]>l.key[j+1]) { temp=l.key[j+1]; l.key[j+1]=l.key[j]; l.key[j]=temp; flag=1; } } }}
冒泡排序借助交换进行排序,辅助空间只需一个。时间上,最好情况进行n-1比较,不移动记录,最坏情况需要进行n-1趟排序,要进行n(n-1)/2次比较,时间复杂度为O(n²)
2.快速排序
主要思想:
取一个记录作为枢纽,通过一趟排序将待排记录分割成独立的两部分,一部分记录关键字记录小于枢纽记录,另一部分记录大于枢纽记录,继续对两部分记录进行排序算法:
void QuickSort(SqList &l,int low,int high){ //快速排序 if(low<high) { int pivotloc=Partition(l,low,high); //找出枢纽,将l.key[low...high]一分为二 QuickSort(l,low,pivotloc-1); //对低子表递归排序 QuickSort(l,pivotloc+1,high); //对高子表递归排序 }}int Partition(SqList &l,int low,int high){ //将枢纽移至正确位置 int pivotkey=l.key[low]; //用第一个记录作为枢纽记录 l.key[0]=l.key[low]; //记录枢纽关键字 while(low<high) //从表的两端向中间扫描 { while(low<high&&l.key[high]>=pivotkey) high--; l.key[low]=l.key[high]; //将比枢纽记录小的记录移到低端 while(low<high&&l.key[low]<=pivotkey) low++; l.key[high]=l.key[low]; //将比枢纽记录大的记录移到高端 } l.key[low]=l.key[0]; return low; //返回枢纽位置}
快速排序需要一个栈空间实现递归。时间上,快速排序平均时间复杂度为O(nlogn),平均性能最好,但不稳定当序列基本有序时,蜕化为冒泡排序,时间复杂度为O(n²)
选择排序
1.简单选择排序
主要思想:
通过n-i次关键字间的比较,从n-i+1个记录中选择出关键字最小的记录,并和第i个记录交换算法:
void SelectSort(SqList &l){ //简单选择排序 int i,j,temp,k; for(i=1;i<=l.length;i++) { temp=l.key[i]; k=i; for(j=i;j<=l.length;j++) //选择第i小的记录 { if(temp>l.key[j]) { temp=l.key[j]; k=j; } } if(k!=i) { l.key[k]=l.key[i]; l.key[i]=temp; } }}简单选择排序辅助空间只需一个。时间上,比较次数为n(n-1)/2,移动次数为0-3(n-1),时间复杂度为O(n²)
2.堆排序
归并排序
主要思想:
将数组中前后相邻的两个有序序列归并为一个有序序列
算法:
void MergeSort(SqList l1,SqList &l2,int s,int t){ //归并排序 //将l1.key[s...t]归并排序为l2.key[s...t] if(s==t) l2.key[s]==l1.key[s]; else { int m=(s+t)/2; MergeSort(l1,l1,s,m); //递归将l1.key[s..m]归并为有序 MergeSort(l1,l1,m+1,t); //递归将l1.key[m+1..t]归并有序 Merge(l1,l2,s,m,t); //将l1.key[s..m]和l1.key[m+1..t]归并到l2[s..t] }}void Merge(SqList l1,SqList &l2,int i,int m,int n){ //将有序的l1.key[i...m]和l1.key[m+1...n]归并为有序的l2.key[i..n] int j,k; for(j=m+1,k=i;i<=m&&j<=n;k++) { if(l1.key[i]<l1.key[j]) l2.key[k]=l1.key[i++]; else l2.key[k]=l1.key[j++]; } if(i<=m) while(i<=m) l2.key[k++]=l1.key[i++]; if(j<=n) while(j<=n) l2.key[k++]=l1.key[j++];}归并排序是一种稳点的排序方法,辅助空间需要n个,时间复杂度为O(nlogn)
基数排序
1.简单选择排序
主要思想:
借助多关键字排序的思想对单逻辑关键字进行排序
算法:
typedef struct LNode{ KeyType data; struct LNode *next;}LNode,*LinkList;void RadixSort(SqList &l){ //基数排序 LinkList ll[10]; for(int i=0;i<10;i++) //构造静态链表 { ll[i]=(LinkList)malloc(sizeof(LNode)); ll[i]->data=0; ll[i]->next=NULL; } for(int i=1;i<=MAX_NUM_OF_KEY;i++) //按最低位优先依次对各关键字进行分配和收集 { //MAX_NUM_OF_KEY为关键字的最大位数 Distribute(l,ll,i); //第i趟分配 Collect(l,ll); //第i趟收集 }}void Distribute(SqList l,LinkList *ll,int i){ int j,k; int a[l.length+1]; for(j=1;j<=l.length;j++) //求各关键字的第i位上的值 { ll[j-1]->data=0; //每趟分配中,初始化链表长度 a[j]=l.key[j]; for(k=1;k<=i;k++) { a[j]=a[j]/10; } a[j]=a[j]%10; } for(j=1;j<=l.length;j++) //映射到链表中 { LinkList node; node=(LinkList)malloc(sizeof(LNode)); node->data=l.key[j]; node->next=NULL; int num=0; LinkList p=ll[a[j]]; while(num++<(ll[a[j]]->data)) p=p->next; p->next=node; ll[a[j]]->data++; //链表头结点记录链表的长度 }}void Collect(SqList &l,LinkList *ll){ int i,num,k; for(i=0,k=1;i<10;i++) //将各链表连接起来 { LinkList p=ll[i]; num=0; while(num<ll[i]->data) { p=p->next; l.key[k++]=p->data; num++; } }}基数排序的辅助空间需要rd个,r为基数值,d为关键字位数。时间上,每一趟分配时间复杂度为O(n),每一趟收集时间复杂度为O(rd),时间复杂为O(d(n+rd))
各种内部排序方法的比较
参考书目:数据结构(C语言版) 严蔚敏
图片来源于网络
- 各种排序算法的实现
- 各种排序算法的实现
- 各种排序算法的实现
- 各种排序算法的实现
- 各种排序算法的实现
- 各种排序算法的实现
- 各种排序算法的实现
- 各种排序算法的实现
- 各种排序算法实现
- 各种排序算法实现
- 各种排序算法实现
- 各种排序算法的java实现
- 各种排序算法的C实现
- 各种排序算法的C实现(转载)
- 各种排序算法的具体实现
- 各种常见的排序算法及其实现
- 各种常见的排序算法及其实现 .
- 各种内排序算法的C++实现
- C++ primer知识点整理
- 好文linux地址
- 随便看看之shell 学习
- 生成N个不相等的随机数
- 关于搭建restful web service + springMVC + ibatis/hibernate的整合和XML配置意思和ssh+springMVC框架搭建
- 各种排序算法的实现
- ios 简单的plist文件读写操作(Document和NSUserDefaults)
- C语言如何判断一个数是否为素数
- 加长宝马:为后座的主人牺牲了什么?
- 只出现一次的字符
- 关于Android MVC结构
- matlab RGB图转灰度图
- 华为机试——基础语法查缺补漏
- POJ 2377 Bad Cowtractors