希尔排序堆排序和基数排序
来源:互联网 发布:淘宝会员名有什么用处 编辑:程序博客网 时间:2024/05/16 05:46
希尔排序又称缩小增量排序,它是对直接插入排序方法的一种改进。希尔排序是不稳定的排序,时间复杂度小于O(n^2) 优于直接插入排序,空间复杂度O(1)
希尔排序又称缩小增量排序,它是对直接插入排序方法的一种改进 希尔排序的基本思想:对与含有n个元素的序列,取初始增量dk<n;将待排序序列按下标的初始增量进行分组分成dK个组,在各组内进行直接插入排序;然后缩小增量重复分组和排序的操作,直到增量缩小为1,将n元素放在同一组中进行插入排序为止;
//希尔排序 又称缩小增量排序,它是对直接插入排序方法的改进void ShellSort(int *a,int n){ int dk=n/2;//初始增量dk<n 一般取n/2while(dk>0)//最后一次循环dk=1 增量缩小为1,将n元素放在同一组中进行插入排序为止;{ for(int i=dk;i<n;i++){ if(a[i]<a[i-dk]){ int temp=a[i];//备份带插入元素 挖坑int j;for(j=i-dk;j>=0&&a[j]>temp;j=j-dk)//每组按增量往前搜索合适的插入位置{ a[j+dk]=a[j];//元素按增量后移}a[j+dk]=temp;//填数}}dk=dk/2;//缩小增量}}
1.堆
堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]
即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。
堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的
堆排序是利用堆的性质进行的一种选择排序
原理:利用大根堆或小根堆思想,首先建立堆,然后将堆首与堆尾交换,堆尾之后为有序区。
要点:建堆、交换、调整堆
以大顶堆排序为例:
堆排序中的堆结构其实是完全二叉树 堆排序的基本思想:将含有n个元素的序列data[0...n-1]按堆的性质建立初始堆,初始状态整个堆为无序区,
然后将堆顶元素和无序区的最后一个元素交换,交换后将原先无序区中最后一个元素的归到有序区中,形成新的无序区data[0...n-2]和有序区data[n-1] 然后将新的无序区调整为大顶堆,重复之前的交换和调整堆的步骤直到无序区只有一个元素为止堆排序的三个步骤:1建立初始堆,2交换堆顶元素和无序区最后一个元素的值,3调整堆
堆排序中的堆结构其实是完全二叉树对于含有n个元素的数组 data[0],data[1],...,data[n-1] 堆的性质满足 data[i]>=data[2*i+1]&&data[i]>=[2*i+2] 或 data[i]<=data[2*i+1]&&data[i]<=[2*i+2]
建立初始堆的过程:建立初始堆是是从第一个非叶子结点开始调整的。建立初始堆 即把data[0...n-1]中的n个元素调整为大顶堆 建初始堆时,data[n/2]...data[n-1]为叶子结点已经满足堆的性质了所以一开始从第一个非叶子结点data[n/2-1]开始调整
对于含有n个元素的数组 data[0],data[1],...,data[n-1] 从后往前第一个非叶子结点为data[n/2-1];
调整堆的过程:调整堆时将父节点与其子节点中的较大者进行比较下标索引为s的父节点,对于数组来讲,其子结点的第一个结点为2*s+1,第二个结点为2*s+2;
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;//希尔排序 又称缩小增量排序,它是对直接插入排序方法的改进void ShellSort(int *a,int n){ int dk=n/2;//初始增量dk<n 一般取n/2while(dk>0)//最后一次循环dk=1 增量缩小为1,将n元素放在同一组中进行插入排序为止;{ for(int i=dk;i<n;i++){ if(a[i]<a[i-dk]){ int temp=a[i];//备份带插入元素 挖坑int j;for(j=i-dk;j>=0&&a[j]>temp;j=j-dk)//每组按增量往前搜索合适的插入位置{ a[j+dk]=a[j];//元素按增量后移}a[j+dk]=temp;//填数}}dk=dk/2;//缩小增量}}void swap(int &a,int &b){ a=a+b;b=a-b;a=a-b;}//堆排序 在data[s...m]构成的序列中除了 data[s] 外其余元素均满足堆的定义//调整元素data[s] 的位置,使data[s...m] 称为一个大根堆//对于含有n个元素的序列 k1,k2...kn-1,kn, 堆的性质满足 ki>=k2*i&&ki>=k2*i+1 或 ki<=k2*i&&ki>=k2*i+1 //对于含有n个元素的数组 data[0],data[1],...,data[n-1] 堆的性质满足 data[i]>=data[2*i+1]&&data[i]>=[2*i+2] 或 data[i]<=data[2*i+1]&&data[i]<=[2*i+2]//对于含有n个元素的数组 data[0],data[1],...,data[n-1] 从后往前第一个非叶子结点为data[n/2-1]; void HeapAdjust(int *data,int s,int m){int temp=data[s];//保存data[s]值,在找到适当的位置后再插入for(int j=2*s+1;j<=m;j=2*j+1)//标号为j的父结点的左孩子结点为2*j+1,右孩子 结点为2*j+2 初始化时j第一次指向了data[s],左孩子结点{ if(j+1<=m&&(data[j]<data[j+1])){ j++;//让j 是左右孩子结点中的较大者}if(temp>=data[j])//如果待调整的结点已经大于它左右孩子的最大者了则跳出循环,注意此处是 temp>=data[j]{ break;}data[s]=data[j];s=j;//继续向下调整}data[s]=temp;}void HeapSort(int *data,int n){ int i=0; for(i=n/2-1;i>=0;i--)//此循环为建立初始堆 即把data[0...n-1]中的n个元素调整为大顶堆 建初始堆时,data[n/2]...data[n-1]为叶子结点已经满足堆的性质了所以一开始从第一个非叶子结点data[n/2-1]开始调整 { HeapAdjust(data,i,n-1);//从第一个非叶子结点开始调整 } for(i=n-1;i>0;--i) { // swap(data[0],data[i]);//将堆顶元素和无序区的最后一个元素data[i]交换 int temp=data[0]; data[0]=data[i]; data[i]=temp; HeapAdjust(data,0,i-1);//将无序区从新调整为大顶堆 }}int main(){int a[]={1,1,1,434342,3,6,12,43,56,7,9,0,32787,3,4545};int length=sizeof(a)/sizeof(a[0]);HeapSort(a,length);ShellSort(a,length);for(int i=0;i<length;i++){ cout<<a[i]<<" ";}cout<<endl; return 0;}
一. 算法描述
#include<iostream>#include<cstdio>#include<cstdlib>#include<queue>using namespace std;/******************************************************** *函数名称:GetNumInPos *参数说明:num 一个整形数据 * pos 表示要获得的整形的第pos位数据 *说明: 找到num的从低到高的第pos位的数据 *********************************************************/ int GetNumInPos(int num,int pos) //找到num的从低到高的第pos位的数据 即可以得到装入的桶号{ int temp = 1; for (int i = 0; i < pos - 1; i++) temp *= 10; return (num / temp) % 10; } int NumberOfBit(int number)//判读一个十进制整形数是多少位 如23为2位 则返回2{ int count=0;while(number){ count++; number=number/10;}return count;}void RadixSort(int *a,int length){ if(a==NULL||length<=0){ return ;} int maxValue=a[0];//for(int i=1;i<length;i++)//找待排序数组中元素的最大值{ if(maxValue<a[i]) { maxValue=a[i]; }}int maxBit=NumberOfBit(maxValue);queue<int> Queue[10];//用Queue[0]....Queue[9] 九个队列来表示桶int pos=1;//pos范围为1到maxBit 表示从第一位开始 一直到待排序数组中元素的最高位while(maxBit--)//当待排序数组中元素的最大值的位数为maxBit 时,需要进行maxBit次的分配和收集操作{ for(int i=0;i<length;i++){ int index=GetNumInPos(a[i],pos); //根据元素第pos位数值将元素分配到相应的桶号中 即分配操作Queue[index].push(a[i]);}int j=0;//数组下标索引for(int i=0;i<length;i++)//改变此处for(int i=9;i>=0;i--)变为从大大小排列{ while(!Queue[i].empty()){ a[j++]=Queue[i].front();//根据桶号顺序的收集数组元素 收集操作Queue[i].pop();}}pos++;//开始 分配下一位}}int main(){int a[]={1,2,3,43,545,323,3,5,77666,};int length=sizeof(a)/sizeof(a[0]);RadixSort(a,length);for(int i=0;i<length;i++){ cout<<a[i]<<" ";}cout<<endl; return 0;}
以上文字部分转自:http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html
图片转自:http://blog.csdn.net/whuslei/article/details/6442755
进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集
- 希尔排序堆排序和基数排序
- 归并排序,堆排序,基数排序,希尔排序,快速排序,交换排序,选择排序和插入排序的总结和比较
- C# 插入排序 冒泡排序 选择排序 快速排序 堆排序 归并排序 基数排序 希尔排序
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法, 冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
- 希尔排序和基数排序的实现
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序
- 【Java】八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序 、快速排序、归并排序、堆排序和LST基数排序
- 希尔排序,基数排序,归并排序
- 快速排序,归并排序,堆排序,基数排序,插入排序,希尔排序,
- java实现:快速排序,基数排序,计数排序,归并排序,堆排序,希尔排序
- 插入排序、冒泡排序、选择排序、希尔排序、快速排序、归并排序、堆排序和LST基数排序——JAVA实现
- 插入排序、冒泡排序、选择排序、希尔排序、快速排序、归并排序、堆排序和LST基数排序——C++实现
- 插入排序、冒泡排序、选择排序、希尔排序、快速排序、归并排序、堆排序和LST基数排序的C++代码实现
- 内部排序合集●插入、希尔、起泡、快速、选择、堆、归并和基数排序●
- 常用排序算法二 希尔-鸡尾酒-堆-桶-基数排序(C++)
- 各种排序算法总结----基数排序、归并排序、插入排序、冒泡排序、选择排序、快速排序、堆排序、希尔排序
- 各种常见的排序,冒泡排序,选择排序,插入排序,希尔排序,堆排序,快速排序,基数排序,桶排序
- android-percent-support-lib-sample
- SQL表复制
- Bentley STAAD.Pro V8i SS6 v20.07.11.33 1CD(土木結構分析)
- [转载] 尺度不变特征变换匹配算法详解
- C++栈实践
- 希尔排序堆排序和基数排序
- COPRA.RF.v2005.SR1-ISO 1CD(设计检验轧辊的虚拟现实的集成软件)
- 影像去条带噪声
- Android System Property
- Engineering Equation Solver(EES) v7.171 1CD(工程方程求解器)
- GIT初学文章推荐
- 黑马程序员——Java基础---io流
- 切换imageview当中的图片
- ConcurrentHashMap原理分析