1.是一種完全二叉樹,第n層至少有 2 ^(n-1)個結點2.大頂堆:父節點 大於左右子結點;小頂堆:父節點小於左右子結點
3.用一維陣列來表示
4.最後乙個非葉結點的下標 = length / 2 -1
parent = floor( ( (i -1) / 2 ) i > 1
left = i * 2+1;
right = i * 2 + 2;
1.shiftup( i ):跟父結點比較,將第i個結點往上冒,將結點在陣列中的更靠前,主要用於insert2.shiftdown( i , n) : n代表當前參與構建堆的結點數量,跟左右子結點比較,與shiftup操作相反,主要用於remove,又稱為堆化(heapify)
shiftup 或者 shiftdown 是乙個遞迴的過程,所以它的時間複雜度是 o(log n),這兩個是堆的基本方法,其他都是基於它們產生的
3.insert( value ):將value新增到堆尾,然後呼叫shiftup調整堆
4.remove( ):移除堆頂結點,然後將堆尾結點放在堆頂,呼叫shiftdown調整堆
// shiftup
/** * 往上冒 (小頂堆)
* @param arr 堆陣列
* @param i 往上冒的結點下標
*/function shiftup(arr, i)
// 為交換騰出坑
let tmpvalue = arr[i];
while (i === 1 || math.floor((i - 1) / 2) >= 0) else
}arr[i] = tmpvalue;
}
1.基本思想:a.先將無序陣列構建成大頂堆(小頂堆)— 從最後的乙個非葉結點開始,從下往上迴圈調整每個小二叉樹,使其形成區域性最優解
b.將根結點與葉結點交換位置 — 為了下次調整堆得時候,將最大(最小)的結點排除
c.迴圈的重新構建一次堆 — 因為已經構成了區域性最優解,這次從上往下調整,最多調整乙個分支
2.選擇排序,所以是不穩定的
3.o(nlogn) — 第一次構建堆,用一次for迴圈為o(n),以後每次迴圈調整 最後再遍歷乙個分支,即o(logn)
4.注:堆排序的主要應用並不是全排(快速排序更方便)更適用最優n解得問題,或者動態的資料;
對於已經構建好的堆,主要有兩個操作,插入和刪除
插入:插入到堆尾,然後從下往上調整堆
刪除:將堆頂移動到堆尾,然後從上往下調整堆
// 堆排序
function heapsort(arr)
// 最後乙個非葉節點的下標
let i = math.floor(arr.length / 2) - 1;
// 構建大堆序
for (; i >= 0; i--)
// 調換堆頂和結點位置,再從上往下調整堆
for (let j = arr.length - 1; j > 0; j--)
}/**
* 調整堆結構
* 從左往右,從下到上
*/function adjustheap(arr, i, length)
if (arr[k] < temp) else
}arr[i] = temp;
}let arr = [12, 34, 2, 34, 5, 1, 0, 2, 5, 8, 9, 6, 3, 2, 33, 3, 3, 3, 5, 6, 8];
heapsort(arr);
console.log(arr);
用js 手動實現了堆結構,以及主要方法
/**
* 堆結構(小頂堆為例)
*/class heap
get size()
return this.arr.length;
}/**
* 將i位置的元素往上冒
* @param i
*/shiftup(i)
let tempvalue = this.arr[i];
while (i === 1 || math.floor((i - 1) / 2) >= 0) else
}this.arr[i] = tempvalue;
}/**
* 往下沉 (堆化heapify)
* @param i
*/shiftdown(i, size)
let tempvalue = this.arr[i];
let k = i * 2 + 1;
while (k < length)
if (this.arr[k] < tempvalue) else
}this.arr[i] = tempvalue;
}/**
* 插入新元素
* 放到堆尾,然後往上冒
* @param value
*/insert(value)
/*** 刪除堆頂元素
* 1.移除堆頂
* 2.將堆尾的結點移到堆頂
* 3.往下沉
*/remove()
if (this.size === 1) else
}/**
* 堆排序
* 1.先構建堆
* 2.再迴圈remove堆頂
* @param heap
*/sort()
}/**
* 構建堆
** @param heap
*/static createheap(heap)
//從最後乙個非葉結點開上往上堆化
let node = math.floor(arr.length / 2) - 1;
while (node >= 0)
return true;
}}let arr = [12, 34, 2, 34, 5, 1, 0, 2, 5, 8, 9, 6, 3, 2, 33, 3, 3, 3, 5, 6, 8];
let heap = new heap(arr);
heap.createheap(heap);
// heap.sort();
console.log(heap.arr);
// heap.remove();
heap.insert(-1);
console.log(heap.arr);
資料結構和演算法 堆和堆排序
堆是一種特殊的樹,他有倆個要求 1 堆是乙個完全二叉樹 2 堆每乙個節點的值,都大於等於 或小於等於 其左右子樹節點的值 解釋一下 第一點,完全二叉樹就是除了最後一層,其它層的節點數都是滿的,最後一層的節點都靠左排列 每個節點都大於等於左右子樹節點的叫做大頂堆,每個節點都小於等於左右子樹節點的叫做小...
資料結構 堆(堆排序和模擬堆)
輸入乙個長度為n的整數數列,從小到大輸出前m小的數。輸入格式 第一行包含整數n和m。第二行包含n個整數,表示整數數列。輸出格式 共一行,包含m個整數,表示整數數列中前m小的數。資料範圍 1 m n 10 5,1 數列中元素 10 9 輸入樣例 5 34 5 1 3 2 輸出樣例 1 2 3 演算法的...
資料結構 排序演算法 選擇排序和堆排序
選擇排序 1.基本思想 以公升序為例,假設有n個資料,每一趟在後面n i的待排序的資料元素集合中選出關鍵碼最小的資料元素,作為有序序列的第i個元素,直至待排序集合中只剩下1個元素。2.操作步驟 舉乙個例子 3.演算法效能 時間複雜度 直接選擇演算法需要遍歷每一趟選出最小的乙個數,遍歷n遍,時間複雜度...