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

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

這篇具有很好參考價值的文章主要介紹了深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

二叉樹概念博客:http://t.csdn.cn/XIW84

目錄

1. 了解堆

1.1 堆的概念

1.2 堆的性質(zhì):

1.3 堆的結(jié)構(gòu)圖片

1.3.1 小堆

1.3.2 大堆

2. 堆的實現(xiàn)

2.1 插入數(shù)據(jù)進堆

2.2 向上調(diào)整函數(shù)

2.3 堆的刪除

2.4 向下調(diào)整

3. 堆的應(yīng)用

3.1 建堆(兩種方式)

3.1.1 建堆方式1

3.1.2 建堆方式2

3.2 堆排序?

3.3 堆的TOP—K問題


1. 了解堆

1.1 堆的概念

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

1.2 堆的性質(zhì):

堆中某個節(jié)點的值總是不大于或不小于其父節(jié)點的值;

堆總是一棵完全二叉樹。

1.3 堆的結(jié)構(gòu)圖片

1.3.1 小堆

?滿足下面條件的是小堆

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

1.3.2 大堆

滿足下面條件的是大堆

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

?注意不一定是從大到小、從小到大存儲的?。?!


堆有什么作用呢?

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

下面來細講,別走開?。。?/span>



2. 堆的實現(xiàn)

2.1 插入數(shù)據(jù)進堆

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, sizeof(HPDataType)*newcapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}

		php->a = tmp;
		php->capacity = newcapacity;
	}

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

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

注意點?。?!

假如一開始我們的堆是小堆,但是在插入數(shù)據(jù)以后要保持還是小堆,要將插入的數(shù)據(jù)的大小和它的父親進行比較,比較的兩種情況:

1. 如果插入的數(shù)據(jù)比父親還要大,那就不需要調(diào)整

2.?如果插入的數(shù)據(jù)比父親還要小,那就需要調(diào)整? ?

? 如果需要調(diào)整,我們就要使用向上調(diào)整算法,保持插入數(shù)據(jù)后的堆還是小堆


2.2 向上調(diào)整函數(shù)

void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;//求出插入數(shù)據(jù)的父親位置下標
	
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;//將父親的下標給孩子,向上調(diào)整
			parent = (child - 1) / 2;//再算出此時插入數(shù)據(jù)的父親下標
		}
		else
		{
			break;
		}
	}
}

2.3 堆的刪除

能不能使用覆蓋刪除呢—不能?。?!

使用覆蓋刪除,會打亂父子之間的下標關(guān)系,父子關(guān)系就會全部亂掉,因此我們使用下面的方法來刪除數(shù)據(jù)


1. 先將下標為0位置的數(shù)據(jù)和下標最大的數(shù)據(jù)進行交換

2. 然后直接size--

3. 然后還需要使用向下調(diào)整算法,把堆再調(diào)整為小堆

void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	Swap(&(php->a[0]), &(php->a[php->size - 1]));1.交換
	php->size--;//2. 刪除堆頂元素

	AdjustDwon(php->a, php->size, 0);//向下調(diào)整,保證還是小堆
}

2.4 向下調(diào)整

void AdjustDwon(HPDataType* a, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		// 選出左右孩子中小那個
        //這里的if里面的判斷大小盡量寫成小于是小堆,大于是大堆
		if (child+1 < size && a[child+1] < a[child])
		{
			++child;
		}

		// 孩子跟父親比較
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}	
}


3. 堆的應(yīng)用

3.1 建堆(兩種方式)

3.1.1 建堆方式1

利用插入元素的方式,向上調(diào)整建堆?

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

void HeapSort(int* a, int n)//傳一個數(shù)組過來,還有元素個數(shù)
{
	// 建堆方式1:O(N*logN)
	for (int i = 1; i < n; ++i)
	{
		AdjustUp(a, i);//從插入的第二個元素開始
	}
}

建堆方式1的時間復(fù)雜度 ——錯位相減法

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】


