最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++超詳細(xì)分析優(yōu)化排序算法之堆排序

 更新時間:2023年02月09日 08:53:36   作者:36°熨斗的焦慮日記  
堆是計算機科學(xué)中一類特殊的數(shù)據(jù)結(jié)構(gòu)的統(tǒng)稱,通常是一個可以被看做一棵完全二叉樹的數(shù)組對象。而堆排序是利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計的一種排序算法。本文將通過圖片詳細(xì)介紹堆排序,需要的可以參考一下

堆排序,學(xué)習(xí)了整整一天才把這個排序徹底搞明白……

首先第一點,堆排序是直接選擇排序的一種優(yōu)化排序算法。由于直接排序算法的遍歷次數(shù)過多,導(dǎo)致直接排序算法的時間復(fù)雜度為O(N^2),不適合排大量數(shù)據(jù),堆排序應(yīng)運而生。

堆排序(Heap Sort)進行的改進是能夠保存一部分在每次遍歷整個數(shù)組找出最大(小)值、次大(?。┲?,主要利用的就是完全二叉樹這種數(shù)據(jù)結(jié)構(gòu)。(后面說是如何保存這些數(shù)據(jù)的)

堆排序最重要的知識點無非兩個:

1、向下調(diào)整算法

2、堆的邏輯結(jié)構(gòu)是一棵完全二叉樹

先從定義開始學(xué)習(xí):

向下調(diào)整算法:顧名思義就是從上到下進行數(shù)據(jù)的調(diào)整,可以將完全二叉樹調(diào)整為最大堆與最小堆(這兩種堆也同時被稱為“大頂堆”和“小頂堆”)這種算法的前提是:根節(jié)點的左右兩棵子樹均以建成最大(小)堆。

最大堆:所有的父節(jié)點都大于子結(jié)點

最小堆:所有的父節(jié)點都小于子結(jié)點

完全二叉樹:從上到下、從左到右依次排列的一種樹(即從第一層到第n-1層都是滿的,只有第n層不滿且從左到右排列數(shù)據(jù))

(以建小堆為例)看一種典型的示例:

向下調(diào)整算法就是處理這種完全二叉樹的一種算法,經(jīng)過這種算法可將此數(shù)組建成最小堆。

先從根節(jié)點開始處理:

9 為父(根)節(jié)點,0,1都是其子節(jié)點,0 < 1;所以將0與9作一次交換;父節(jié)點同時下移至子節(jié)點,子節(jié)點變?yōu)樾赂腹?jié)點的子節(jié)點:(p = parent, c = child)

9 為父(根)節(jié)點,2,3都是其子節(jié)點,2 < 3;所以將2與9作一次交換;父節(jié)點同時下移至子節(jié)點,子節(jié)點變?yōu)樾赂腹?jié)點的子節(jié)點:

9 為父(根)節(jié)點,6 是其子節(jié)點,6< 9;所以將6與9作一次交換;父節(jié)點同時下移至子節(jié)點,子節(jié)點變?yōu)樾赂腹?jié)點的子節(jié)點:

發(fā)現(xiàn)此時新的子節(jié)點已經(jīng)越界,故停止向下調(diào)整;整個堆現(xiàn)已完成建堆成為最小堆!

這便是所謂的“向下調(diào)整算法”。

了解了以上知識后,還得知道父節(jié)點與子結(jié)點的表示方法:

leftchild = parent * 2 + 1;

rightchild = parent * 2 + 2;

parent = (leftchild - 1) /2;

下面代碼實戰(zhàn):

//向下調(diào)整:
//根節(jié)點左右子樹必須已經(jīng)成堆
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++;
		}
		//向下調(diào)整
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

簡單的交換函數(shù):

void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

堆排序的思想現(xiàn)在已經(jīng)有了雛形:

