(二叉)堆是乙個陣列,是一顆近似完全二叉樹,分為大頂堆&小頂堆。表示堆的陣列a有兩個屬性:(1)a.length表示陣列元素的個數;(2)a.heap-size表示有多少個堆元素儲存在陣列a中。更多的關於堆的性質的介紹:演算法導論第三版:p85-p89、程式設計珠璣:p141-p145。
堆的操作主要包括堆插入、堆刪除兩個,而堆插入設計到siftup操作(自底向上調整),堆刪除涉及到siftdown操作(自頂向下調整,大頂堆時對應演算法導論上的max-heapify操作)。
下面是大頂堆和小頂堆的基本操作的c++的實現:
#pragma once
templateclass heap
virtual ~heap()
void insert(const t &e);
void delete(const t &e);
int search(const t &e) const;
void print() const;
protected:
t *arr;
const int max_size; //max array elements
int size; //size of heap
virtual void siftdown(int i) = 0; //adjust from up to down
virtual void siftup(int i) = 0; //adjust from down to up
};templatevoid heap::insert(const t &e)
templatevoid heap::delete(const t &e)
templateint heap::search(const t &e)const
templatevoid heap::print()const
最大堆:maxheap.h
#pragma once
#include "heap.h"
#include using std::cout;
using std::endl;
templateclass maxheap : public heap
~maxheap() {}
private:
virtual void siftdown(int i); //adjust from up to down
virtual void siftup(int i); //adjust from down to up
};templatevoid maxheap::siftdown(int i)
arr[i] = tmp;
}templatevoid maxheap::siftup(int i)
arr[i] = tmp;
}
最小堆:minheap.h
#pragma once
#include "heap.h"
#include using std::cout;
using std::endl;
templateclass minheap : public heap
~minheap(){}
private:
virtual void siftdown(int i);
virtual void siftup(int i);
};templatevoid minheap::siftdown(int i)
arr[i] = tmp;
}templatevoid minheap::siftup(int i)
arr[i] = tmp;
}
測試**:
#include "maxheap.h"
#include "minheap.h"
int main()
; maxheapmaxheap(20);
minheapminheap(20);
for (int i = 0; i < 12; i++)
maxheap.insert(a[i]); //向上調整
maxheap.print();
maxheap.delete(4); //向下調整
maxheap.print();
for (int i = 0; i < 12; i++)
minheap.insert(a[i]); //向上調整
minheap.print();
minheap.delete(4); //向下調整
minheap.print();
getchar();
return 0;
}
這裡用的是插入的方法建堆:最壞情況下,建立乙個包含n個元素的堆的時間複雜度是o(nlgn),大theta。
一般地,還要k叉堆:演算法導論第三版p93。
利用堆可以實現:堆排序
、優先佇列
。在dijkstra演算法中: extract-min(q) 操作,就可以先建立最小堆,然後從最小佇列中,每次抽取最小結點(參考 最短路徑之dijkstra演算法 一文的參考資料鏈結)。
此外,堆還可以用於:海量資料中選擇前k個最大(最小)的數。
思想:在乙個很大的無序陣列裡面選擇前k個最大(最小)的資料,最直觀的做法是把陣列裡面的資料全部排好序,然後輸出前面最大(最小)的k個資料。但是,排序最好需要o(nlogn)的時間,而且我們不需要前k個最大(最小)的元素是有序的。這個時候我們可以建立k個元素的最小堆(得出前k個最大值)或者最大堆(得到前k個最小值),我們只需要遍歷一遍陣列,在把元素插入到堆中去只需要logk的時間,這個速度是很樂觀的。利用堆得出前k個最大(最小)元素特別適合海量資料的處理。
資料結構之二叉堆
二叉堆的介紹 二叉堆是完全二元樹或者是近似完全二元樹,按照資料的排列方式可以分為兩種 最大堆和最小堆。示意圖如下 二叉堆一般都通過 陣列 來實現。陣列實現的二叉堆,父節點和子節點的位置存在一定的關係。有時候,我們將 二叉堆的第乙個元素 放在陣列索引0的位置,有時候放在1的位置。當然,它們的本質一樣 ...
基礎資料結構之二叉堆
二叉堆一般用於涉及插入 刪除 查詢最值得題目。往往配合其它題型使用。對頂堆 對頂堆常用於動態維護的問題。動態中位數 動態求解前i個數的中位數。黑盒子 動態求解前u i 個數第i大的數。超市 貪心題目。需要用到二叉堆的查詢最值 插入和刪除功能。序列 多路歸併問題。注意到是求和問題,題目讓求m個序列 合...
資料結構 二叉堆
二叉堆一般用來實現優先佇列 優先佇列是一種至少允許以下兩種操作的資料結構 insert 以及 deletemin 同查詢樹一樣,二叉堆具有結構性與堆序性,對二叉堆的基本操作可能會破壞這些性質,所以二叉堆的操作要直到其基本性質滿足才能結束。一 結構性 二叉堆在結構上為完全二叉樹,其具有完全二叉樹的結構...