實現數據結構:堆。swift
/* * 堆類型 * small 小根堆 * big 大根堆 */
enum HeapType {
case small, big
}
/* * 堆 */
class Heap<T: Comparable> {
private var _arr: [T];
private var _type: HeapType;
/* * 使用數組建立堆 * @param {[T]} - arr 建立堆的數組 * @param {HeapType} - type 堆類型 */
init(arr: [T], type: HeapType = .big) {
self._arr = arr;
self._type = type;
self._create();
}
/* * 調整堆:調整以idx爲頂的3元素子堆,若頂部元素不是最大/最小,則調整爲最大/最小 * @param {Int} - idx 表示調整以idx爲頂的3元素子堆 * @return {Bool} - 調整成功返回true,無需調整返回false */
@discardableResult
private func _adjust(_ idx: Int) -> Bool{
let maxAdjustIdx = Int(ceilf(Float(_arr.count) / 2) - 1);
if idx > maxAdjustIdx || idx < 0{
return false;
}
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 {
if let l = left, let r = right {
let v = self._type == .big ? max(t, l, r) : min(t, l, r);
switch v {
case l:
swapArr(arr: &_arr, f: leftIdx, t: idx);
_adjust(leftIdx);
return true;
case r:
swapArr(arr: &_arr, f: rightIdx, t: idx);
_adjust(rightIdx);
return true;
default:
break;
}
}else if let l = left {
let b = self._type == .big ? (l > t) : (l < t);
if b {
swapArr(arr: &_arr, f: leftIdx, t: idx);
_adjust(leftIdx);
return true;
}
}else if let r = right {
let b = self._type == .big ? (r > t) : (r < t);
if b {
swapArr(arr: &_arr, f: rightIdx, t: idx);
_adjust(rightIdx);
return true;
}
}
}
return false;
}
/** * 建立堆,依次調整 n/2 -> 0 元素 */
private func _create(){
let maxAdjustIdx = Int(ceilf(Float(_arr.count) / 2) - 1);
for i in stride(from: maxAdjustIdx, to: -1, by: -1){
_adjust(i);
}
}
/** * 彈出一個元素,移除頂部元素,而後令頂部元素等於最後一個元素,最後調整頂部元素 * @return [T?] 返回頂部元素 */
func pop() -> T? {
let first = _arr.first;
if first != nil {
if _arr.count <= 1 {
_arr.removeLast();
}else{
swapArr(arr: &_arr, f: 0, t: _arr.count - 1);
_arr.removeLast();
_adjust(0);
}
}
return first;
}
/** * 插入一個元素,插入到尾部,依次調整該元素的頂部元素,直到無需調整或下標爲0 * @param {T} - t 插入的元素 */
func push(_ t: T){
_arr.append(t);
var idx = Int(ceilf(Float(_arr.count - 1) / 2) - 1);
while true {
if !_adjust(idx){
break;
}
if idx == 0{
break;
}
idx = Int(ceilf(Float(idx) / 2) - 1);
}
}
/** * 返回當前元素數量 * @return {Int} 返回堆內元素數量 */
func count() -> Int{
return _arr.count;
}
}
複製代碼
//常量
const BigHeap = 1;
const SmallHeap = 2;
//構造函數
function Heap(type, arr, compareFunction){
this.type = type;
this.arr = arr;
this.compareFunction = compareFunction;
this._createHeap(arr);
}
//數組交換
Heap._swap = function(i,j,arr){
let tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//比較值
Heap.prototype._compare = function(v1, v2){
if(this.type == SmallHeap){
if(v2 == null){
return true;
}else{
if(this.compareFunction){
return this.compareFunction(v1, v2) == -1;
}else{
return v1 < v2;
}
}
}else{
if(v2 == null){
return true;
}else{
if(this.compareFunction){
return this.compareFunction(v1, v2) == 1;
}else{
return v1 > v2;
}
}
}
}
//調整堆的第i個結點
Heap.prototype._adjustNode = function(i, arr){
let leftChildIdx = 2 * i + 1;
let leftValue = null;
if(leftChildIdx < arr.length){
leftValue = arr[leftChildIdx];
}
let rightChildIdx = 2 * i + 2;
let rightValue = null;
if(rightChildIdx < arr.length){
rightValue = arr[rightChildIdx];
}
if(!leftValue && !rightValue){
return;
}
let exchangeIdx = null;
//左值存在而且大於根結點
if(leftValue && this._compare(leftValue, arr[i])){
//右值存在而且大於左結點
if(rightValue && this._compare(rightValue, leftValue)){
//右值交換
exchangeIdx = rightChildIdx;
}else{
//左值交換
exchangeIdx = leftChildIdx;
}
}else if(rightValue && this._compare(rightValue, leftValue)){
//右值交換
exchangeIdx = rightChildIdx;
}
if(exchangeIdx != null){
Heap._swap(exchangeIdx, i, arr);
//交換完畢後,新的子結點也須要調整
this._adjustNode(exchangeIdx, arr);
}
}
//根據數組建立堆
Heap.prototype._createHeap = function(arr){
let len = arr.length;
if(len <= 1){
return;
}
//最後一個非葉子結點
let lastNonLeafIdx = Math.floor(len / 2) - 1;
//依次調整每一個結點
for (let index = lastNonLeafIdx; index >= 0; index--) {
this._adjustNode(index, arr);
}
}
//插入
Heap.prototype.insert = function(ele){
this.arr.push(ele);
let adjustIdx = this.arr.length;
while(adjustIdx > 0){
adjustIdx = Math.ceil(adjustIdx / 2) - 1;
this._adjustNode(adjustIdx, this.arr);
if(adjustIdx <= 0){
break;
}
}
}
//刪除
Heap.prototype.remove = function(){
if(this.arr.length <= 0){
return null;
}
let value = this.arr[0];
if(this.arr.length > 1){
this.arr[0] = this.arr.pop();
this._adjustNode(0, this.arr);
}else{
this.arr.pop();
}
return value;
}
//是否爲空
Heap.prototype.empty = function(){
return this.arr.length == 0 || this.arr[0] == null;
}
複製代碼
h = logn
2^0*h
2^1*(h-1)
2^(h-1)*1
count=2^0*h + 2^1*(h-1) + 2^2*(h-2) + ... + 2^(h-1)*(h-(h-1))
//使用錯位相減count*2 = 2^1*h + 2^2*(h-1) + 2^3*(h-2) + ... + 2^h*(h-(h-1))
count = count*2-count = 2^1 + 2^2 + ... + 2^(h-1) + 2^h - 2^0*h
count = 2^(h+1) - 2 - h
count = 2n - 2 - logn