数据结构:排序算法总结
来源:互联网 发布:windows怎么连接wifi 编辑:程序博客网 时间:2024/05/22 05:32
排序方式
排序的稳定性:假设
内排序和外排序:内排序是在排序整个过程中,待排序的所有记录全部被放置在内存中。外排序是由于排序的记录个数太多,不能同时放置在内存,整个排序过程需要在内外存之间多次交换数据才能进行。
影响内排序的3个方面:
1,时间性能:时间开销主要在于(比较和移动)
2,辅助空间:除了存放待排序所占用的存储空间之外,执行算法所 需要的其他存储空间
3,算法的复杂性:算法本身的复杂度(非时间复杂度)
按算法复杂度分类:
简单算法:冒泡排序,简单选择排序,直接插入排序
改进算法:希尔排序,堆排序,归并排序,快速排序
代码实现:
冒泡排序实现
void Bubblesort1(SqList *L){ int i,j; for(i=1;i<L->length;i++) for(j=L->length-1;j>=i;j--) { if(L->r[j]>L->r[j+1]) { swap(L,j,j+1); } }}
改进的冒泡排序
void Bubblesort2(SqList *L){ int i,j; bool flag=true; for(i=1;i<L->length && flag;i++) for(j=L->length-1;j>=i;j--) { flag=false; if(L->r[j]>L->r[j+1]) { swap(L,j,j+1); flag=true; } }}
简单选择排序
在n-i+1个记录中选取关键字最小的记录作为有序序列的第i个记录。
void SelectSort(SqList *L){ int i,j,min; for(i=1;i<L->length;i++) { min=i; for(j=i+1;j<=L->length;j++) { if(L->r[min]>L->r[j]) min=j; } if(i!=min) swap(L,i,min); }}
直接插入排序
将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增1的有序表。
void InsertSort(SqList *L){ int i,j; for(i=2;i<=L->length;i++) { if(L->r[i]<L->r[i-1]) { L->r[0]=L->r[i]; for(j=i-1;L->r[j]>L->r[0];j--) { L->r[j+1]=L->r[j]; } L->r[j+1]=L->r[0]; } }}
希尔排序
将原本有大量记录数的记录进行分组,分割成若干个子序列,此时每个子序列待排序的记录个数就比较少了,然后在这些子序列内分别进行直接插入排序,当整个序列都基本有序时(只是基本有序时),再对全体记录进行一次直接插入排序
void ShellSort(SqList *L){ int i,j; int increment=L->length; do { increment=increment/3+1; for(i=increment+1;i<=L->length;i++) { if(L->r[i]<L->r[i-increment]) { L->r[0]=L->r[i]; for(j=i-increment;j>0 && L->r[0]<L->r[i];j-=increment) L->r[j+increment]=L->r[j]; L->r[j+increment]=L->r[0]; } } } while(increment>1);}
根据代码可知,划分间隔为increment,每隔increment的数进行大小比较排序,排序完成后,increment取之前的三分之一,直到increment不满足大于1的条件(由increment=increment/3+1 可以保证增量序列最后一个增量值为1),循环结束。
在这里增量的选择对排序效率有极大影响,大量研究表明,较好的增量序列为:
堆排序
即对简单选择排序进行的一种改进,利用堆进行排序的方法
此处堆是具有以下性质的完全二叉树:
每个结点的值都小于或等于其左右孩子结点的值,称为大顶堆
90 / \ 70 80 / \ / \ 60 10 40 50 / \ 30 20
或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆
10 / \ 20 70 / \ / \ 30 50 90 80 / \ 60 40
以层次遍历的方式给结点从1开始编号,则有
或
其中
在大顶堆的情况下,此时,整个序列的最大值就是堆顶的根节点,将它移走(末尾元素放到根节点处),再将剩余元素重新构造一个大顶堆,一次循环,可以得到一个有序序列。
代码实现:
void HeapSort(SqList *L){ int i; for(i=L->length/2;i>1;i--) HeapAdjust(L.i.L->length); //把L中的r构建成一个大顶堆 for(i=L->length;i>1;i--) { swap(L,1,i);//将堆顶记录和当前未经排序子序列的最后一个记录交换 HeapAdjust(L,1,i-1);//将L->r[1..i-1]重新调整为大顶堆 }}
前一个循环是构建一个大顶堆,后一个循环是,把根节点(即最大的值和尾元素互换,然后1至i-1个元素重新构建大顶堆,第i个为最大值)依次循环,最终得到由小到大的有序表
void HeapAdjust(SqList *L,int s,int m){ int temp,j; temp=L->r[s]; for(j=2*s;j<=m;j*=2) { if(j<m && L->r[j]<L->r[j+1]) ++j; if(temp>=L->r[j]) break; L->r[s]=L->r[j]; s=j; } L->r[s]=temp;}
时间复杂度分析:他的运行时间主要是消耗在初始构建堆和在重建堆时的反复筛选上,。构建堆得时间复杂度为O(n),正式排序时,第i次堆顶记录重建堆时间复杂度均为O(
归并排序
归并排序原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2] ([x]表示不小于x的最小整数)个长度为2或1的有序子序列;再两两归并,… …,如此重复,直到得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。
代码实现
首先采用递归的方法实现:
void Merge( int SR[],int TR[],s,m,t){ int i=s.j=m+1; int count=s; while(i<m+1&&j<t+1) { if(SR[i]<SR[j]) TR[count++]=SR[i++]; else TR[count++]=SR[j++]; } if(i<m+1) while(i<m+1) TR[count++]=SR[i++]; if(j<t+1) while(j<t+1) TR[count++]=SR[j++];}//将SR[s...t]归并排序为TR1[s...t]void MSort(int SR[],int TR1[],int s,int t){ int m; int TR2[MAXSIZE+1];//临时排序空间 if(s==t) TR1[s]=SR[s]; else { m=(s+t)/2; MSort(SR,TR2,s,m); MSort(SR,TR2,m+1,t); Merge(TR2,TR1,s,m,t); }}void MergeSort(SqList *L){ MSort(L->r,L->r,1,L->length);}
非递归的算法实现,采用迭代的方法:
void
快速排序
快速排序的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
代码实现:
//交换顺序表L中子表的记录,使枢轴记录到位,并返回其所在位置//此时在它之前(后)的记录均不大(小)于它int Partition(SqList *L,int low,int high){ int pivotkey ; pivotkey=L->[low]; while(low<high) { while(low<high && L->r[high]>=pivotkey) high--; swap(L,low,high); while(low<high && L->r[low]<=pivotkey) low++; swap(L,low,high); } return low;}//对顺序表L中的子序列L->r[low...high]做快速排序void QSort(SqList *L,int low,int high){ int pivot; if(low<high) { pivot=Partition(L,low,high); QSort(L,low,pivot-1); QSort(L,pivot+1,high); }}//对顺序表L做快速排序void QuickSort(SqList *L){ QSort(L,1,L->length);}
基数排序
基数排序:
希尔排序相当于直接插入排序的升级,同属于插入排序类
堆排序相当于简单选择排序的升级,同属于选择排序类
快速排序相当于冒泡排序的升级,同属于交换排序类
reference:《大话数据结构》
- 数据结构排序算法总结
- 数据结构排序算法总结
- 数据结构排序算法总结
- 数据结构排序算法总结
- 数据结构排序算法总结
- 数据结构:排序算法总结
- 【数据结构】排序算法总结
- 数据结构排序算法总结
- 数据结构:排序算法总结
- 数据结构排序算法总结
- 数据结构---排序算法总结
- 数据结构--排序算法总结
- 数据结构-排序算法总结
- 数据结构各种排序算法总结
- 数据结构各种排序算法总结
- 数据结构算法总结-内排序
- 数据结构-八大排序算法总结
- 数据结构-各类排序算法总结
- myselipse中创建web projects
- linux获取时间函数介绍
- 有关蛇形填数的问题
- iOS-获取当前View所在的控制器
- 学习Javascript闭包(Closure)
- 数据结构:排序算法总结
- <响应式布局>1---响应式布局介绍
- WEB前端开发书籍推荐
- Linux线程的前世今生
- ui-router搭建的angularjs模板
- Springmvc中视图向控制器传输参数的一种方法
- 大白话解析模拟退火算法
- (二)一个简单的加数算法
- 什么是回调函数?如何运用?