总感觉有些知识点,要经过以后的多多实践才能真正的熟练运用,因为我感觉看了之后理解吧是问题,问题是每次理解玩了之后要自己去很快形成思路并写出来,还是有一定的难度,感觉得多多运用才是王道啊! 反正吧管怎么说先记录下自己的理解对于以后必定有用...^.^,
首先是堆排序算法:
先简单的根据自己的理解介绍下什么是堆排序,这里所谓的堆是指二叉树,也就是用一维数组来线性的表示二叉树,而是怎么样实现排序的呢? 其实现原理其实就是对于数组中剩下的元素进行一次堆构造,构造的时候从树的底部向上逐渐的将大的数据放置到根结点 如图:
如图先比较 45与54 因为45<54 所以只要将左右孩子中大的与父节点比较即可,又因为54 > 23 这时就要交换父节点与子节点的值了。如此循环.....直到该棵树中根结的值最大。然后将根节点的最大值与一维数组的最后一个数据交换,完成了一次堆构造,然后循环....
代码如下:
//进行一次堆构造,完成后在数组的最大位置上,放置的是整个数组中的最大值,另外还有一点需要注意的就是s=j,赋值的意思,就是每次如果交换了数据则原来的堆结构被破坏需要重新构造。
void HeapAdjust(int a[],int s,int n)
{
int j,t;
while(2*s+1<n) //存在右子树
{
j=2*s+1;
if((j+1)<n) //左右子树比较
if(a[j]<a[j+1])
j++;
if(a[s]<a[j])
{
a[s]+=a[j];
a[j]=a[s]-a[j];
a[s]-=a[j];
s=j; //堆结构被破坏
}
else
break;
}
}
此函数完成数组所以元素的排序
void HeapSort(int a[],int n)
{
int t,i;
int j;
for(i=n/2-1;i>=0;i--) //先初始化二叉树,将其构造成堆
HeapAdjust(a,i,n);
for(i=n-1;i>0;i--)
{
a[0]+=a[i];
a[i]=a[0]-a[i];
a[0]=a[0]-a[i];
HeapAdjust(a,0,i);
}
} 其平均时间复杂度为O(nlogn)
第二种: 希尔排序
首先也是介绍下自己理解的希尔排序:
就是为一个数组增加一个递增访问变量,每次都按照那个增量进行访问比较,按照这个增量将数组划分为很多的子序列,对每个子序列一次进行访问,然后增量依次减半,最后等于一的时候结束排序比较。如图:
![](https://img-my.csdn.net/uploads/201204/17/1334664258_6205.jpg)
每次对已经排好序的每个子序列让其增量变为原来的2 倍再次进行比较即可,代码如下:
void ShellSort(int a[],int n)
{
int d,i,j,x;
d=n/2; //d为增量
while(d>=1)
{
for(i=d;i<n;i++)
{
x=a[i];
j=i-d;
while(j>=0 && a[j]>x)
{
a[j+d]=a[j];
j=j-d;
}
a[j+d]=x;
}
d=d/2;
}
} 其平均时间复杂度 O(n^(3/2))
第三种: 合并排序,这种排序也称为外部排序:
这个排序步骤还真不少,跟上面希尔有点象,就是有增量,但是图有所不同如下:
![](https://img-my.csdn.net/uploads/201204/17/1334664586_4581.jpg)
所以这种排序有三步,第一步是第一个系列中元素的排列,第二步是整个数组中相同系列的排序,这样就完成了一趟排序,然后增量变化,直到增量长度超过数组长度时停止,如下代码:
第一趟排序:
void MergeStep(int a[],int r[],int s,int m,int n)
{
int i,j,k;
k=i=s;
j=m+1;
while(i<=m && j<=n)
if(a[i]<=a[j])
r[k++]=a[i++];
else
r[k++]=a[j++];
while(i<=m)
r[k++]=a[i++];
while(j<=n)
r[k++]=a[j++];
}
第二趟排序:
void MergePass(int a[],int r[],int n,int len)
{
int s,e;
s=0;
while(s+len<n)
{
e=s+2*len-1;
if(e>=n)
e=n-1;
MergeStep(a,r,s,s+len-1,e);
s=e+1;
}
if(s<n)
for(;s<n;s++)
r[s]=a[s];
}
第三趟排序:
void MergeSort(int a[],int n)
{
int *p;
int len=1;
int f=0;
if(!(p=(int*)malloc(sizeof(int)*n)))
{
printf("内存分配失败!\n");
exit(0);
}
while(len<n)
{
if(f)
MergePass(p,a,n,len);
else
MergePass(a,p,n,len);
len*=2;
f=1-f;
}
if(f)
for(f=0;f<n;f++)
a[f]=p[f];
free(p);
}其平均时间复杂度 O(nlogn);