二叉堆的一些基本操作,以及升序降序
阿新 • • 發佈:2019-01-13
我要理解二叉樹如何定義一個堆的
- 必須是一顆完全二叉樹
- 我們可以分大堆和小堆
- 這裡主要通過順序連結串列的方法定義堆
-
這是一個從上往下的大堆
-
我們要如何儲存這個堆了,顯然我們需要一個數組,然後通過寫演算法實現這個堆的順序儲存。
-
這裡主要說一下堆的升序與降序,以及初始化,插入刪除吧。
-
堆其實理解起來相比二叉樹的鏈式儲存要容易很多,堆升序時候我們其實主要需要的這是一個判斷條件結點是否存在
以及二叉樹的一個基本關係式,parent = child * 2 + 1 || parent = child * 2 + 2 -
好了還是看程式碼吧,短時間這個我也不知道怎麼說了
#include <stddef.h> #include <stdio.h> #include <assert.h> typedef struct Heap { int array[100]; int size; } Heap; static void Swap(int *a, int *b) { int t = *a; *a = *b; *b = t; } void HeapInit(Heap *pH, int source[], int size) { for (int i = 0; i < size; i++) { pH->array[i] = source[i]; } pH->size = size; } void HeapAdjustDown(Heap *pH, int root) { int parent = root; while (1) { // 先判斷有沒有孩子(葉子結點) // 陣列角度去想 -> 孩子的下標是否越界 // 只要判斷左孩子的下標(因為是完全二叉樹) int left = parent * 2 + 1; if (left >= pH->size) { // 越界,沒有左孩子,也肯定沒有右孩子 return; } // 一定有左孩子 int maxChild = left; if (2 * parent + 2 < pH->size && pH->array[2 * parent + 2] > pH->array[left]) { // 前一個條件是判斷右孩子有沒有 // 後一個條件判讀是右孩子是否比左孩子大 maxChild = 2 * parent + 2; } if (pH->array[parent] > pH->array[maxChild]) { return; } // 交換 root 和 maxChild 下標所在的值 int t = pH->array[parent]; pH->array[parent] = pH->array[maxChild]; pH->array[maxChild] = t; parent = maxChild; } } // 1. 陣列的越界判斷不對, 是否 == size // 2. array[left] == NULL array -> int[] 這麼判斷左孩子在不在是錯的 // 3. 交換的時候,交換的下標,而不是下標所在的值 void HeapAdjustDown2(Heap *pH, size_t root) { size_t parent = root; size_t left, right; size_t maxChild; left = 2 * root + 1; right = 2 * root + 2; while (left < (size_t)pH->size) { maxChild = left; if (right < (size_t)pH->size && pH->array[left] < pH->array[right]) { maxChild = right; } if (pH->array[maxChild] < pH->array[parent]) { break; } Swap(pH->array + maxChild, pH->array + parent); parent = maxChild; left = 2 * parent + 1; right = 2 * parent + 2; } // left 不存在 } // i-- 寫成 i++ void HeapMakeHeap(Heap *pH) { // [(size - 2) / 2, 0] // 理解迴圈的區間的來歷 for (int i = (pH->size - 2) / 2; i >= 0; i--) { HeapAdjustDown(pH, i); } } void HeapPop(Heap *pH) { pH->array[0] = pH->array[pH->size - 1]; pH->size--; HeapAdjustDown(pH, 0); } int HeapTop(const Heap *pH) { return pH->array[0]; } void HeapAdjustUp(Heap *pH, int child) { int parent; while (child > 0) { parent = (child - 1) / 2; if (pH->array[parent] >= pH->array[child]) { return; } Swap(pH->array + parent, pH->array + child); child = parent; } } void HeapPush(Heap *pH, int data) { assert(pH->size < 100); pH->array[pH->size++] = data; HeapAdjustUp(pH, pH->size - 1); } #include <stdio.h> void Test() { int array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 }; int size = sizeof(array) / sizeof(int); Heap heap; HeapInit(&heap, array, size); HeapMakeHeap(&heap); HeapPush(&heap, 100); printf("%d\n", HeapTop(&heap)); printf("建堆完成\n"); } int main() { Test(); return 0; }
我們初始化放入的資料是 int array[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
我們看一下我們分別降序升序以後隊中元素的變化吧
- 降序以後
- 我們插入100升序以後
- 好了,大概就這樣了。