演算法(4)資料結構 堆

2021-09-24 07:14:50 字數 3172 閱讀 6306

實現資料結構:堆。

堆一般使用陣列來表示,其中某個節點下標i的兩個子節點的下標為 2i+1 和 2i+2。堆是一棵完全二叉樹。

堆有3種基本操作:建立,插入,刪除。

這3種操作都需要通過「調整堆」的方式來實現。調整堆是指,對堆中的某個節點,若它的值和它所有子節點相比,不是最大/最小,那麼就需要將最大/最小的元素和當前節點交換,這種操作成為「調整堆」。

建立可以用插入來實現(複雜度o(nlogn)),也可以使用陣列直接轉換成堆(複雜度o(n))。

假設陣列長度為n,那麼這個陣列轉成堆,需要從第乙個有子節點的節點((n - 1)/2或(n - 2)/2開始,倒序「調整堆」,直到下標為0。

插入操作可以先將資料插入到陣列尾部,然後依次調整該資料的父節點,父節點的父節點......直到根節點。

刪除操作可以先將陣列首尾節點互換,然後刪除最後面的元素,最後再調整根節點即可。

/*

* 堆型別

* small 小根堆

* big 大根堆

*/enum

heaptype

/* * 堆

*/class

heap

- arr 建立堆的陣列

* @param - type 堆型別

*/init(arr: [t], type: heaptype = .big)

/** 調整堆:調整以idx為頂的3元素子堆,若頂部元素不是最大/最小,則調整為最大/最小

* @param - idx 表示調整以idx為頂的3元素子堆

* @return - 調整成功返回true,無需調整返回false

*/@discardableresult

private

func

_adjust

(_ idx: int)

-> bool

let leftidx = 2 * idx + 1;

let rightidx = 2 * idx + 2;

let top: t? = _arr[idx];

letleft: t? = leftidx < _arr.count ? _arr[leftidx]: nil;

letright: t? = rightidx < _arr.count ? _arr[rightidx]: nil;

iflet t = top

}else

iflet l = left

}else

iflet r = right }}

return

false;

}/**

* 建立堆,依次調整 n/2 -> 0 元素

*/private

func

_create

() }

/*** 彈出乙個元素,移除頂部元素,然後令頂部元素等於最後乙個元素,最後調整頂部元素

* @return [t?] 返回頂部元素

*/func

pop()

-> t? else

}return first;

}/**

* 插入乙個元素,插入到尾部,依次調整該元素的頂部元素,直到無需調整或下標為0

* @param - t 插入的元素

*/func

push

(_ t: t)

if idx == 0

idx = int(ceilf(float(idx) / 2) - 1);}}

/*** 返回當前元素數量

* @return 返回堆內元素數量

*/func

count

() -> int

}複製**

//常量

const bigheap = 1;

const smallheap = 2;

//建構函式

function

heap(type, arr, comparefunction)

//陣列交換

heap._swap = function(i,j,arr)

//比較值

heap.prototype._compare = function(v1, v2)elseelse

}}elseelseelse}}

}//調整堆的第i個結點

heap.prototype._adjustnode = function(i, arr)

let rightchildidx = 2 * i + 2;

let rightvalue = null;

if(rightchildidx < arr.length)

if(!leftvalue && !rightvalue)

let exchangeidx = null;

//左值存在並且大於根結點

if(leftvalue && this._compare(leftvalue, arr[i]))else

}else

if(rightvalue && this._compare(rightvalue, leftvalue))

if(exchangeidx != null)

}//根據陣列建立堆

heap.prototype._createheap = function(arr)

//最後乙個非葉子結點

let lastnonleafidx = math.floor(len / 2) - 1;

//依次調整每個結點

for (let index = lastnonleafidx; index >= 0; index--)

}//插入

heap.prototype.insert = function(ele)

}}//刪除

heap.prototype.remove = function()

let value = this.arr[0];

if(this.arr.length > 1)else

return value;

}//是否為空

heap.prototype.empty = function()

複製**

陣列轉堆的複雜度

每次調整堆最少可能需要1次調整

實際上,需要少量調整的運算元遠遠大於需要多次調整的操作。

堆的插入:o(logn)

堆的刪除:o(logn)

演算法(4)資料結構 堆

實現資料結構 堆。堆一般使用陣列來表示,其中某個節點下標i的兩個子節點的下標為 2i 1 和 2i 2。堆是一棵完全二叉樹。堆有3種基本操作 建立,插入,刪除。這3種操作都需要通過 調整堆 的方式來實現。調整堆是指,對堆中的某個節點,若它的值和它所有子節點相比,不是最大 最小,那麼就需要將最大 最小...

資料結構與演算法 堆結構

1 本質 一顆特殊的樹。2 特性 3 分類 對於每乙個節點的值都大於等於子節點的值的情況,該堆被稱為大頂堆。對於每乙個節點的值都小於等於子節點的值的情況,該堆被稱為小頂堆。4 儲存方式 對於完全二叉樹而言,陣列儲存方式是最節省記憶體的。5 插入節點的時間複雜度 將節點插入到靠左的底層作為新的葉子節點...

資料結構與演算法 堆

堆 完全二叉樹,高度為o lgn 基本操作至多和樹的高度成正比,構建堆的時間複雜度是o n 堆是一顆完全二叉樹,假設有n個節點,樹高h log2 n 證明方法如下 1 假設根節點的高度為0,葉子節點高度為h,每層包含元素個數為2 x,x 從0 到h。2 構建堆的過程是自下而上,對於每層非葉子節點需要...