建堆的两种方法&小疑惑

堆,有时也被叫做优先队列。
更多的应用在需要优化一些效率的地方。各类语言中也提供了一些自治的优先队列的函数。C++就有priority_queue这个玩意。
但是这并不代表着就需要写建堆的函数了。
可是我有时写建堆函数的时候遇到了一些很疑惑的点,现在先记录下来。供以后研究吧。
第一种方法好像叫做筛选法建堆。也是教的那种。
具体思想就是从最后一棵子树调整起,保持到每颗子树都是堆,然后这么调整下去,直至到堆顶。也就建完堆了。
这种调整方法需要注意的点在于,每次一颗新子树调整的过程可能会影响到之前就已经调整好的子树,所以是一直找到结尾,而不是就在当前这里写完。
具体代码

void AdjustHeap(int heap[],int n){
    for(int i = n/2;i >= 1;i--)
    {
		int par = i;
		int tmp = heap[par];
		for(int lch = par*2; lch <= n;i++)
		{
			if(lch + 1 <= n && heap[lch+1] < heap[lch])
				lch++;
			if(heap[lch] > tmp)
				break;
			heap[par] = heap[lch];
			par = lch;
		}
		heap[par] = tmp;
    }
 }

还有一种方法则是像插入排序那样,每一步都是有序的,然后保证到最后都是有序的。
代码如下

void AdjustHeap(int heap[],int n){
    for(int i=1; i <= n; i++)
    {
        int k=i;
        while(k>1 && heap1[k] < heap1[k/2])
        {
            swap(heap1[k],heap1[k/2]);
            k=k/2;
        }
    }
  }

以上两种代码都是默认从1到n的数组下标。
但是这样会出现一个问题,就是上面两种代码对于同一组数据会有不同的结果。
比如下面这个
8
7 5 8 4 2 3 6 1
对于大顶堆 上述两种方法得到的结果是一样的
都是
8 5 7 4 2 3 6 1
而对于小顶堆
插入法是
1 2 3 4 5 8 6 7
筛选法是
1 2 3 4 7 8 6 5
之前写题目时遇到过插入法对的题目,有的又是筛选法对的题目,只能是把这两种方法都记住。方便使用了。
没想到之前抄的网上写的筛选法的代码有那么多的漏洞,汗

你可能感兴趣的:(算法,数据结构)