国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典)

這篇具有很好參考價值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法


一、前言:二叉樹的順序結(jié)構(gòu)

普通的二叉樹是不適合用數(shù)組來存儲的,因為可能會存在大量的空間浪費。而完全二叉樹更適合使用順序結(jié)構(gòu)存儲。
?
現(xiàn)實中我們通常把堆(一種二叉樹)使用順序結(jié)構(gòu)的數(shù)組來存儲,需要注意的是這里的堆和操作系統(tǒng)虛擬進程地址空間中的堆是兩回事,一個是數(shù)據(jù)結(jié)構(gòu),一個是操作系統(tǒng)中管理內(nèi)存的一塊區(qū)域分段。

【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法


二、堆的概念及結(jié)構(gòu)

堆是一種特殊的數(shù)據(jù)結(jié)構(gòu),可以將堆分為大頂堆和小頂堆兩種形式。堆中的每個節(jié)點都有一個值,并且滿足以下兩個條件:
?
①:堆的父節(jié)點的值總是大于或等于其子節(jié)點的值(大頂堆)或者小于或等于其子節(jié)點的值(小頂堆)。
②:堆是完全二叉樹,即除了最底層外,其他層的節(jié)點都是滿的,并且最底層的節(jié)點都盡量靠左排列。

大(小)堆示意圖:

【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法
【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法


三、堆的實現(xiàn)(本篇博客以實現(xiàn)小堆為例)

3.1 準備工作

由于堆是通過數(shù)組來實現(xiàn)的,所以我們也和順序表一樣,首先要創(chuàng)建一個結(jié)構(gòu)體來存儲:數(shù)組指針 + 容量 + 存儲數(shù)據(jù)大小。

代碼實現(xiàn):

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;//數(shù)組指針
	int size;//存儲數(shù)據(jù)大小
	int capacity;//容量
}HP;

3.2 初始化

初始化有兩種方式:
①:初始化時為數(shù)組開辟一定大小空間。②:直接將數(shù)組指針置為NULL,插入數(shù)據(jù)過程中在進一步處理。(本篇博客采用第二種)

代碼實現(xiàn):

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

3.3 堆的插入

【代碼思路】:
①:在插入數(shù)據(jù)前,我們首先要判斷是否要擴容的問題。由于前面初始化時我們直接置空,所以我們先判斷容量是否為空。如果為空開4個空間,否則空間擴大到原來的2倍。(為空時,第一次具體開辟多少空間讀者可自行選擇,本篇博客開4)
②:接下來就是插入數(shù)據(jù)了!但有一個問題,直接插入數(shù)據(jù)可能會破壞堆的結(jié)構(gòu),所以我們采用了向上調(diào)整算法

代碼:

void HPPush(HP* php, HPDataType x)
{
	assert(php);
	//擴容
	if (php->size == php->capacity)
	{
		int newcapacity = php->size == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("malloc fail");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}
	
	//插入數(shù)據(jù)
	php->a[php->size] = x;
	php->size++;

	//向上調(diào)整
	AdjustUp(php->a, php->size - 1);
}

3.3.1 向上調(diào)整算法

【代碼思路】:由于插入數(shù)據(jù)時,影響的只是插入數(shù)據(jù)到根節(jié)點間的關(guān)系。所以我們只需將插入數(shù)據(jù)通過雙親節(jié)點調(diào)到合適位置即可。
?
Tips:父節(jié)點和子節(jié)點關(guān)系

  • leftchild = parent *2 + 1
  • rightchild = parent * 2 + 2
  • parent = (child - 1)/2

【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法
代碼:

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

void AdjustUp(HPDataType* 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;
		}		
	}
}

3.4 堆的刪除

