堆(Heap)

1.优先队列

特殊的队列,出队列的顺序按照优先级顺序。

1.1实现方法

image.png

2.优先队列的完全二叉树表示即是堆

2.1 堆的特点:

image.png

所有根结点是最大值或最小值

最大堆:从上之下每个结点从大到小(最小堆同理)

3. 堆的插入和删除(小顶堆)

3.1堆的插入

先插入到最后,然后调整堆。
调整堆的操作为判断父节点是否比 value 大 ,如果比 value 将此父节点往下调,最后找到 value 插入的位置。

void HEAP::push(int value) {  //最小堆插入
    int i = ++cur_size;
    for (; data[i / 2] > value; i /= 2)
    {
        data[i] = data[i / 2];
    }
    data[i] = value;
}

3.2堆的删除

堆的删除直接删除堆顶,但是删完后得做调整。
删除后将最后一个元素放到堆顶,然后判断孩子与此时堆顶的关系,如果孩子更小将孩子放入父节点,依次循环。
判断孩子节点时 需要判断左右孩子的大小。
循环终止条件为找到堆顶位置或无孩子节点

void HEAP::pop() {
   int temp = data[cur_size--];
   int Child = 0;
   int Par = 0;
   data[1] = temp;
   for (Par = 1; Par * 2 <= cur_size; Par = Child)
   {
       Child = Par * 2;
       if (data[Par * 2] > data[Par * 2 + 1])
       {
           Child = Child++;
       }
       if (data[Child] >= temp)
       {
           break;
       }
       else
       {
           data[Par] = data[Child];
       }
   }
   data[Par] = temp;
}

4. 给数组构建大根堆

首先先建立大根堆数组

void BuildMaxHeap(int A[],int len)
{
	for(int i = len/2;i > 0;i--)
	{
		HeadAdjust(A,i,len);
	}
}

void HeadAdjust(int A[],int k,int len) 
{
	int temp = A[k];
	int i = k*2;
	for(;i <= len;i *= 2)  // i 一直指向大的子孩子,和根节点 k 相比是否需要替换,如果能替换需要继续下沉比较
	{
		if( i+1 <= len && A[i+1] > A[i])
			 i++;
		if(A[k] > A[i]) break;
		else
		{
			A[k] = A[i];
			k = i;
		}
	}
	A[k] = temp;
}

建立后 heap.top 是最大元素,此时与末尾元素交换再调整即可排序。

void Heapsort(int A[],int len)
{
	BuildHeap(A,len);
	for(int i = 1;i < len;i++)
	{
		
	}
}