排序算法(直接插入,堆排,归并排序)
来源:互联网 发布:木工简易算法在线阅读 编辑:程序博客网 时间:2024/06/06 01:06
1. 直接插入排序
思想:其基本思路就是将一个数插入一个已经有序的数据结构中。这里的数组从1下标开始存数据,代码如下:
void InsertSort(int *arr,int len)
{
int i,j;
for(i=2;i<=len;++i)
{
if(arr[i]<arr[i-1])
{
arr[0]=arr[i]; //设置哨兵
for(j=i-1;arr[j]>arr[0];j--)
{
arr[j+1]=arr[j]; //数据后移,循环结束,即找到了起始的要插入的数该插入的实际位置
}
arr[j+1]=arr[0]; //将要插入的哨兵位数据插入对应位置
}
}
}
直接插入排序的时间复杂度为O(n2),即二次方。
2. 堆排序
堆分为大顶堆和小顶堆,每个结点的值都大于或等于其左右孩子结点的值,就称为大顶堆,或者每个结点的值均小于或等于其左右孩子结点的值,称为小顶堆。
解决堆排序存在两个问题:(1)如何由一个无序序列构建一个堆;(2)如何利用一个大顶堆做升序排序,代码如下:
void HeapSort(int *arr,int len)
{
int i;
for(i=len/2;i>0;i--)
{
HeapAdjust(arr,i,len); //调整所有非叶子结点所在子树为大顶堆
}
for(i=len;i>1;i--)
{
swap(arr,1,i); //大顶堆的首个元素就是所有数中的最大值,所以每次只需要将arr[1]与最后一个元素交换,此后该位置的值不再变化
HeaoAdjust(arr,1,i-1); //交换之后,对剩下的1~i-1的下标数据调整为大顶堆
}
}
void HeapAdjust(char *arr,int sindex,int mindex)
{
int tmp,j;
tmp=arr[sindex]; //tmp保存当前根结点数值
for(j=2*sindex;j<=mindex;j*=2) //j为i的左孩子结点
{
if(j<m&& arr[j]<arr[j+1]) //如果左孩子下标在合理范围内并且左孩子数值小于右孩子数值
{
++j; //此时j记录的是左右孩子中数值较大的下标
}
if(tmp>=arr[j]) //如果根结点的值比左右孩子中最大的值都大,则不需要做任何改变,跳出循环
{
break;
}
else
{
arr[sindex]=arr[j]; //如果根结点的值小于左右孩子中最大的值,则将左右孩子中最大的值赋值给根结点,
sindex=j; //根结点下标变为原先左右孩子中较大值的下标
}
}
arr[sindex]=tmp; //将新的根结点赋值成原来的根结点数值
}
堆排序的时间复杂度为O(nlog(n))。
3. 归并排序
思想:假设初始序列含有n个数值记录,则可以看成n个有序子序列,每个子序列长度为1,然后两两归并,直到得到一个完整的有序序列。代码如下:
void MergeSort(int *arr,int len)
{
Msort(arr,arr,1,len);
}
void Msort(int sr[],int tr1[],int s,int t) //将sr[s.....t]归并排序为tr1[s....t]
{
int mid;
int tr2[MAXSIZE+1]; //用来临时存放归并后的有序记录
if(s==t)
{
th1[s]=sr[s];
}
else
{
mid=(s+t)/2;
Msort(sr,tr2,s,m); //将sr[s...m]归并为有序tr2[s....m]
Msort(sr,tr2,m+1,t); //将sr[m+1...t]归并为有序tr2[m+1....t]
Merge(tr2,tr1,s,m,t); //将tr2[s...m]和tr2[m+1.....t]合并为有序tr1[s....t]
}
}
void Merge(int sr[],int tr[],int i,int m,int n)
{
for(j=m+1,k=1;i<=m&&j<=n;k++) // i为左半部分最左边下标,j为右半部分最左端下标,k表示最终合并排好序的tr数组的下标
{
if(sr[i]<sr[j]) //如果整个最左端小,就将小的放入tr数组中
{
tr[k]=sr[i++];
}
else
{
tr[k]=sr[j++]; //否则,将sr[j]放入tr中,再让j后移
}
}
if(i<=m) //循环结束后,若是前半部分未放完,而后半部已完,则将前半部分剩余数据以此拷贝至tr数组中
{
for(int x=0;x<=m-i;x++)
{
tr[k+x]=sr[i+x];
}
}
if(j<=n) //循环结束后,若是后半部分未放完,而前半部已完,则将后半部分剩余数据以此拷贝至tr数组中
{
for( x=0;x<=n-j;x++)
{
tr[k+x]=sr[j+x];
}
}
}
归并排序时间复杂度为O(nlog(n)).
4. 非递归的归并排序算法
void MergeSort2(int arr[],int len)
{
int *tr=(int *)malloc(sizeof(int)*len);
int k=1;
while(k<len)
{
MergePass(arr,tr,k,len);
k=2*k;
MergePass(tr,arr,k,len);
k=2*k;
}
}
void MergePass(int sr[],int tr[],int s,int n)
{
int i=1;
int j;
while(i<=n-2*s+1)
{
Merge(sr,tr,i,i+s-1,i+2*s-1);
i=i+2*s;
}
if(i<n-s+1)
{
Merge(sr,tr,i,i+s-1,n);
}
else
{
for(j=i;j<=n;j++)
{
tr[j]=sr[j];
}
}
}
- 排序算法(直接插入,堆排,归并排序)
- 八种排序算法(直接插入,希尔,直接选择,堆,冒泡,快排,归并,基数)
- 常见排序算法C++实现(冒泡,直接插入,希尔,堆,归并,简单选择,快排)
- (冒泡,选择,插入,归并,堆排)排序算法
- 排序(快排,冒泡,堆排序,插入排序,归并排序,选择排序)算法Java实现
- 排序算法 快排 堆排 选择 插入 希尔 归并
- 学生成绩排序(直接插入,冒泡,快排,选择,堆排,2路归并)
- 直接插入排序、快排 AND归并排序(图)
- 排序(插入,希尔,选择,堆排序,归并,快排)
- 排序算法:快排,插入,希尔,归并,堆,选择,冒泡
- 排序算法(堆排序,归并排序,快排)
- 各种排序算法(冒泡、选择、快排、插入、希尔、堆排、归并、计数、基数)
- 常见排序算法总结与实现(冒泡、插入、选择、希尔、堆排序、归并、快排)
- 数据结构6-排序算法(直接插入排序、希尔排序、快速排序、归并排序和堆排序)
- 排序算法(堆排序,归并排序,快速排序、选择排序、直接插入排序)
- 排序算法: 冒泡排序, 快速排序,希尔排序,直接插入排序 ,直接选择排序,归并排序,堆排序
- 直接插入、冒泡、快速、简单选择、堆、归并排序算法
- 直接插入、冒泡、快速、简单选择、堆、归并排序算法
- 配置主机名 IP地址 主机映射
- c/c++面试题1
- HDU
- setTimeout顺序输出的问题
- 【差分+费用流|单纯形】BZOJ3112 [Zjoi2013]防守战线
- 排序算法(直接插入,堆排,归并排序)
- gRPC学习笔记(一)
- socket 编程 服务器端-客户端
- 对于数据去重的处理-PDI导入前及数据库端的双重设定
- c/c++面试题2
- validate-binary-search-tree
- [iPhone]解决:手指按住不动时,屏幕也会上下抖动
- 左偏树简介(洛谷P3377题解)
- Solr区间查询背后原理