Maximum (small) heap --- related properties and code implementation

Heap characteristics

Insert picture description here

Maximum heap code implementation

插入时放在最后一个位置  ---  再进行上滤
删除时把最后一个结点放树根   ---  再进行下滤

Build the structure of the heap

  1. Use an array to store each value. Because the heap is a complete binary tree, it satisfies the relevant properties of a complete binary tree — iii under the left child node superscripti * 2 i * 2i2 , the subscript of the right child nodei ∗ 2 + 1 i*2+1i2+1
    (The node exists and the effective starting index of the array is 1)
  2. The position where the subscript of the array is 0 is stored as the maximum value of all possible elements in the heap. As
    a sentry, the for loop judgment condition can be simplified in the insert operation
    • If there is no sentry, the value of subscript 1 and subscript 0 should be added.
    • There is no need to add this condition to the condition with sentry, because the position with subscript 0 is saved as the maximum value
#include <stdio.h>
#include <stdlib.h>

// 建立最大堆
typedef struct HeapStruct* MaxHeap;
struct HeapStruct {
    
    
	int* Elements;
	int Size;	// 堆中当前的元素个数  不计算岗哨
	int Capacity;  //最大容量
};
#define MAXDATA 1000; //定义为堆中所有可能元素的最大值
/*作为数组中的0号位置上的元素,当作岗哨,在遍历的时候可以减少判断条件*/

Create heap

MaxHeap CreateHeap(int MaxSize) {
    
     // 创建容量为MaxSize大小的堆
	MaxHeap H = (MaxHeap)malloc(sizeof(struct HeapStruct));
	H->Elements = (int*)malloc(sizeof(int) * (MaxSize + 1));
	H->Size = 0;
	H->Capacity = MaxSize;
	H->Elements[0] = MAXDATA;  // 下标为0的元素为岗哨元素
	return H;
}

Insert elements into the heap

  1. Pay attention to the role of sentry in building the structure of the heap
  2. Logical process:
    • Insert the element into the complete binary treeLast node
    • Start from this node and compare with the parent node step by step
      • When greater than, swap the positions of the two nodes
      • When it is less than, the position is the insertion node position
int IsFull(MaxHeap H) {
    
    
	if (H->Capacity == H->Size)
		return 1;
	return 0;
}

/*插入一个结点*/
int Insert(MaxHeap H, int x) {
    
    
	if (IsFull(H)) {
    
    
		printf("FULL\n");
		return 0;
	}
	int i = ++H->Size;  //i指向插入后堆中的最后一个元素  也即对应完全二叉树的最后一个结点
	// 没用岗哨时就增加一个限制 i>1 以防止下标为0与下标为1的值进行比较
	for (; x > H->Elements[i / 2]; i /= 2) {
    
      //当子结点的值大于父结点的值 交换两结点位置
		H->Elements[i] = H->Elements[i / 2];
	}
	H->Elements[i] = x;
	return 1;
}

Delete the top element of the heap and adjust to create a new heap

How to adjust when the left and right child nodes are heaps, but a root is added:

  1. After deleting the top element of the heap, let the complete binary treeThe last node is regarded as the top element (root of the tree), And then continuously adjust this node through its relationship with the child nodes.
  2. Adjustment process:
    among the left and right child nodes of the corresponding node, find the node with the largest value to compare with the parent node
    • When the value of the parent node is small, change the position of the parent node and the child node of the maximum value
    • When the parent node value is large, this position is the correct position
int IsEmpty(MaxHeap H) {
    
    
	return H->Size == 0;
}

/*取出来最大值(堆顶) 并删除一个结点*/
int DeleteMax(MaxHeap H) {
    
      // 把最后一个结点放到堆顶然后调整
	if (IsEmpty(H)) {
    
    
		printf("EMOTY\n");
		return -1;
	}
	int Parenet, Child;
	int Maxitem, X;
	Maxitem = H->Elements[1];  // 返回最大值
	X = H->Elements[H->Size--];	 // 保存最后一个结点的值并删除一个结点

	// 开始调整堆 找左子树与右子树最大值 进行与X的比较
	for (Parenet = 1; Parenet * 2 <= H->Size; Parenet = Child) {
    
    
		Child = Parenet * 2;
		if ((Child != H->Size)  // 有右结点
			&& (H->Elements[Child] < H->Elements[Child + 1])) {
    
    
			Child++;  //Child 指向左右结点最大的值
		}

		if (X >= H->Elements[Child])  // 元素比子结点最大值还大时则找到正确的位置
			break;
		else
			H->Elements[Parenet] = H->Elements[Child];
	}
	H->Elements[Parenet] = X;
	return Maxitem;
}

Insert and delete icon

Insert picture description here

Build a heap by given elements

When a sequence is given, we save it in an array. During the
deletion process, it is essentiallyThe left and right child nodes are heaps, but how to adjust when adding a rootThe problem, which means that we can solve such a problem now, then we will turn a sequence into a heap into this problem:

  • We start to adjust from the last parent node, because the left (right) child node of the last parent node must have only elements or none, so it must be a heap. So the left and right child nodes are heaps, but how to adjust the problem when adding a root
/*调整下标为P对应的子树为一个堆*/
void PercDown(MaxHeap H, int P) {
    
    
	int Parenet, Child;
	int X;
	X = H->Elements[P];
	for (Parenet = P; Parenet * 2 <= H->Size; Parenet = Child) {
    
    
		Child = Parenet * 2;
		if (Child != H->Size && (H->Elements[Child] < H->Elements[Child + 1]))
			Child++;
		if (X >= H->Elements[Child])
			break;
		else
			H->Elements[Parenet] = H->Elements[Child];
	}
	H->Elements[Parenet] = X;
}

/*建立最大堆*/  // 所有H->Size个元素已经存在H->Data[]中
void BuildHeap(MaxHeap H) {
    
      // 从最后一个父结点开始调整这些元素使之成为最大堆
	for (int i = H->Size / 2; i > 0; i--) {
    
    
		PercDown(H, i);
	}
}

test

int main() {
    
    
	MaxHeap H = CreateHeap(20);
	for (int i = 0; i < 10; i++) {
    
    
		H->Elements[++H->Size] = i;
		
	}
	BuildHeap(H);
	for (int i = 1; i <= 10; i++) {
    
    
		printf("%d ", H->Elements[i]);
	}
	printf("\n");
	Insert(H, 10);
	for (int i = 1; i <= 11; i++) {
    
    
		printf("%d ", H->Elements[i]);
	}
	printf("\n");
	DeleteMax(H);
	for (int i = 1; i <= 10; i++) {
    
    
		printf("%d ", H->Elements[i]);
	}
	printf("\n");
	return 0;
}

result

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_43779658/article/details/105352929