zoukankan      html  css  js  c++  java
  • 建堆,以及对堆排序

                                            建堆,以及堆排序

    代码1:
    #include<stdio.h>
    int h[101];//用来存放堆的数组 
    int n;//用来存储堆中元素的个数,就是堆的大小 
    //交换函数,用来交换堆中的俩个元素的值 
    void swap(int x,int y)
    {
    	int t;
    	t=h[x];
    	h[x]=h[y];
    	h[y]=t;
    }
    //向下调整函数 
    void siftdown(int i)
    {//传入一个须要向下调整的的节点编号i,这里传入1。即从堆的顶点開始向下调整 
    	int t,flag=0;//flag用来标记是否须要继续向下调整
    	//当i节点有儿子(事实上是至少有左儿子)而且有须要继续调整的时候循环就运行 
    	while(i*2<=n&&flag==0)
    	{
    		//首先推断它与左儿子的关系。而且t记录值比較小的节点编号 
    		if(h[i]>h[i*2])
    		{
    			t=i*2;
    		}
    		else
    	    {
    	    	t=i;
    		}
    		//假设它有右儿子,再对右儿子进行讨论 
    		if(i*2+1<=n)
    		{
    			//假设右儿子的值更小。更新较小的节点编号 
    			if(h[t]>h[i*2+1])
    			{
    				t=i*2+1;
    			}
    		}
    		//假设发现最小的结点编号不是自己,说明子结点中有比父节点更小的值 
    		if(t!=i)
    		{
    			swap(t,i);//交换他们。注意swap函数 
    			i=t;//更新i为刚才与它交换的儿子结点的编号。便于接下来继续向下调整 
    		}
    		else
    		{
    			flag=1;
    			//否则说明当前的父结点已经比俩个子结点都要小了,不须要再进行调整 
    		}
    	}	
    } 
    //建立堆函数 
    void creat()
    {
    	int i;
    	for(i=n/2;i>=1;i--)
    	{
    		//总最后一个非叶结点到第一个结点一次进行向上调整 
    		siftdown(i);
    	}
    }
    //删除最大的元素 
    int deletemax()
    {
    	int t;
    	t=h[1];//用一个暂时变量记录堆顶点的值 
    	h[1]=h[n];//将堆的最后一个点赋值给堆顶 
    	n--;//堆的元素降低1 
    	siftdown(1);//向下调整 
    	return t;//返回之前记录的堆的顶点的最大值 
    }
    int main()
    {
    	int i,num;
    	scanf("%d",&num);
    	for(i=1;i<=num;i++)
    	{
    		scanf("%d",&h[i]);
    	}
    	n=num;
    	creat();
    	for(i=1;i<=num;i++)
    	{//删除顶部元素,连续删除n次,事实上也就是从大到小的把数输出 
    		printf("%d ",deletemax());
    	}
    	return 0;
    }
    代码,2:
    #include<stdio.h>
    int h[101]; //用来存储堆的数组
    int n;//用来存储堆中的元素的个数,也就是堆的大小
    //交换函数,用来交换堆中的俩个元素的值
    void swap(int x,int y)
    {
    	int t;
    	t=h[x];
    	h[x]=h[y];
    	h[y]=t;
    } 
    //向下调整函数 
    void siftdown(int i)
    {//传入一个须要向下调整的的节点编号i,这里传入1,即从堆的顶点開始向下调整 
    	int t,flag=0;//flag用来标记是否须要继续向下调整
    	//当i节点有儿子(事实上是至少有左儿子)而且有须要继续调整的时候循环就运行 
    	while(i*2<=n&&flag==0)
    	{
    		//首先推断它与左儿子的关系,而且t记录值比較小的节点编号 
    		if(h[i]<h[i*2])
    		{
    			t=i*2;
    		}
    		else
    	    {
    	    	t=i;
    		}
    		//假设它有右儿子。再对右儿子进行讨论 
    		if(i*2+1<=n)
    		{
    			//假设右儿子的值更大,更新较小的节点编号 
    			if(h[t]<h[i*2+1])
    			{
    				t=i*2+1;
    			}
    		}
    		//假设发现最小的结点编号不是自己,说明子结点中有比父节点更小的值 
    		if(t!=i)
    		{
    			swap(t,i);//交换他们,注意swap函数 
    			i=t;//更新i为刚才与它交换的儿子结点的编号。便于接下来继续向下调整 
    		}
    		else
    		{
    			flag=1;
    			//否则说明当前的父结点已经比俩个子结点都要小了,不须要再进行调整 
    		}
    	}	
    } 
    //建立堆函数 
    void creat()
    {
    	int i;
    	for(i=n/2;i>=1;i--)
    	{
    		//总最后一个非叶结点到第一个结点一次进行向上调整 
    		siftdown(i);
    	}
    }
    //堆排序
    void heapsort()
    {
    	while(n>1)
    	{
    		swap(1,n);
    		n--;
    		siftdown(1);
    	}
     } 
     int main()
     {
     	int i,num;
     	scanf("%d",&num);
     	for(i=1;i<=num;i++)
     	{
     		scanf("%d",&h[i]);
    	}
    	n=num;
    	creat();//建堆
    	heapsort();//堆排序
    	for(i=1;i<=num;i++)
    	{
    		printf("%d ",h[i]);
    	 } 
    	 return 0;
     }



  • 相关阅读:
    leetcode算法题基础(三十三)动态规划(一)70. 爬楼梯
    leetcode算法题基础(三十二)trie(四)676. 实现一个魔法字典
    leetcode算法题基础(三十一)trie(三)692. 前K个高频单词
    leetcode算法题基础(三十)trie(二)720. 词典中最长的单词
    leetcode算法题基础(二十九)trie(一)211. 添加与搜索单词
    leetcode算法题基础(二十八)拓扑排序(二)210. 课程表 II
    leetcode算法题基础(二十七)拓扑排序(一)207. 课程表
    leetcode算法题基础(二十六)深度优先(四)721. 账户合并
    leetcode算法题基础(二十五)深度优先(三)200. 岛屿数量
    leetcode算法题基础(二十四)深度优先(二)101. 对称二叉树
  • 原文地址:https://www.cnblogs.com/lytwajue/p/6795368.html
Copyright © 2011-2022 走看看