資料結構和演算法之路 堆和堆排序

2021-09-22 17:53:23 字數 3388 閱讀 5456

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個結點往上冒,將結點在陣列中的更靠前,主要用於insert

2.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遍,時間複雜度...