排序总结:堆排序、快速排序、归并排序、基数排序
2016-08-06 14:30
363 查看
排序算法按照不同的方式可以进行不同的分类:分为内部排序和外部排序;稳定性排序和不稳定性排序。
我们常用的简单排序方法(选择、交换、插入),尽管非常容易理解和实现,但是它们的效率不高,这点在数据量较大时尤为明显。
本文将简绍一些更高效的排序模式(堆排序、快速排序、归并排序、基数排序)的算法和实现,主要用于本人近期学习的总结,各位不喜勿喷
堆排序
算法总结:堆,是一棵完全二叉树,其中每个节点的数据项大于或等于其子树的数据项。我们用堆实现排序,实际上就是利用树形结构查找方便的优势,这种排序方法已经在STL中实现,对应函数名分别是make_heap、push_heap、pop_heap、sort_heap。对于最大堆,堆的根实际上就是堆中所有元素的最大值,将根元素以堆最后一个元素交换,再经过调整堆中剩余元素,找出剩余元素中的最大值,这实际上是一种选择排序法的思想:通过对调整找到元素中的最大值,然后放到尾部。
实现代码:
快速排序
算法总结:在冒泡排序法中,把一个元素移动到它的正确位置,需要许多次与相邻元素交换,往往很多交换都不是必须的。作为改进,快速排序法每次找到元素的正确位置,并交换,而且采用分治策略,将数据分成两部分。更贴切第讲:每次选定一个元素,将数据分成大于和小于等于该元素的两部分,再对两部分进一步快速排序。
实现代码:
归并排序
算法总结:我们常用的归并实际上是折半归并排序,它也是采用了分治策略,将要排序的序列均分成两份,每一份分别进行归并排序后,再将排序的两个序列合并在一起,形成有序的整体序列。
实现代码:
基数排序
算法总结:基数排序一种独特的排序方式,它是建立的数字的表示方式上的,基本思想:对一组数,先对各位排序,再对十位排序,百位...。这样,对于十进制的数,可以定义是个容器,该过程就可以描述成:分别按由低到高为放入容器,取出容器。
实现代码:
我们常用的简单排序方法(选择、交换、插入),尽管非常容易理解和实现,但是它们的效率不高,这点在数据量较大时尤为明显。
本文将简绍一些更高效的排序模式(堆排序、快速排序、归并排序、基数排序)的算法和实现,主要用于本人近期学习的总结,各位不喜勿喷
算法总结:堆,是一棵完全二叉树,其中每个节点的数据项大于或等于其子树的数据项。我们用堆实现排序,实际上就是利用树形结构查找方便的优势,这种排序方法已经在STL中实现,对应函数名分别是make_heap、push_heap、pop_heap、sort_heap。对于最大堆,堆的根实际上就是堆中所有元素的最大值,将根元素以堆最后一个元素交换,再经过调整堆中剩余元素,找出剩余元素中的最大值,这实际上是一种选择排序法的思想:通过对调整找到元素中的最大值,然后放到尾部。
实现代码:
#include <iostream> #include <cstdlib> #include <ctime> #include <algorithm> #include <iterator> int * rand_seq(int num) { int *tem=new int[num]; srand((unsigned)time(NULL)); for(int i=0;i<num;i++) tem[i]=rand()%100; return tem; } void print(int *data,int num) { std::copy(data,data+num,std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; } //下调第i个元素,保证以i元素为根的堆结构 void adjust_heap(int *data, int i, int num) { if(i<num) { //左右子树索引 int left=2*i+1; int right=2*i+2; //找到i,left,right中最大数的索引 //当然还要确保索引值有效 int index= (left<num&&data[left]>data[i])? ((right<num&&data[right]>data[left])?right:left): ((right<num&&data[right]>data[i])?right:i); //交换 if(i!=index) { std::swap(data[i],data[index]); adjust_heap(data,index,num); } } } //将无序的数据元素重建成堆 void build_heap(int *data, int num) { int tree_index=(num-1)/2;//最后一个非叶子节点 for(int i=tree_index;i>=0;i--) adjust_heap(data,i,num); } void heap_sort(int *data, int num) { if(num>1) { build_heap(data,num); do { std::swap(data[0],data[--num]); adjust_heap(data,0,num); }while(num>1); } } int main(int argc, char** argv) { int *data=rand_seq(20); print(data,20); heap_sort(data,20); print(data,20); delete[] data; return 0; }
算法总结:在冒泡排序法中,把一个元素移动到它的正确位置,需要许多次与相邻元素交换,往往很多交换都不是必须的。作为改进,快速排序法每次找到元素的正确位置,并交换,而且采用分治策略,将数据分成两部分。更贴切第讲:每次选定一个元素,将数据分成大于和小于等于该元素的两部分,再对两部分进一步快速排序。
实现代码:
#include <iostream> #include <cstdlib> #include <ctime> #include <algorithm> #include <iterator> int * rand_seq(int num) { int *tem=new int[num]; srand((unsigned)time(NULL)); for(int i=0;i<num;i++) tem[i]=rand()%100; return tem; } void print(int *data,int num) { std::copy(data,data+num,std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; } //start、end分别是排序的起始索引 void quick_sort(int *data,int start,int end) { if(start<end)//迭代终止条件start==end { int tem=data[start];//临时变量 int left=start; int right=end; while(left<right) { //找得到小于等于tem的数,由于tem=data[start],所以不会越界 while(data[right]>tem) --right; while(left<right&&data[left]<=tem) ++left;//找到大于tem的数 if(left<right) std::swap(data[left],data[right]); } if(data[right]<tem)std::swap(data[right],data[start]); quick_sort(data,start,right-1); quick_sort(data,right+1,end); } } int main(int argc, char** argv) { int *data=rand_seq(20); print(data,20); quick_sort(data,0,19); print(data,20); delete[] data; return 0; }
算法总结:我们常用的归并实际上是折半归并排序,它也是采用了分治策略,将要排序的序列均分成两份,每一份分别进行归并排序后,再将排序的两个序列合并在一起,形成有序的整体序列。
实现代码:
#include <iostream> #include <cstdlib> #include <ctime> #include <algorithm> #include <iterator> #include <climits> int * rand_seq(int num) { int *tem=new int[num]; srand((unsigned)time(NULL)); for(int i=0;i<num;i++) tem[i]=rand()%100; return tem; } void print(int *data,int num) { std::copy(data,data+num,std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; } void merge(int *data,int start,int mid,int end) { int *left=new int[mid-start+2];//需要用到额外空间 int *right=new int[end-mid+1]; for(int i=0;i<mid-start+1;i++) left[i]=data[start+i]; left[mid-start+1]=/*~(1<<31)*/INT_MAX; for(int i=0;i<end-mid;i++) right[i]=data[mid+1+i]; right[end-mid]=/*~(1<<31)*/INT_MAX; int i=0; int j=0; while(start<=end)//注意合并已序序列的过程 { if(left[i]<right[j]) data[start++]=left[i++]; else data[start++]=right[j++]; } delete[] left; delete[] right; } void merge_sort(int *data,int start,int end) { if(start<end) { int mid=(start+end)/2; merge_sort(data,start,mid);//分别归并排序 merge_sort(data,mid+1,end); merge(data,start,mid,end);//合并已序序列 } } int main(int argc, char** argv) { int *data=rand_seq(20); print(data,20); merge_so 4000 rt(data,0,19); print(data,20); delete[] data; return 0; }
算法总结:基数排序一种独特的排序方式,它是建立的数字的表示方式上的,基本思想:对一组数,先对各位排序,再对十位排序,百位...。这样,对于十进制的数,可以定义是个容器,该过程就可以描述成:分别按由低到高为放入容器,取出容器。
实现代码:
#include <iostream> #include <cstdlib> #include <ctime> #include <algorithm> #include <iterator> int * rand_seq(int num) { int *tem=new int[num]; srand((unsigned)time(NULL)); for(int i=0;i<num;i++) tem[i]=rand()%100; return tem; } void print(int *data,int num) { std::copy(data,data+num,std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; } //数据data的pos位上的数 int pos_num(int data,int pos) { int tem=1; for(int i=1;i<pos;i++) tem*=10; return (data/tem)%10; } //容器类型 struct container { int num; int *data; }; void radix_sort(int *data,int num) { container con[10]; for(int i=0;i<10;i++)//清空容器 { con[i].data=new int[num]; con[i].num=0; } for(int k=1;k<=2;k++)//每一位分别处理 { for(int i=0;i<num;i++)//装入容器 { int pos=pos_num(data[i],k); con[pos].data[con[pos].num++]=data[i]; } //清空容器 int tem=0; for(int i=0;i<10;i++) { int con_data_num=con[i].num; for(int j=0;j<con_data_num;j++) data[tem++]=con[i].data[j]; con[i].num=0; } } } int main(int argc, char** argv) { int *data=rand_seq(20); print(data,20); radix_sort(data,20); print(data,20); delete[] data; return 0; }
相关文章推荐
- 【Java】快速排序、归并排序、堆排序、基数排序实现总结
- 七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)
- 排序总结:插入(简单和改进)、希尔、选择、冒泡、快速、堆排序、归并排序
- 数据结构与算法从零开始系列:冒泡排序、选择排序、插入排序、希尔排序、堆排序、快速排序、归并排序、基数排序
- 笔试面试最常涉及到的12种排序算法(包括插入排序、二分插入排序、希尔排序、选择排序、冒泡排序、鸡尾酒排序、快速排序、堆排序、归并排序、桶排序、计数排序和基数排序)进行了详解。每一种算法都有基本介绍、算
- 七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)
- 常用排序算法C++实现(堆排序,快速排序,归并排序,基数排序)
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法, 冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
- 八大排序算法:简单插入排序、冒泡排序、希尔排序、快速排序、堆排序、归并排序等总结。
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
- 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 六、内部排序综合(九种)—插入类排序(直接插入、折半插入、希尔排序);交换类排序(冒泡、快速);选择类排序(简单选择、堆排序);二路归并排序;基数排序
- 各种排序算法总结----基数排序、归并排序、插入排序、冒泡排序、选择排序、快速排序、堆排序、希尔排序
- 七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)
- 几种常见的排序算法,选择排序,冒泡排序,希尔排序,堆排序,快速排序,归并排序,基数排序的比较
- 面试珠玑 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)
- 排序方法了解一下(冒泡排序、选择排序、堆排序、插入排序、希尔排序、归并排序、快速排序、基数排序)
- 归并排序,堆排序,基数排序,希尔排序,快速排序,交换排序,选择排序和插入排序的总结和比较
- 七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)