3.1.2 建堆方式2

利用向下調(diào)整建堆

方法:找到最后一個元素的父親,并從這個位置開始向下調(diào)整?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

void HeapSort(int* a, int n)
{

	// 建堆方式2:O(N)
	for (int i = (n-1-1)/2; i >= 0; --i)
	{
		AdjustDwon(a, n, i);
	}

	// O(N*logN)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDwon(a, end, 0);
		--end;
	}
}

建堆方式2的時間復(fù)雜度——錯位相減法


深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】


3.2 堆排序?

排升序,建大堆,再向下調(diào)整

為什么建大堆呢?

建大堆,堆頂元素是最大的數(shù),讓堆頂元素和最后一個元素交換,再向下調(diào)整,注意:這里向下調(diào)整時是調(diào)整的數(shù)組大小-1個,也就是調(diào)整剛剛交換下來前面的數(shù)據(jù)


排降序,建小堆,再向下調(diào)整

void HeapSort(int* a, int n)
{

	// 建堆方式2:O(N)
	for (int i = (n-1-1)/2; i >= 0; --i)
	{
		AdjustDwon(a, n, i);
	}

	// O(N*logN)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);//這里的end是9,傳過去向下調(diào)整的元素個數(shù)也是9,
                             //就不會調(diào)整剛剛從堆頂傳下來的數(shù)據(jù)
		AdjustDwon(a, end, 0);
		--end;
	}

3.3 堆的TOP—K問題

TOP-K問題:即求數(shù)據(jù)結(jié)合中前K個最大的元素或者最小的元素,一般情況下數(shù)據(jù)量都比較大。

比如:專業(yè)前10名、世界500強、富豪榜、游戲中前100的活躍玩家等。

實現(xiàn)思路:?

深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】

這樣空間復(fù)雜度非常小


注意:

? ? ? ? ? ?求前k個最大的數(shù),是建小堆

? ? ? ? ? ?解釋:由于建立的前k個數(shù)是小堆,后面n-k個數(shù)都可能比對頂?shù)臄?shù)值大,比堆頂?shù)脑卮?,就替換堆頂?shù)脑?,然后再向下調(diào)整,保持前k個數(shù)是小堆,然后再比較····