將一個數(shù)組想象成堆,建堆,然后將堆頂最大(?。┲抵糜诙训鬃鳛橛行驍?shù)據(jù),這時會新形成一個堆,比之前的堆少一個數(shù)據(jù),并且只有根節(jié)點的那棵小樹未成堆,左右子樹已形成大(?。┒?,用一次向下調(diào)整算法即可將新堆再次建成最大(小)堆。

現(xiàn)在的問題是我們選擇建一個最大堆還是最小堆呢?

我們不妨假設(shè)建了最小堆,也即上面我們剛剛構(gòu)建好的堆:

不難發(fā)現(xiàn)這樣是將最小值篩選出來,再向下調(diào)整,選出次小值,這樣一來會得到降序的一個數(shù)組,反之,若使用最大堆,會得到一個升序的數(shù)組。

我們建大堆來得到一個升序數(shù)組,現(xiàn)有此無序數(shù)組:

//數(shù)組
int a[] = { 5,9,6,1,7,2,0,4,3,8 };
//元素個數(shù)
int n = (int)sizeof(a) / sizeof(a[0]);

第一步就是建堆:

我們會發(fā)現(xiàn):這樣“不聽話”的數(shù)組顯然不符合向下調(diào)整算法的前提條件,所以我們可以從這個數(shù)組中找能用這個算法的地方:從后向前去調(diào)整,最后一個葉子節(jié)點?一個數(shù)據(jù),不需要調(diào)整;

最后一個父節(jié)點?他將會有0-2個子節(jié)點,而且只有這三個數(shù)據(jù),不管怎么“不聽話”,這個最小單位會滿足“根的左右子樹成堆”的這個條件,下一次再將這個父節(jié)點-1,即可實現(xiàn)對前一個父節(jié)點進行向下調(diào)整,循環(huán)此步驟直至真正的根節(jié)點,這時整個數(shù)組會被建成最大堆。

void HeapSort(int a[], int n)
{
    //建堆
	int parent = (n - 1 - 1) / 2;
	while (parent >= 0)
	{
		AdjustDown(a, n, parent);
		parent--;
	}
}

第二步就是排序:

建成堆后,我們需要進行數(shù)據(jù)的交換形成有序數(shù)據(jù)區(qū)。

void HeapSort(int a[], int n)
{
    //建堆
	int parent = (n - 1 - 1) / 2;
	while (parent >= 0)
	{
		AdjustDown(a, n, parent);
		parent--;
	}
	//已經(jīng)成最大堆,不用再從最后一個父節(jié)點建堆
	//每次只用改變根節(jié)點的堆(根左右堆已為最大堆)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}

堆排序完畢!

整個代碼分享:

#include <stdio.h>
void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
//向下調(diào)整:
//根節(jié)點左右子樹必須已經(jīng)成堆
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++;
		}
		//向下調(diào)整
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapSort(int a[], int n)
{
	int parent = (n - 1 - 1) / 2;
	while (parent >= 0)
	{
		AdjustDown(a, n, parent);
		parent--;
	}
	//已經(jīng)成最大堆,不用再從最后一個父節(jié)點建堆
	//每次只用改變根節(jié)點的堆(根左右堆已為最大堆)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}
void print(int* a, int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}
int main()
{
	int a[] = { 5,9,6,1,7,2,0,4,3,8 };
	int n = (int)sizeof(a) / sizeof(a[0]);
	HeapSort(a, n);
	print(a, n);
	return 0;
}

到此這篇關(guān)于C++超詳細(xì)分析優(yōu)化排序算法之堆排序的文章就介紹到這了,更多相關(guān)C++堆排序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言實現(xiàn)通訊管理系統(tǒng)設(shè)計

    C語言實現(xiàn)通訊管理系統(tǒng)設(shè)計

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)通訊管理系統(tǒng)設(shè)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 詳解C++異常處理機制示例介紹

    詳解C++異常處理機制示例介紹

    任何東西都可以認(rèn)為是異常,錯誤只是異常的一種。本文將帶大家了解C++中異常是什么,是如何捕獲和處理的等相關(guān)知識。文中示例代碼簡潔易懂,感興趣的小伙伴可以了解一下
    2022-08-08
  • C語言實現(xiàn)繪制南丁格爾玫瑰圖的示例代碼

    C語言實現(xiàn)繪制南丁格爾玫瑰圖的示例代碼

    玫瑰圖中有一種不等半徑的統(tǒng)計圖稱為南丁格爾玫瑰圖,網(wǎng)上很熱門,是一很有藝術(shù)感的漂亮的統(tǒng)計圖,下面我們就來看看如何使用C語言繪制它吧
    2024-03-03
  • 一文詳解C++17中的結(jié)構(gòu)化綁定

    一文詳解C++17中的結(jié)構(gòu)化綁定

    C++17中的結(jié)構(gòu)化綁定(structured binding)是指將指定名稱綁定到初始化程序的子對象或元素,本文主要來和大家聊聊C++17中結(jié)構(gòu)化綁定的實現(xiàn),感興趣的小伙伴可以了解下
    2023-12-12
  • c語言沒有try catch的替代方案

    c語言沒有try catch的替代方案

    這篇文章主要介紹了c語言沒有try catch的替代方案,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • C/C++指針和取地址的方法

    C/C++指針和取地址的方法

    C/C++指針和取地址的方法,需要的朋友可以參考一下
    2013-04-04
  • C++對象的淺復(fù)制和深復(fù)制詳解及簡單實例

    C++對象的淺復(fù)制和深復(fù)制詳解及簡單實例

    這篇文章主要介紹了C++對象的淺復(fù)制和深復(fù)制詳解及簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • C++實現(xiàn)讀寫ini配置文件的示例代碼

    C++實現(xiàn)讀寫ini配置文件的示例代碼

    配置文件的讀取是每個程序必備的功能,配置文件的格式多種多樣,例如:ini格式、json格式、xml格式等。其中屬ini格式最為簡單,且應(yīng)用廣泛。本文和大家分享了C++讀寫ini配置文件的方法,需要的可以參考一下
    2023-05-05
  • Qt5開發(fā)視頻播放器的項目實踐

    Qt5開發(fā)視頻播放器的項目實踐

    Qt對音視頻的播放和控制、相機拍攝、收音機等多媒體應(yīng)用提供了強大的支持,本文主要介紹了Qt5開發(fā)視頻播放器,具有一定的參考價值,感興趣的可以了解一下
    2023-08-08
  • Opencv 視頻轉(zhuǎn)為圖像序列的實現(xiàn)

    Opencv 視頻轉(zhuǎn)為圖像序列的實現(xiàn)

    今天小編就為大家分享一篇Opencv 視頻轉(zhuǎn)為圖像序列的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12

最新評論

丰都县| 兖州市| 韶山市| 福安市| 白河县| 贵德县| 朔州市| 永康市| 凌源市| 开化县| 虹口区| 江城| 娱乐| 八宿县| 孝感市| 东明县| 沈丘县| 昌图县| 聂荣县| 新郑市| 濮阳市| 武义县| 延安市| 闽侯县| 手游| 大邑县| 新沂市| 临潭县| 乌恰县| 遵化市| 通山县| 仲巴县| 姜堰市| 长阳| 龙口市| 乌鲁木齐市| 盐山县| 达孜县| 无极县| 光泽县| 理塘县|