1. 程式人生 > >演算法之堆排序(最大堆c++實現)

演算法之堆排序(最大堆c++實現)

堆是完全二叉樹的結構,因此對於一個有n個節點的堆,高度為O(logn)。

最大堆:堆中的最大元素存放在根節點的位置。 除了根節點,其他每個節點的值最多與其父節點的值一樣大。也就是任意一個子樹中包含的所有節點的值都不大於樹根節點的值。

堆中節點的位置編號都是確定的,根節點編號為1,每一層從左到右依次編號。由堆是完全二叉樹,可以知道當堆中某個節點的編號為i時,如果這個節點有左右子樹,那麼左子樹的節點編號為2*i,右子樹的節點編號為2*i+1(當然這是在根節點編號為1的情況時)。

如下圖所示:

堆排序演算法:

    初始時候演算法是利用buildMaxHeap將陣列A[1...n]建成最大堆,因為陣列中最大元素總在根節點A[1]處,通過把他與A[n]進行互換,我們可以讓該元素放到正確位置。這時候,如果我們從堆中去掉結點n,剩餘結點仍然是最大堆,而新的結點可能會違背最大堆的性質。為了維護最大堆的性質,我們呼叫maxHeap(A, 1),從而在A[1...n-1]上構造一個新的最大堆。堆排序要做的是不斷重重複這樣的操作,直到堆的大小從n-1降到2.

虛擬碼及圖解如下:

HEAPSORT(A)

1:buildMaxHeap(A)

2: for i=A.length downto 2

3:          exchange A[1] with A[I]

4:         maxHeap(A, 1)

通過上面觀察可知,最大堆的排序過程其實是和最大堆的刪除操作類似,由於最大堆的刪除只能在根結點進行,當將根結點刪除完成之後,就是將剩下的結點進行整理讓其符合最大堆的標準。

程式碼實現如下:

#include<iostream>
using namespace std; 
void heapSort(int a[], int n);
void maxHeap(int a[], int n);
void buildMaxHeap(int a[], int n);

int size;
int main()
{
	int a[] = { 9, 12, -3, 0, 6, 8, 15, 7 };
	size= sizeof(a) / 4;
	heapSort(a, size);
	for (int i = 0; i < 8; i++)
		cout << a[i] << " ";
	return 0;
}
void heapSort(int a[], int n)
{
	int i;
	buildMaxHeap(a, n);
	for (i = size; i>1; i--)
	{
		swap(a[0], a[i-1]);
	    size = size - 1;
		maxHeap(a, 1);


	}

}
void buildMaxHeap(int a[], int n)
{
	int i = n / 2;
	for (i; i > 0; i--)
		maxHeap(a, i);

}
void maxHeap(int a[], int n)
{
	int leftChild, rightChild, largest;
	leftChild = 2 * n;
	rightChild = 2 * n + 1;
	int q = sizeof(a);
	if (leftChild<=size&&a[leftChild-1]>a[n-1])
		largest = leftChild;
	else
		largest = n;
	if (rightChild<=size&&a[rightChild-1]>a[largest-1])
		largest = rightChild;
	if (largest != n)
	{
		
		swap(a[n-1], a[largest-1]);
		maxHeap(a, largest);
	}
}


結果如下:

相關推薦

演算法排序大堆c++實現

堆是完全二叉樹的結構,因此對於一個有n個節點的堆,高度為O(logn)。 最大堆:堆中的最大元素存放在根節點的位置。 除了根節點,其他每個節點的值最多與其父節點的值一樣大。也就是任意一個子樹中包含的所有節點的值都不大於樹根節點的值。 堆中節點的位置編號都是確定的,根節點編號

演算法入門--排序大堆,從小到大排序

#include <stdio.h> #include <stdlib.h> /*由於不會動態獲得當前堆的元素數量heap_size,所以暫時用傳參的方法,但是當多次執行後發現 為了防止錯誤應該把heap_size設定為全域性變數,主函式初始化後,讓

排序演算法排序關鍵詞:資料結構/演算法/排序演算法/排序