? ? ? ? ? ?求前k個最小的數(shù),是建大堆(同上


?代碼實現(xiàn):

void PrintTopK(int* a, int n, int k)
{
	// 1. 建堆--用a中前k個元素建堆
	int* kMinHeap = (int*)malloc(sizeof(int)*k);
	assert(kMinHeap);
	for (int i = 0; i < k; ++i)//將a數(shù)組里面前10個數(shù)賦值給KMinHeap
	{
		kMinHeap[i] = a[i];
	}
	for (int i = (k - 1 - 1) / 2; i >= 0; --i)//向下調(diào)整建堆,建立k個數(shù)的小堆
	{
		AdjustDwon(kMinHeap, k, i);
	}

	// 2. 將剩余n-k個元素依次與堆頂元素交換,不滿則則替換
	for (int j = k; j < n; ++j)
	{
		if (a[j] > kMinHeap[0])
		{
			kMinHeap[0] = a[j];
			AdjustDwon(kMinHeap, k, 0);//再向下調(diào)整,保持前k個數(shù)是小堆
		}
	}

	for (int i = 0; i < k; ++i)
	{
		printf("%d ", kMinHeap[i]);
	}
	printf("\n");
}

void TestTopk()
{    
    //隨機生成一萬個數(shù)字,每個數(shù)字%1百萬,這一萬都是比一百萬小的數(shù)字,
    //我們將其中的10個數(shù)改為比一百萬大的值
	int n = 10000;
	int* a = (int*)malloc(sizeof(int)*n);
	srand(time(0));
	for (int i = 0; i < n; ++i)
	{
		a[i] = rand() % 1000000;
	}
	a[5] = 1000000 + 1;
	a[1231] = 1000000 + 2;
	a[531] = 1000000 + 3;
	a[5121] = 1000000 + 4;
	a[120] = 1000000 + 5;
	a[99] = 1000000 + 6;
	a[0] = 1000000 + 7;
	a[76] = 1000000 + 8;
	a[423] = 1000000 + 9;
	a[3144] = 1000000 + 10;

	PrintTopK(a, n, 10);
}


本文講的是二叉樹的順序存儲結(jié)構(gòu)(堆)的實現(xiàn),下期我們來講二叉樹的鏈式存儲結(jié)構(gòu),到時候記得來支持小余哦?。?!

如果覺得文章不錯,期待你的一鍵三連哦,你個鼓勵是我創(chuàng)作的動力之源,讓我們一起加油,頂峰相見!??!文章來源地址http://www.zghlxwxcb.cn/news/detail-441177.html

到了這里,關(guān)于深入淺出堆—C語言版【數(shù)據(jù)結(jié)構(gòu)】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 【數(shù)據(jù)結(jié)構(gòu)與算法】深入淺出:單鏈表的實現(xiàn)和應(yīng)用

    【數(shù)據(jù)結(jié)構(gòu)與算法】深入淺出:單鏈表的實現(xiàn)和應(yīng)用

    ? ??博客主頁:青竹霧色間. ??博客制作不易歡迎各位??點贊+?收藏+?關(guān)注 ?? 人生如寄,多憂何為? ? 目錄 前言 單鏈表的基本概念 節(jié)點 頭節(jié)點 尾節(jié)點 單鏈表的基本操作 創(chuàng)建單鏈表 頭插法: 尾插法: 插入(增)操作 ?刪除(刪)操作: 查找(查)操作: 修改(改

    2024年02月08日
    瀏覽(24)
  • 深入淺出分支語句—【C語言】

    深入淺出分支語句—【C語言】

    目錄 前言:為什么要學習分支和循環(huán)語句呢? 1. 語句的分類 2. 分支語句(選擇語句) 2.1 if-else語句 注意點:if-else語句后面不加{},默認只能跟一條語句 2.2? switch語句 ?注意點: 因為C語言是一門結(jié)構(gòu)化的程序設(shè)計語言,具有三種結(jié)構(gòu):順序結(jié)構(gòu)、選擇結(jié)構(gòu)、循環(huán)結(jié)構(gòu),這三

    2024年02月02日
    瀏覽(161)
  • 深入淺出C語言—【函數(shù)】上

    深入淺出C語言—【函數(shù)】上

    ?? 目錄 1.函數(shù)的概念 2.C語言函數(shù)的分類 2.1 庫函數(shù) 2.1.1 strcpy庫函數(shù)舉例學習方式 2.1.2?庫函數(shù)擴展知識 2.2 自定義函數(shù) 2.2.1求兩個整數(shù)中的較大值 3. 函數(shù)的參數(shù) 3.1 實際參數(shù)(實參) 3.2 形式參數(shù)(形參) 4. 函數(shù)的調(diào)用 4.1 傳值調(diào)用 4.2 傳址調(diào)用 老鐵們,網(wǎng)址自取,記得一鍵

    2024年02月07日
    瀏覽(82)
  • 深入淺出C語言—【函數(shù)】下

    深入淺出C語言—【函數(shù)】下

    函數(shù)和函數(shù)之間可以根據(jù)實際的需求進行組合的,也就是互相調(diào)用的。 注意: 函數(shù)可以嵌套調(diào)用,但是不能嵌套定義。 把一個函數(shù)的返回值作為另外一個函數(shù)的參數(shù)。 上面的strlen函數(shù)是求數(shù)組長度的庫函數(shù), 特別注意的是,當數(shù)組為字符數(shù)組時,數(shù)組的末尾會自動放一個

    2024年02月17日
    瀏覽(114)
  • 深入淺出循環(huán)語句—【C語言】

    深入淺出循環(huán)語句—【C語言】

    ? 分支語句博客: http://t.csdn.cn/U2kZF 目錄 ?編輯 前言:我們先來了解一下break 、continue在循環(huán)中的作用 1. while循環(huán) ?while循環(huán)中的break ?while循環(huán)中的continue? 2. for循環(huán) for循環(huán)省略出錯舉例: ?for循環(huán)中的break ?for循環(huán)中的continue 3. do???while循環(huán) 利用do?while循環(huán)打印1~10? ?d

    2024年02月04日
    瀏覽(232)
  • 【藍橋杯日記】復(fù)盤篇一:深入淺出順序結(jié)構(gòu)

    【藍橋杯日記】復(fù)盤篇一:深入淺出順序結(jié)構(gòu)

    ? 本期是一篇關(guān)于順序結(jié)構(gòu)的題目的復(fù)盤,通過復(fù)盤基礎(chǔ)知識,進而把基礎(chǔ)知識學習牢固!通過例題而進行復(fù)習基礎(chǔ)知識。 前言 1.字符三角形 ?分析: 知識點: 代碼如下 2.?字母轉(zhuǎn)換 題目分析: 知識點: 代碼如下? 3.?再分肥宅水 題目分析: 知識點: 代碼如下? 4.?數(shù)字反轉(zhuǎn) 題

    2024年01月22日
    瀏覽(23)
  • 深入淺出:大語言模型的視覺解析

    深入淺出:大語言模型的視覺解析

    一系列工具與文章的匯編,直觀易懂地解讀復(fù)雜的 AI 概念 圖片由作者利用 unDraw.co 的免費插圖制作 在當今世界,大語言模型(LLM)成為了熱門話題。幾乎每天都有新的語言模型問世,讓人們在 AI 領(lǐng)域懷有一種“不容錯過”的緊迫感。盡管如此,許多人仍對大語言模型的基礎(chǔ)

    2024年01月19日
    瀏覽(26)
  • 深入淺出講解自動駕駛 - 激光雷達原理和結(jié)構(gòu)簡介

    深入淺出講解自動駕駛 - 激光雷達原理和結(jié)構(gòu)簡介

    ?? 個人主頁 : 同學來啦 ?? 版權(quán) : 本文由【同學來啦】原創(chuàng)、在CSDN首發(fā)、需要轉(zhuǎn)載請聯(lián)系博主 ?? 如果文章對你有幫助, 歡迎關(guān)注、點贊、收藏和訂閱專欄哦 激光雷達最先應(yīng)用于海洋深度探測領(lǐng)域,其實現(xiàn)思路是通過相同回波之間的時間差實現(xiàn)海洋深度測算。后來不斷演

    2024年02月16日
    瀏覽(26)
  • 深入淺出對話系統(tǒng)——自然語言理解模塊

    深入淺出對話系統(tǒng)——自然語言理解模塊

    首先回顧一下自然語言理解的概念。 自然語言理解(Natural Language Understanding)包含三個子模塊: 其中領(lǐng)域識別和意圖識別都是分類問題,而語義槽填充屬于序列標注問題。所以,在自然語言理解中,我們要解決兩個分類任務(wù)和一個序列標注任務(wù)。既然其中兩個問題都屬于分類任

    2024年02月08日
    瀏覽(21)
  • 深入淺出對話系統(tǒng)——基于預(yù)訓練語言模型的對話管理

    深入淺出對話系統(tǒng)——基于預(yù)訓練語言模型的對話管理

    主要講解三篇論文,主要思想是把自然語言理解、對話管理和自然語言生成三部分整合到一起。 數(shù)據(jù)集 CamRest676 MultiWOZ 都是用的自回歸語言模型 causal GPT-2、Transformer Decoder 一個概念:delexicalization 通過相應(yīng)的占位符替換特定的槽值 占位符作為特定的token,不關(guān)心具體的取值

    2024年02月16日
    瀏覽(163)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包