Heap in C language and its implementation process

Keywords: less

I. The concept and structure of heap

If there is a set of key codes K = k0, k1, k2,... kn-1} stores all its elements in a one-dimensional array in the order of a complete binary tree, and satisfies: Ki <= K2i+1 and Ki <= K2i+2 (Ki >= K2i+1 and Ki >= K2i+2) I = > 0, 1, 2... It is called a small heap (or a large heap). The heap with the largest root node is called the maximum heap or the large root heap, and the heap with the smallest root node is called the minimum heap or the small root heap.

2. The nature of the reactor:

1. The value of a node in the heap is always not less than or less than the value of its parent node.
2. The heap is always a complete binary tree

3. Creation of heaps (take heaps as examples below)


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

Starting from the last non-leaf node, it adjusts forward and exchanges with the largest of his left and right children. If the value of this node is larger than that of both left and right children, it does not exchange, so the cycle lasts until the root node is judged.

IV. Insertion of heap

First insert the element to be inserted into the end of the array and perform the downward adjustment algorithm

5. Heap deletion

First, the first element and the last element of the array are exchanged, the length of the array is reduced by 1, and the downward adjustment algorithm is executed.

Heap sorting

1. Exchange the first element with the last one. At this point, the last element is the maximum, the array element is subtracted by 1 and the process is executed by 2 until only one root node is left. (The green line exchange in the figure is process 1)
2. The downward adjustment algorithm is performed from the last non-leaf node to the root node. Execution Procedure 1. (The red lines in the figure are exchanged for Procedure 1)

7. Code Implementation

The data structure of heap stores data in arrays, so it is most convenient to access it with subscripts, and one of the greatest advantages of heap is that it is a complete binary tree. The following figure is the number of left and right children, father's coordinates and the number of leaves and non-leaves deduced from the characteristics of node number, coordinate number and complete binary tree of heap. It is easy to implement the code.

heap.h

#ifndef HEAP_H
#define HEAP_H
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
typedef int HPDataType;

typedef struct Heap//Define a heap structure
{
	HPDataType *data;
	int size;
	int capacity;
}Heap;

void HeapInit(Heap* hp, HPDataType* a, int n);//Initialization heap
void HeapDestory(Heap* hp);//Destroy the heap
void HeapPush(Heap* hp, HPDataType x);//Insert element x to ensure that a new heap is generated
void HeapPop(Heap* hp);//Delete the top element of the heap to ensure that a new heap is generated
HPDataType HeapTop(Heap* hp);//Determine whether the heap is empty, return 0 for empty, or return the first element
int HeapSize(Heap* hp);//Number of data in heap
int HeapEmpty(Heap* hp);//Clean-up Reactor
void HeapPrint(Heap* hp);//Print heap
void AdjustDown(Heap* hp, int n);//Downward adjustment function from n-node
void AdjustUp(Heap* hp);//Upward adjustment function (from the last node)
void HeapSort(int* a, int n);// Heap sorting 
void TestHeap();//Test function

#endif 

heap.c

#include"heap.h"


    #define _CRT_SECURE_NO_WARNINGS 1
#include"heap.h"


void HeapInit(Heap* hp, HPDataType* a, int n)//Initialization of Reactor
{
	assert(hp != NULL);
	hp->capacity = 2 * n;
	hp->size = n;
	hp->data = (HPDataType*)malloc(sizeof(HPDataType)*hp->size);
	int i;
	for (i = 0; i < n; i++)
	{
		hp->data[i] = a[i];
	}
	for (i = n/2; i >= 0; i--)//Up-down adjustment algorithm from the first non-leaf node
	{
		AdjustDown(hp,i);
	}
}

void HeapDestory(Heap* hp)//Destruction function
{
	assert(hp != NULL);
	if (hp->data != NULL)
	{
		free(hp->data);
		hp->data = NULL;
	}
	hp->capacity = 0;
	hp->size = 0;
}
void HeapPush(Heap* hp, HPDataType x)//Adding elements to the heap
{
	assert(hp != NULL);
	Heap *cur = hp;
	int i;
	hp->size++;//Array size plus 1
	hp->data[hp->size] = x;//Adding data to the end of an array
	for (i = (hp->size - 2 )/ 2; i >= 0; i--)//
	{
		AdjustDown(hp, i);
	}
}
void HeapPop(Heap* hp)//Delete heap top elements
//Replace the last leaf node with the top of the heap, size--, and then perform the downward adjustment algorithm.
{
	assert(hp != NULL);
	if (hp->size == 0)
	{
		return;
	}
	int tmp = hp->data[0];//Exchange data from the beginning and end of an array
	hp->data[0] = hp->data[hp->size - 1];
	hp->data[hp->size - 1] = tmp;
	hp->size--;//The largest element is deleted
	AdjustDown(hp, 0);//Then the downward adjustment algorithm is executed to get a new heap
}

