Data structure - heap implementation (fine)

Table of contents

1.1 Sequential structure of binary tree

Ordinary binary trees are not suitable for storage in arrays, because there may be a lot of wasted space. The complete binary tree is more suitable for sequential structure storage. In reality, we usually store the heap (a binary tree) in an array of sequential structures. It should be noted that the heap here and the heap in the virtual process address space of the operating system are two different things. One is the data structure, and the other is the management in the operating system. A region of memory is segmentedEdit

1.2 The concept and application of heap

Properties of the heap:

The value of a node in the heap is always not greater than or not less than the value of its parent node;

The heap is always a complete binary tree.

​edit

​Edit As shown in the picture, it is the display of the small root pile and the big root pile 

2. Heap code and implementation  

 2.1 Adjustment down and adjustment up

Here we mainly explain two methods in this issue: downward adjustment and upward adjustment.

Code:


1.1 Sequential structure of binary tree


Ordinary binary trees are not suitable for storage in arrays, because there may be a lot of wasted space. The complete binary tree is more suitable for sequential structure storage. In reality, we usually store the heap (a binary tree) in an array of sequential structures. It should be noted that the heap here and the heap in the virtual process address space of the operating system are two different things. One is the data structure, and the other is the management in the operating system. A region of memory is segmented

 

1.2 The concept and application of heap

A heap is a data structure in which elements are stored in the order of a binary tree, and at the same time, the data stored in the father node is greater than the data stored in the son node (or the data in the father node is smaller than the data in the son node). . There are only two types of heaps, namely large heaps and small heaps. The large heap means that the father node data is greater than the son node data, and the small heap is vice versa.

Properties of the heap:
  • The value of a node in the heap is always not greater than or not less than the value of its parent node;
  • The heap is always a complete binary tree.


As shown in the figure is the display of the small root pile and the big root pile
 

2. Heap code and implementation  

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

void AdjustUp(HPDataType* a, int child);
void AdjustDown(int* a, int n, int parent);

void HeapInit(HP* php);
void HeapDestroy(HP* php);
void HeapPush(HP* php, HPDataType x);

void HeapPop(HP* php);
HPDataType HeapTop(HP* php);
bool HeapEmpty(HP* php);
int HeapSize(HP* php);

 2.1 Adjustment down and adjustment up

Here we mainly explain two methods in this issue: downward adjustment and upward adjustment.

Downward adjustment algorithm : the function is to turn any heap into a minimum heap or a maximum heap through the top-to-bottom algorithm sorting.

Steps: (Here take the minimum heap as an example)
1. Select a smaller value min from the left and right children of the root node
2. Compare the current data that needs to be adjusted with the smaller value min

  • Greater than min: exchange with min, and continue to step 1 from the exchanged position;
  • Less than or equal to min: end

 

void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child<n)
	{
		if (a[child + 1] > a[child])
		{
			child++;

		}
		if(a[child]>a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}

	}
}

Adjusting Up : Graphical Ideas

 Every time you build a small root heap and exchange elements, have you put the smallest element at the end of the array at this time, indicating that it has been determined, then we don’t need to move, what we want to move is the array that is not Determined elements, find the smallest among these. Then this step is reflected on the heap.
For example, after we first build a small root heap with a set of numbers such as 6, 2.1.4, 1 goes to the top of the heap, that is, to the first element 1 of the array, and the array is now 1***, exchanged with the last element, becomes ** * 1, then 1 has been determined at this time, what we need to do next is to build a small root pile from the three of **, these three Put the smallest element in the first element
, for example, 2** 1, we exchange 2 and the last element of the array that has not been determined this time, and it becomes **21. At this time, 2 and 1 have been determined, and we go to the remaining two A** to build, to swap, and finally get 6 4 2 1

void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child<n)
	{
		if (a[child + 1] > a[child])
		{
			child++;

		}
		if(a[child]>a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}

	}
}


Code:

#include"Heap.h"
void HeapInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}

void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;

	php->size = 0;
	php->capacity = 0;
}

void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		int newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a, newCapacity * sizeof(HPDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		php->a = tmp;
		php->capacity = newCapacity;
	}
	php->a[php->size] = x;
	php->size++;

	AdjustUp(php->a, php->size - 1);

}

void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType* tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);

			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child<n)
	{
		if (a[child + 1] > a[child])
		{
			child++;

		}
		if(a[child]>a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}

	}
}

void Heapop(HP* php)
{
	assert(php);
	assert(!HeapEmpty(php));

	Swap(&php->a[0], &php->a[php->size - 1]);
	php--;

	AdjustDown(php->a, php->size, 0);
}

HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(!HeapEmpty(php));

	return php->a[0];
}

//
bool HeapEmpty(HP* php)
{
	assert(php);

	return php->size == 0;
}

int HeapSize(HP* php)
{
	assert(php);

	return php->size;

Guess you like

Origin blog.csdn.net/m0_74459304/article/details/131657378