【代碼思路】:堆的刪除默認是頭刪。刪除有兩種思路:
?
①:將根節(jié)點刪除,再將其余數(shù)據(jù)全部向前移動。但這樣做會造成一個問題:挪動覆蓋導(dǎo)致父子節(jié)點的關(guān)系全亂了,需要重新建堆。為了刪個數(shù)據(jù),重新建堆,得不償失,所以我們采用下面這種方法。
?
②:將堆頂?shù)?數(shù)據(jù)和最后一個數(shù)據(jù)交換,在刪除最后一個數(shù)據(jù)。堆頂數(shù)據(jù)在通過向下調(diào)整算法調(diào)到合適位置即可。

【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法

代碼:

void HPPop(HP* php)
{
	assert(php);
	assert(!HPEmpty(php));//非空,還有數(shù)據(jù)可刪。該接口后面實現(xiàn)
	
	Swap(&php->a[0], &php->a[php->size - 1]);//交換
	php->size--;//刪除

	//向下調(diào)整
	AdjustDown(php->a, php->size, 0);
}

3.4.1 向下調(diào)整算法

【代碼思路】:向下調(diào)整算法有一個前提:左右子樹必須是一個堆,才能調(diào)整。同時還要注意是調(diào)大堆還是小堆。
調(diào)小堆:堆頂元素和孩子中最小的節(jié)點比較,如果父節(jié)點大于較小的子節(jié)點子,兩者交換。不斷向下調(diào)整到合適位置。(調(diào)大堆,和較大孩子比較)

【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法

代碼

//這里博主在多說一句,為什么向下調(diào)整算法不直接傳結(jié)構(gòu)體指針,
//而是分別傳數(shù)組指針和數(shù)據(jù)大小呢?
//這里是博主有意為之的,目的在于讓向下調(diào)整算法通用性更強,在做其他題時,也可以直接調(diào)用此接口
void AdjustDown(HPDataType* a, int n, int parent)
{
	assert(a);
	int child = parent * 2 + 1;//假設(shè)左孩子更小
	while (child < n)
	{
		//如果右孩子存在,且右孩子更小,則左孩子加1移到右孩子
		if ((child + 1) < n && a[child] > a[child + 1])
		{
			child++;
		}

		if (a[parent] > a[child])//交換
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			//父節(jié)點小于較小的子節(jié)點,說明已經(jīng)調(diào)到合適位置,此時break跳出
			break;
		}
	}
}

3.5 堆的判空(接下的過于簡單直接給出代碼)

bool HPEmpty(HP* php)
{
	return php->size == 0;
}

3.6 取堆頂?shù)臄?shù)據(jù)

	assert(php);
	assert(!HPEmpty(php));//斷言堆中還有元素
	return php->a[0];

3.7 堆的個數(shù)

int HPSize(HP* php)
{
	assert(php);
	return php->size;
}

3.8 堆的銷毀

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

四、所有代碼

Heap.h

#pragma once

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

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

void HPInit(HP* php);//初始化
void HPPush(HP* php, HPDataType x);//插入數(shù)據(jù)
void HPPop(HP* php);//刪除數(shù)據(jù)
int HPTop(HP* php);//堆頂元素
bool HPEmpty(HP* php);//判空
int HPSize(HP* php);//數(shù)據(jù)個數(shù)
void HPDestory(HP* php);//銷毀

Heap.c

#include "Heap.h"

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

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

void AdjustUp(HPDataType* 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;
		}
		
	}
}

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

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

void HPPush(HP* php, HPDataType x)
{
	assert(php);
	//擴容
	if (php->size == php->capacity)
	{
		int newcapacity = php->size == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("malloc fail");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}

	php->a[php->size] = x;
	php->size++;

	//向上調(diào)整
	AdjustUp(php->a, php->size - 1);
}


bool HPEmpty(HP* php)
{
	return php->size == 0;
}

void HPPop(HP* php)
{
	assert(php);
	assert(!HPEmpty(php));
	
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;

	//向下調(diào)整
	AdjustDown(php->a, php->size, 0);
}

int HPTop(HP* php)
{
	assert(php);
	assert(!HPEmpty(php));
	return php->a[0];
}

int HPSize(HP* php)
{
	assert(php);
	return php->size;
}

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