假定:有 1 個亂序的數列 nums ,其中有 n 個數。 要求:排好序之後是 從小到大 的順序。 堆排序演算法 原理 先將原始的堆,調整為最大堆: 從倒數第 1 個有子結點的結點(下標為 index = n//2 - 1)開始,將以結點 index 為根結點的子堆

排序演算法選擇排序直接選擇、排序

排序演算法穩定性 假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序後的序列中,r[i]仍在r[j]之前,則稱這種排序演算法是穩定的;否則稱為不穩定的。 ————百度百

排序C++

堆分為大根堆(最大堆)和小根堆(最小堆),堆排序就是二叉堆的升級版,實際上是一棵完全二叉樹 不同的是這棵二叉樹裡每個節點保證父節點都小於孩子節點 最後進行堆排序,將堆頂最小的節點(第一個)與最後一個節點(最大的節點)進行交換,對剩下的進行調節,令其滿足最小堆 #incl

資料結構排序演算法歸併排序c語言實現

博主身為大二萌新,第一次學習資料結構,自學到排序的時候,對於書上各種各樣的排序演算法頓覺眼花繚亂,便花了很長的時間盡力把每一個演算法都看懂,但限於水平有限,可能還是理解較淺,於是便將它們逐個地整理實現出來,以便加深理解。 歸併排序就是通過將一個具有n個key記錄的線性表,看

排序--【演算法導論】

堆排序的思想在堆排序(最大堆)已做說明,故不再贅述; 總之,思想就是首先進行建堆,由於這是最小堆,故而必須保證父節點都小於孩子節點,若不滿足條件,則進行調節; 最後進行堆排序,不斷將最小的提取出來,並對剩下的進行調節,使之滿足最小堆; 故而將最大堆中的判斷父節點與孩子大小部

排序演算法排序及其C語言程式碼實現

概述:堆排,實際上是一種選擇排序,只不過採用了堆這種資料結構,利用這種資料結構,使得在每次查詢最大元素時,直接選取堆頂元素,從而時間大大縮短,相對簡單選擇排序演算法來說,比較高效。 堆排序演算法可描述

資料結構排序演算法快速排序c語言實現

快排的原理就是通過一趟排序將待排記錄分割成獨立的兩部分,其中的一部分記錄的關鍵字均比另一部分記錄的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。這其中,可以使用遞迴呼叫某一關鍵函式的辦法來實現這樣的功能。 分割的方法就是,選取一個樞軸,將所有關鍵字比它

排序--大堆構造和排序單步檢視過程

這裡先簡單說下最大堆的基本性質: 最大堆一定是完全二叉樹 當父節點為 n 時,左孩子為 n * 2 + 1,右孩子為 n * 2 + 2 當孩子為 n 時,其父節點為: (n - 1) / 2 ----> 這一點很重要,在後面初始化的時候會用到 父節點大於等於左孩子和右孩子,但左孩子不一定大於右孩子

排序演算法插入排序直接插入、希爾排序

前言 一個好的排序演算法對於程式的優化會有很大的提升,雖然在許多語言的類庫中就存在了N種排序方法,但是隻有在瞭解了每一種排序演算法後才能更好的在實際中運用這些演算法。這裡我主要說明插入排序中的直接插入以及希爾排序的實現。 直接插入 直接插入排序是最簡單的排序演算法之一。對於直

排序演算法選擇排序關鍵詞:資料結構/演算法/排序演算法/選擇排序

假定:有 1 個亂序的數列 nums ,其中有 n 個數。 要求:排好序之後是 從小到大 的順序。 選擇排序演算法 程式碼 from swap import swap def select_sort(nums): n = len(nums) i = 0 while

排序演算法插入排序關鍵詞:資料結構/演算法/排序演算法/插入排序

假定:有 1 個亂序的數列 nums ,其中有 n 個數。 要求:排好序之後是 從小到大 的順序。 插入排序演算法 程式碼 def insert_sort(nums): i = 1 n = len(nums) while i <= n-1: j = i

排序演算法氣泡排序關鍵詞:資料結構/演算法/排序演算法/氣泡排序

假定:有 1 個亂序的數列 nums ,其中有 n 個數。 要求:排好序之後是 從小到大 的順序。 氣泡排序演算法 程式碼 from swap import swap def bubble_sort(nums): n = len(nums) for i in rang

九大排序演算法插入排序原理及實現

1、演算法思路:每趟將一個待排序的元素作為關鍵字,按照其關鍵字值得大小插入到已經排好的部分的適當位置上,知道插入完成。 2、演算法過程 舉個栗子(第一趟的排序過程) 原始序列:49、38、65、97、76、13、27、49 1)開始以第一個元素49為關鍵字,看成一個序列,其餘數看成另

大堆 詳解

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Java中的經典演算法選擇排序SelectionSort

Java中的經典演算法之選擇排序(SelectionSort) 神話丿小王子的部落格主頁 a) 原理:每一趟從待排序的記錄中選出最小的元素,順序放在已排好序的序列最後,直到全部記錄排序完畢。也就是:每一趟在n-i+1(i=1,2,…n-1)個記錄中選取關鍵字最小的記錄作為有序序列中第i個記錄。基

十大經典排序演算法選擇排序Selection Sort

選擇排序(Selection-sort)是一種簡單直觀的排序演算法。 它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。  2.1 演算法描

排序演算法快速排序關鍵詞:資料結構/演算法/排序演算法/快速排序

快速排序 實現 def partition(nums, left, right): middle = (left+right) // 2 pivot = nums[middle] swap(nums, middle, right) # 現在主元 pivot 等於 num

排序演算法歸併排序關鍵詞:資料結構/演算法/排序演算法/歸併排序

假定:有 1 個亂序的數列 nums ,其中有 n 個數。 要求:排好序之後是 從小到大 的順序。 歸併排序演算法 程式碼 def merge(a, b): res = [] A = 0 B = 0 while A<len(a) and B<len(b