PTA练习题目:7-5 堆中的路径(2019.03.24)

2019年3月24日

堆排序,大,小顶堆的建立,堆插入

首先去复习了数据结构中学的堆排序。伪代码如下:

typedef SqList HeapType;
void  HeapAdjust( HeapType &H, int s, int m)
{
    rc = H.r[s];
    for( j=2*s; j<=m; j*=2){ //沿key较大的孩子结点向下筛选
        if( j<m && H.r[j].key < H.r[j+1].key)  ++j;
        if( rc.key >= H.r[j].key)  break;
        H.r[s] = H.r[j]; s = j;
    }
    H.r[s] = rc;
} 
void HeapSort( HeapType &H )
{  (1) 
    for( i=H.length/2; i>0; --i)  //建立初始堆,从i= ?n/2?到1,反复“筛选”
         HeapAdjust( H, i, H.length);
  (2)
    for( i=H.length; i>1; --i){
         H.r[1] ←→ H.r[i]; //堆顶记录和当前未排子序列中
                                                 //最后一个记录相交换
           HeapAdjust( H, 1, i-1 ); //将H. r[l .. i - 1] 重新调整为大顶堆
    }
}                    (参考小甲鱼视频)

代码如下:

void swap(int a[],int x,int y){
	int temp;
	temp=a[x];
	a[x]=a[y];
	a[y]=temp;
	
}
void HeapAdjust(int a[],int s,int n){
//s下面的序号都已经是一个小顶堆了 ,此时考虑的是由于a[s]一个的变化的变化引起下面小顶堆的变化 
	int i,temp;
	temp=a[s];//存放需要调整的双亲节点 
	for(i=2*s;i<=n;i*=2){
		if(i<n&&a[i]>a[i+1])//保证i<n否则不需要i+1 
			i++;
		if(temp<=a[i])  break;
		a[s]=a[i];
		s=i;
	}
	a[s]=temp;
}
void CreateHeap(int a[],int n){
	int i;
	for(i=n/2;i>0;i--){//从最大的非叶子节点开始筛选 
		HeapAdjust(a,i,n);//从a[i]到a[n]调整为小顶堆 
	}
	for(i=n;i>1;i--){//进行n-1次, 
		swap(a,1,i);
		HeapAdjust(a,1,i-1);
		//因为一个根节点发生变化,可能不再是小顶堆,(根节点之下都还是小顶堆)重新构建堆 
	}
}

本来以为是简单的建堆,结果发现怎么建堆都得不出输出样例的结果。原因如下:我用的建堆方法是直接生成完全二叉树然后从i/2结点开始调整,这种建堆方式时间复杂度为线性。本题中的要求是一个一个插入到堆中,时间复杂度为O(N Log N)。

#include<stdio.h>
int h[1000];
int insert(int x,int i){
	int temp;
	if(h[i/2]<=x){
		h[i]=x;
	}
	while(h[i/2]>x&&i/2>0){
		temp=h[i/2];
		h[i/2]=x;
		h[i]=temp;
		i=i/2;
	}
	
}
int main()
{
	int n,i,m,x,t,k;
	scanf("%d",&n);
	scanf("%d",&m);
	scanf("%d",&h[1]);
	for(i=2;i<=n;i++){
		scanf("%d",&x);
		insert(x,i);
	}
	for(t=0;t<m;t++){
		scanf("%d",&k);
		for(i=k;i>1;i=i/2){
		printf("%d ",h[i]);
		}
		printf("%d",h[1]); 
		printf("\n");
	}
	
 } 

或者一点小改动

#include<stdio.h>
int h[1001];
int size=0;
#define min -10001;
void insert(int x){
	int i;
	for(i=++size;h[i/2]>x;i=i/2){
		h[i]=h[i/2];
	}
	h[i]=x;
}
int main(){
	int n,m,i,temp;
	scanf("%d%d",&n,&m);
	h[0]=min;
	for(i=0;i<n;i++){
		scanf("%d",&temp);
		insert(temp);
	}
	for(i=0;i<m;i++){
		scanf("%d",&temp);
		printf("%d",h[temp]);
		while(temp>1){
			temp=temp/2;
			printf(" %d",h[temp]);	
		}
		printf("\n");
	}
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值