Introduction to data structure (C language version) the sequential structure of the binary tree and the concept and application of the heap

insert image description here

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 .

The concept and structure of the heap

Here we first learn about the heap. The heap is a special form of binary tree.
If there is a set of key codes K = {N1, N2, N3,...,}, all its elements are stored in the order of a complete binary tree. In a one-dimensional array, and satisfy: Ni<= N(2 i+1) and Ni<= N(2 i+2)( Ni>= N(2 i+1) and Ni >=N(2 i+ 2) ) i = 0, 1, 2..., then it is called a small heap (or a large heap). The heap with the largest root node is called the largest heap or large root heap, and the heap with the smallest root node is called the smallest heap or small root 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.
insert image description here
insert image description here

implementation of the heap

1. Heap downward adjustment algorithm

Now we give an array, which is logically regarded as a complete binary tree. We can adjust it into a small heap through the downward adjustment algorithm starting from the root node. The downward adjustment algorithm has a premise: the left and right subtrees must be a heap to be adjusted.

int arr[] = {
    
    27,15,19,18,28,34,65,49,25,37};

insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
Later, when we talk about the heap insertion interface function, we will also mention the upward adjustment algorithm

2. Heap creation

Below we give an array, which logically can be regarded as a complete binary tree, but it is not a heap yet. Now we use an algorithm to build it into a heap. The left and right subtrees of the root node are not heaps, how do we adjust it? Here we start to adjust from the last subtree of the first non-leaf node to the tree of the root node, and then we can adjust it into a pile.

int a[] = {
    
    1,5,3,8,7,6};

insert image description here
Please add a picture description
insert image description here
insert image description here
At this time, when the positions of 1 and 8 are exchanged, the left subtree heap structure of 8 is destroyed, so every time an element exchange occurs, it is necessary to recursively call to reconstruct the heap structure and finally construct a large heap: 8, 7,
insert image description here
insert image description here
6 ,5,1,3

3. Heap insertion

Deleting the heap is to delete the data at the top of the heap, replace the data at the top of the heap with the last data, then delete the last data in the array, and then perform the downward adjustment algorithm.
insert image description here
insert image description here
insert image description here
★Exchange the top element of the heap with the last element in the heap
★Delete the last element
★Adjust the top element of the heap downward until the heap characteristics are satisfied

4. Implementation of the heap

The implementation of the heap here we use
the structure and interface definition of the sequence table structure heap

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

void AdjustUp(int* a, int child);//向上调整
void AdjustDown(int* a, int n, int parent);//向下调整

void Swap(HPDataType* px, HPDataType* py);//交换函数
void HeapInit(HP* hp);//堆的初始化
void HeapDestroy(HP* hp);// 堆的销毁
void HeapPush(HP* hp, HPDataType x);// 堆的插入
void HeapPop(HP* hp);// 堆的删除
HPDataType HeapTop(HP* hp);// 取堆顶的数据
void HeapPrint(HP* hp);//堆的打印
bool HeapEmpty(HP* hp);// 堆的判空
int HeapSize(HP* hp);// 堆的数据个数

heap interface implementation

The swap function (Swap)
code is as follows:

void Swap(HPDataType* px, HPDataType* py)
{
    
    
	HPDataType tmp = *px;
	*px = *py;
	*py = tmp;
}

The exchange function here is not an interface function, it is only for the convenience of other interface function calls

Adjust Up (AdjustUp)

code show as below:

void AdjustUp(int* a, int child)
{
    
    
	assert(a);

	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;
		}
	}
}

The upward adjustment function here is to compare an element with its parent. If the child is smaller than the parent, it is exchanged.
Insertion and heap sorting are commonly used in small heaps.

Adjust Down (AdjustDown)

code show as below:

void AdjustDown(int* a, int n, int parent)
{
    
    
	int child = parent * 2 + 1;
	while (child < n)
	{
    
    
		// 选出左右孩子中小的那一个
		if (child + 1 < n && a[child + 1] < a[child])
		{
    
    
			++child;
		}

		// 如果小的孩子小于父亲,则交换,并继续向下调整
		if (a[child] < a[parent])
		{
    
    
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
    
    
			break;
		}
	}
}

The downward adjustment function here is to compare an element with its parent. If the child is smaller than the parent, it is exchanged. It is
also commonly used in small heap insertion and heap sorting. The difference from upward adjustment is the direction.

