演算法(4)資料結構 堆

2021-09-17 03:42:10 字數 3351 閱讀 5581

實現資料結構:堆。

堆一般使用陣列來表示,其中某個節點下標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];

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

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

if let t = top

}else if let l = left

}else if let 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)

else

else}}

else

else

else}}

}//調整堆的第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 構建堆的過程是自下而上,對於每層非葉子節點需要...