HPDataType HeapTop(Heap* hp)//Determine whether the heap is empty, return 0 for empty, or return the first element
{
	assert(hp != NULL);
	if (hp->data == NULL)
	{
		return (HPDataType) 0;
	}
	return hp->data[0];
}

int HeapSize(Heap* hp)//Calculate the data length of the heap
{
	assert(hp != NULL);
	return hp->size;
}

int HeapEmpty(Heap* hp)//empty
{
	assert(hp != NULL);
	memset(&hp, 0, sizeof(HPDataType)* hp->size);
	hp->capacity = 0;
	hp->size = 0;
	return 1;
}

void HeapPrint(Heap* hp)//Printing
{
	int i;
	int rn = 0;
	int bin = 1;
	for (i = 0; i < hp->size; i++)
	{
		printf("%d ", hp->data[i]);
		if (i == rn)
		{
			putchar('\n');
			bin *= 2; 
			rn += bin; 
		}
	}
	putchar('\n');
	putchar('\n');
}

void AdjustDown(Heap* hp, int num)//Downward adjustment function (heap), which only works on num Subscripts
//   1.if (right child does not exist)       
//        Record the coordinates of the left child (which is judged by a loop, this node must not be a leaf node, and the left child must exist)
//   2. Other (both right and left children exist)
//	       if: Left child > Right child, record left child coordinates		
//         Other: Left child <= Right child, record the coordinates of right child
//   3. if (the value of this node < process 1.2 records the child value)       
//        Exchange the values of the two and record the coordinates of the exchanged child and enter the child node. If the node is not a leaf node, continue to cycle (to prevent the last cycle from changing the following heap).
//     else        
//        break;
{
	int cur = num;//Subscripts to be adjusted downward
	int n;
	while (cur * 2 + 1 < hp->size)//Left child coordinates cannot cross the boundary
	{
		if (cur * 2 + 2 >= hp->size)//No Right Child
		{
			n = cur * 2 + 1;//Record the subscript of this node
		}
		else
		{
			if (hp->data[cur * 2 + 1] > hp->data[cur * 2 + 2])//Left child > right child
			{
				n = cur * 2 + 1;//Record left child subscriptions
			}
			else//Otherwise record the subscription of the right child
			{
				n = cur * 2 + 2;
			}
		}
		if (hp->data[cur]< hp->data[n])//If this node is smaller than the recorded child value, the values of both are exchanged.
		{
			int tmp = hp->data[cur];
			hp->data[cur] = hp->data[n];
			hp->data[n] = tmp;
			cur = n;//Record the coordinates after the exchange and proceed with the judgement.
		}
		else //Root node is larger than child value, no exchange, function end
		{
			break;
		}
	}
}

void AdjustUp(Heap* hp,int num)//Upward adjustment function (from the last node)
{
	int tmp = num;//Coordinates to be adjusted upwards
	assert(hp != NULL);
	int i;
	int parent = (num - 1) / 2;
	while (parent > 0)
	{
		if (hp->data[parent] > hp->data[(parent - 1) / 2])
		{
			int tmp = hp->data[parent];
			hp->data[parent] = hp->data[(parent - 1) / 2];
			hp->data[(parent - 1) / 2] = tmp;
			parent = (parent - 1) / 2;//The exchange succeeds, locates the parent node, and continues to loop until the root node.
		}
		else
		{
			break;
		}
	}
}


void HeapSort(Heap* hp)// Heap sorting 
{
	assert(hp != NULL);
	int i;
	int tmp = hp->size;//Record heap size
	for (i = 0; i < hp->size; i++)
	{
		HeapPop(hp);//The first element in the heap is the largest and keeps going until all elements are finished.
	}
	hp->size = tmp;//The array elements are not actually deleted, but are reduced to zero, sorted.
	//The size of the array is restored by re-assigning the original value to size, but after sorting, the array is no longer a heap, but an ordered array.
}

void TestHeap()
{
	int data[] = { 1, 5, 3, 8, 7, 6 };
	Heap hp;
	HeapInit(&hp, data, 6);
	HeapPrint(&hp);
	HeapPop(&hp);
	HeapPrint(&hp);
	HeapPush(&hp, 8);
	HeapPrint(&hp);
	AdjustUp(&hp,5);
	HeapPrint(&hp);
	system("pause");
	return 0;
}

Posted by Deanznet on Thu, 22 Aug 2019 05:32:37 -0700