手書きのバイナリ ツリー -- ヒープ インターフェイスの実装 (ソース コード + ダイアグラム付き)

ヒープインターフェースの実装(ソースコード+図付き)



序文

この記事では主に二分木でのヒープの追加・削除・チェック・修正などのインターフェースの実装を紹介し、最後に全体のソースコードを添付しています!


1. 構造を定義する

ここに画像の説明を挿入

コードは次のとおりです (例)。

typedef int HPDataType;
typedef struct Heap
{
    
    
	HPDataType* a; //定义数组二叉树
	int size;      //二叉树结点个数
	int capacity;  //二叉树容量(考虑增容)
}HP;

2. インターフェース実装(添付ソリューション+ソースコード)

ここに画像の説明を挿入
ここには全部で 11 のインターフェイスがあり、1 つずつ説明します (イラスト + ソースコード)


1.ヒープを初期化する

二分木におけるヒープの格納構造は配列なので、 2つのインターフェースの初期化と破棄はシーケンステーブルやその他のデータ構造と同じなので、ここではあまり紹介しません!

コードは次のとおりです (例)。

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

2. ヒープを破棄する

コードは次のとおりです (例)。

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

3.テールプラグデータ

ここに画像の説明を挿入


コードは次のとおりです (例)。

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

ここで注意してください: 大きなヒープであろうと小さなヒープであろうと、それはノード > または < 子ノード(二分木の性質) を満たす必要があります。ここでは上下調整を使用します! データをプッシュすると、このパスのデータのみが変更されます!
ここに画像の説明を挿入


①上方調整

以下に示すように、いくつかのデータを挿入するとします上向きに調整すると、1 つのパスのみが変更されます。! !
ここに画像の説明を挿入

上方調整は、


ここに画像の説明を挿入


ここに画像の説明を挿入


コードは次のとおりです (例)。

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

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

(2) 交換機能

関数パラメーターを渡す場合、仮パラメーターは実パラメーターの一時的なコピーであるため、ポインターを渡す必要があります。

コードは次のとおりです (例)。

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

(3)下向きに調整


ここに画像の説明を挿入

ここでパラメーターに注意してください: 親ノードから。最高点は最小値です。
ここに画像の説明を挿入

ここに画像の説明を挿入


下方調整は、トップ (最高ノード) が最小値であることを確認する必要があります!
ここに画像の説明を挿入


ここに画像の説明を挿入


4.印刷データ

二分木の格納構造は配列であるため、印刷時に直接トラバースできます。

コードは次のとおりです (例)。

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

5.空かどうかを判断する

コードは次のとおりです (例)。

bool HeapEmpty(HP* hp)
{
    
    
	assert(hp);
	return hp->size == 0;
}

6. ノード数

コードは次のとおりです (例)。

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

7. ヒープトップデータ

配列に対して null 操作を実行することを忘れないでください。そうしないと、ワイルド ポインターの問題が発生します。

コードは次のとおりです (例)。

HPDataType HeapTop(HP* hp)
{
    
    
	assert(hp);
	assert(!HeapEmpty(hp));
	return hp->a[0];
}

8. ヒープの一番上にあるデータを削除する

ここで注意してください: データを削除した後、ヒープのプロパティ構造(Adjustdown) を保護する必要があります。
ここに画像の説明を挿入


ここに画像の説明を挿入


3. ソースコード表示

(1) Heap.h(インターフェース関数の宣言)

コードは次のとおりです (例)。

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
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);//堆结点个数

(2) Heap.c(インターフェース関数の実装)

コードは次のとおりです (例)。

#include "Heap.h"
void Swap(HPDataType * px, HPDataType * py)
{
    
    
	HPDataType tmp = *px;
	*px = *py;
	*py = tmp;
}
void HeapInit(HP* hp)
{
    
    
	assert(hp);
	hp->a = NULL;
	hp->size = hp->capacity = 0;
}
void HeapDestroy(HP* hp)
{
    
    
	assert(hp);
	free(hp->a);
	hp->capacity = hp->size = 0;
}
void AdjustUp(int* a, int child)
{
    
    
	assert(a);
	int parent = (child - 1) / 2;
	//while (parent >= 0)
	while (child > 0)
	{
    
    
		if (a[child] > a[parent])
		{
    
    
			Swap(&a[child], &a[parent]);

			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
    
    
			break;
		}
	}
}
void HeapPrint(HP* hp)
{
    
    
	for (int i = 0; i < hp->size; ++i)
	{
    
    
		printf("%d ", hp->a[i]);
	}
	printf("\n");
}
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);
}
bool HeapEmpty(HP* hp)
{
    
    
	assert(hp);
	return hp->size == 0;
}
int HeapSize(HP* hp)
{
    
    
	assert(hp);
	return hp->size;
}
HPDataType HeapTop(HP* hp)
{
    
    
	assert(hp);
	assert(!HeapEmpty(hp));
	return hp->a[0];
}
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;
		}
	}
}
// 删除堆顶的数据
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);
}

(3) test.c (テスト+メイン関数)

コードは次のとおりです (例)。

#include"Heap.h"
void TestHeap()
{
    
    
	int a[] = {
    
     70, 56, 30, 25, 15, 10, 75 };
	HP hp;
	HeapInit(&hp);
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
    
    
		HeapPush(&hp, a[i]);
	}
	HeapPrint(&hp);

	HeapPop(&hp);
	HeapPrint(&hp);

	HeapPop(&hp);
	HeapPrint(&hp);

	HeapPop(&hp);
	HeapPrint(&hp);

	HeapPop(&hp);
	HeapPrint(&hp);

	HeapDestroy(&hp);
}

要約する

以上が本日の言いたいことですが、この記事では二分木におけるヒープのインターフェース実装を紹介します(ソリューションとソースコードを添付)!
私のブログが役に立ったら、忘れずに 3 回サポートしてください。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/2201_75587702/article/details/129786039