排序算法二-堆,希尔,合并排序

    总感觉有些知识点,要经过以后的多多实践才能真正的熟练运用,因为我感觉看了之后理解吧是问题,问题是每次理解玩了之后要自己去很快形成思路并写出来,还是有一定的难度,感觉得多多运用才是王道啊! 反正吧管怎么说先记录下自己的理解对于以后必定有用...^.^,
    首先是堆排序算法:
          先简单的根据自己的理解介绍下什么是堆排序,这里所谓的堆是指二叉树,也就是用一维数组来线性的表示二叉树,而是怎么样实现排序的呢? 其实现原理其实就是对于数组中剩下的元素进行一次堆构造,构造的时候从树的底部向上逐渐的将大的数据放置到根结点 如图:
          
     如图先比较 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)
   第二种: 希尔排序
         首先也是介绍下自己理解的希尔排序: 
          就是为一个数组增加一个递增访问变量,每次都按照那个增量进行访问比较,按照这个增量将数组划分为很多的子序列,对每个子序列一次进行访问,然后增量依次减半,最后等于一的时候结束排序比较。如图:
      
      每次对已经排好序的每个子序列让其增量变为原来的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))
     第三种: 合并排序,这种排序也称为外部排序:
         这个排序步骤还真不少,跟上面希尔有点象,就是有增量,但是图有所不同如下:
     
   所以这种排序有三步,第一步是第一个系列中元素的排列,第二步是整个数组中相同系列的排序,这样就完成了一趟排序,然后增量变化,直到增量长度超过数组长度时停止,如下代码:
 第一趟排序:
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);
   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值