【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法
【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典),數(shù)據(jù)解構(gòu)和C++學(xué)習(xí)分享,數(shù)據(jù)結(jié)構(gòu),c語言,c++,啟發(fā)式算法文章來源地址http://www.zghlxwxcb.cn/news/detail-663669.html

到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)入門指南】二叉樹順序結(jié)構(gòu): 堆及實現(xiàn)(全程配圖,非常經(jīng)典)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)入門指南:順序表

    數(shù)據(jù)結(jié)構(gòu)入門指南:順序表

    目錄 文章目錄 前言 順序表 靜態(tài)順序表 動態(tài)順序表 總結(jié) ????????今天我們正式進入對數(shù)據(jù)結(jié)構(gòu)的學(xué)習(xí),順序表是數(shù)據(jù)結(jié)構(gòu)中最簡單的一種線性數(shù)據(jù)結(jié)構(gòu),也是數(shù)據(jù)結(jié)構(gòu)入門的試金石,如果對于順序表中內(nèi)容理解過難,可以先填補一下C語言中結(jié)構(gòu)體、動態(tài)內(nèi)存管理及指針

    2024年02月15日
    瀏覽(21)
  • 【數(shù)據(jù)結(jié)構(gòu)入門指南】單鏈表

    【數(shù)據(jù)結(jié)構(gòu)入門指南】單鏈表

    ?由于順序表插入和刪除元素需要移動大量數(shù)據(jù),導(dǎo)致運行效率下降。因此引入了另一種數(shù)據(jù)結(jié)構(gòu) —— 鏈表 。鏈表又分為單鏈表和雙鏈表。單鏈表結(jié)構(gòu)簡單,一般不會單獨用來存數(shù)據(jù)。實際中更多是作為其他數(shù)據(jù)結(jié)構(gòu)的子結(jié)構(gòu),如哈希桶、圖的鄰接表等等。另外這種結(jié)構(gòu)在

    2024年02月14日
    瀏覽(25)
  • C語言筆記 | 數(shù)據(jù)結(jié)構(gòu)入門指南

    文章目錄 0x00 前言 0x01 百雞百錢 0x1 題目描述 0x2 問題分析 0x3 代碼設(shè)計 0x4 完整代碼 0x5 運行效果 0x6 舉一反三 [兔雞百錢] 0x02 借書方案知多少 0x1 題目描述 0x2 問題分析 0x3 代碼設(shè)計 0x4 完整代碼 0x5 運行效果 0x6 舉一反三 [領(lǐng)導(dǎo)小組方案] 0x03 打魚還是曬網(wǎng) 0x1 題目描述 0x2 問題分

    2024年02月08日
    瀏覽(29)
  • 數(shù)據(jù)結(jié)構(gòu)入門指南:單鏈表(附源碼)

    數(shù)據(jù)結(jié)構(gòu)入門指南:單鏈表(附源碼)

    目錄 前言 尾刪 頭刪 查找 位置前插入 ?位置后插入 ?位置刪除 ?位置后刪除 ?鏈表銷毀 總結(jié) ? ? ? ? 前邊關(guān)于鏈表的基礎(chǔ)如果已經(jīng)理解透徹,那么接下來就是對鏈表各功能的實現(xiàn),同時也希望大家能把這部分內(nèi)容熟練于心,這部分內(nèi)容對有關(guān)鏈表部分的刷題很有幫助。廢話

    2024年02月14日
    瀏覽(28)
  • Python基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)入門必讀指南

    Python基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)入門必讀指南

    作者主頁:濤哥聊Python 個人網(wǎng)站:濤哥聊Python 大家好,我是濤哥,今天為大家分享的是Python中常見的數(shù)據(jù)結(jié)構(gòu)。 含義:數(shù)組是一種有序的數(shù)據(jù)結(jié)構(gòu),其中的元素可以按照索引來訪問。數(shù)組的大小通常是固定的,一旦創(chuàng)建就不能更改。 基本操作: 含義:列表是Python中內(nèi)置的

    2024年02月07日
    瀏覽(52)
  • 數(shù)據(jù)結(jié)構(gòu)入門指南:帶頭雙向循環(huán)鏈表

    數(shù)據(jù)結(jié)構(gòu)入門指南:帶頭雙向循環(huán)鏈表

    目錄 文章目錄 前言 1.結(jié)構(gòu)與優(yōu)勢 2.鏈表實現(xiàn)? ? ?? 2.1 定義鏈表 2.2 創(chuàng)建頭節(jié)點 2.3 尾插 2.4 輸出鏈表 2.5 尾刪 2.6 頭插 2.7頭刪 2.8?節(jié)點個數(shù) 2.9?查找 2.10?位置插入 2.11 位置刪除 2.12 銷毀鏈表 ?3. 源碼 總結(jié) ? ? ? ? 鏈表一共有8種結(jié)構(gòu),但最常用的就是無頭單向鏈表、和帶頭

    2024年02月14日
    瀏覽(23)
  • 【數(shù)據(jù)結(jié)構(gòu)】二叉樹基礎(chǔ)入門

    【數(shù)據(jù)結(jié)構(gòu)】二叉樹基礎(chǔ)入門

    ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???? ?? ?? ?? 個人主頁 :阿然成長日記 ??點擊可跳轉(zhuǎn) ?? 個人專欄: ??數(shù)據(jù)結(jié)構(gòu)與算法??C語言進階 ?? 不能則學(xué),不知則問,恥于問人,決無長進 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 一棵二叉樹是結(jié)點的

    2024年02月09日
    瀏覽(24)
  • 數(shù)據(jù)結(jié)構(gòu)入門 — 二叉樹的概念、性質(zhì)及結(jié)構(gòu)

    數(shù)據(jù)結(jié)構(gòu)入門 — 二叉樹的概念、性質(zhì)及結(jié)構(gòu)

    本文屬于數(shù)據(jù)結(jié)構(gòu)專欄文章,適合數(shù)據(jù)結(jié)構(gòu)入門者學(xué)習(xí),涵蓋數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)的知識和內(nèi)容體系,文章在介紹數(shù)據(jù)結(jié)構(gòu)時會配合上 動圖演示 ,方便初學(xué)者在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)時理解和學(xué)習(xí),了解數(shù)據(jù)結(jié)構(gòu)系列專欄點擊下方鏈接。 博客主頁:Duck Bro 博客主頁 系列專欄:數(shù)據(jù)結(jié)構(gòu)專欄

    2024年02月07日
    瀏覽(24)
  • 【Java--數(shù)據(jù)結(jié)構(gòu)】提升你的編程段位:泛型入門指南,一看就會!

    【Java--數(shù)據(jù)結(jié)構(gòu)】提升你的編程段位:泛型入門指南,一看就會!

    泛型是一種編程概念,它允許我們編寫可以適用于多種數(shù)據(jù)類型的代碼。通過使用泛型,我們可以在編譯時期將具體的 數(shù)據(jù)類型作為參數(shù) 傳遞給代碼,從而實現(xiàn)代碼 的復(fù)用和靈活性 。 在傳統(tǒng)的編程中,我們通常需要為不同的數(shù)據(jù)類型編寫不同的代碼,這樣會導(dǎo)致代碼冗余

    2024年04月26日
    瀏覽(35)
  • 數(shù)據(jù)結(jié)構(gòu)入門(C語言版)二叉樹概念及結(jié)構(gòu)(入門)

    數(shù)據(jù)結(jié)構(gòu)入門(C語言版)二叉樹概念及結(jié)構(gòu)(入門)

    1.1 樹的概念 樹是一種非線性的數(shù)據(jù)結(jié)構(gòu),它是由n(n=0)個有限結(jié)點組成一個具有層次關(guān)系的集合。把它叫做樹是因為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。 ☆有一個特殊的結(jié)點,稱為根結(jié)點,根節(jié)點沒有前驅(qū)結(jié)點 ☆除根節(jié)點外,其余結(jié)點被分成M

    2023年04月14日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包