Heap initialization (HeapInit)

code show as below:

void HeapInit(HP* hp)
{
    
    
	assert(hp);
	hp->a = NULL;
	hp->size = hp->capacity = 0;
}

Destruction of the heap (HeapDestroy)

code show as below:

void HeapDestroy(HP* hp)
{
    
    
	assert(hp);
	free(hp->a);
	hp->capacity = hp->size = 0;
}

Heap insertion (HeapPush)

code show as below:

void HeapPush(HP* hp, HPDataType x)
{
    
    
	assert(hp);
	if (hp->size == hp->capacity)
	{
    
    
		size_t newCapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
		HPDataType* tmp = realloc(hp->a, sizeof(HPDataType)*newCapacity);
		if (tmp == NULL)
		{
    
    
			printf("realloc fail\n");
			exit(-1);
		}

		hp->a = tmp;
		hp->capacity = newCapacity;
	}

	hp->a[hp->size] = x;
	hp->size++;
	AdjustUp(hp->a, hp->size - 1);
}

For heap insertion, first create memory space, and then insert elements, not to mention size++;
focus on the upward adjustment here, because it is a decimal upward adjustment, so the call here is used for the establishment of a small heap;
if you want to change it to a large Heap, then the judgment of the upward adjustment function must be changed to greater than;
the modified code is as follows:

if (a[child] >  a[parent])

Heap deletion (HeapPop)

code show as below:

void HeapPop(HP* hp)
{
    
    
	assert(hp);
	assert(!HeapEmpty(hp));

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

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

The deletion of the heap is to delete the element at the top of the heap, but it should be noted that the top element of the heap is not directly deleted,
but the top element and the last element are exchanged, and then the size-
then replace the last element to the Adjust to the corresponding position.
The purpose of doing this is to maintain the basic structure of the heap, otherwise the heap structure may not be established.

Get the data at the top of the heap (HeapTop)

code show as below:

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

	return hp->a[0];
}

Just return the first element directly

Heap printing (HeapPrint)

code show as below:

void HeapPrint(HP* hp)
{
    
    
	for (int i = 0; i < hp->size; ++i)
	{
    
    
		printf("%d ", hp->a[i]);
	}
	printf("\n");
}

The commonly used for loop traverses the elements of the sequence table and prints them one by one

Heap judgment empty (HeapEmpty)

code show as below:

bool HeapEmpty(HP* hp)
{
    
    
	assert(hp);

	return hp->size == 0;
}

The bool value is used here, of course you can also use the int type

The number of data in the heap (HeapSize)

code show as below:

int HeapSize(HP* hp)
{
    
    
	assert(hp);
	return hp->size;
}

Simple example of heap sort

code show as below:

void HeapSort(int* a, int n)
{
    
    
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
    
    
		AdjustDown(a, n, i);
	}
	for (int end = n - 1; end > 0; --end)
	{
    
    
		Swap(&a[end], &a[0]);
		AdjustDown(a, end, 0);
	}
}
int main()
{
    
    
	int a[] = {
    
     70, 56, 30, 25, 15, 10, 75, 33, 50, 69 };
	HeapSort(a, sizeof(a) / sizeof(a[0]));
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
    
    
		printf("%d ", a[i]);
	}
	printf("\n");

	return 0;
}

Here we mainly use the method of downward adjustment to achieve, because the deletion of the heap above is for small heaps, so
after the downward adjustment is called here, the array is in descending order, and it is printed as follows after sorting:

75 70 69 56 50 33 30 25 15 10

If we want to sort in ascending order, we only need to modify some symbols of the downward adjustment function
as follows:

void AdjustDown(int* a, int n, int parent)
{
    
    
	int child = parent * 2 + 1;
	while (child < n)
	{
    
    
		if (child + 1 < n && a[child + 1] > a[child])
		{
    
    
			++child;
		}
		if (a[child] > a[parent])
		{
    
    
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
    
    
			break;
		}
	}
}

After sorting, print as follows:

10 15 25 30 33 50 56 69 70 75

epilogue

Interested friends can pay attention to the author, if you think the content is good, please give a one-click triple link, you crab crab! ! !
It is not easy to make, please point out if there are any inaccuracies
Thank you for your visit, UU watching is the motivation for me to persevere.
With the catalyst of time, let us all become better people from each other! ! !
insert image description here

Guess you like

Origin blog.csdn.net/kingxzq/article/details/130169715