0.1) 本文文字描述部分轉自 數據結構與算法分析, 旨在理解 優先隊列——左式堆 的基礎知識;
0.2) 本文核心思路均爲原創, 源代碼部分借鑑 數據結構與算法分析 ;
0.3) for original source code, please visit https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter6/p145_leftist_heapnode
1)相關定義git
1.1)零路徑長度定義: 到沒有兩個兒子的節點最短距離, 即零路徑長Npl 定義爲 從 X 到一個沒有兩個兒子的 節點的最短路徑的長;也即, 非葉子節點到葉子節點的最少邊數,其中NULL的零路徑長爲-1, 葉子節點的零路徑長爲0;(乾貨——零路徑長的定義—— 非葉子節點到葉子節點的最少邊數,很是重要,由於左式堆的定義是基於零路徑長的定義的)
github
1.2)左式堆定義:一棵具備堆序性質的二叉樹 + 零路徑長:左兒子 ≧ 右兒子 + 父節點 = min{兒子} +1;(乾貨——左式堆的定義是創建在具備堆序性的二叉樹上,而不是二叉堆上)算法
2)merge操做原則: 根值大的堆與根值小的堆的右子堆合併;(乾貨——merge操做原則)
3)merge操做存在的三種狀況(設堆H1的根值小於H2)數據結構
左式堆合併原則:大根堆H2與小根堆H1的右子堆合併 (乾貨——左式堆合併原則)
具體分三種狀況(設堆H1的根值小於H2)
post
Conclusion) 如今才知道,左式堆的merge操做實際上是一個遞歸的過程, 看以下解析; (乾貨——這是最後解析merge操做啦)
spa
Attention once again)code
source code at a glance )blog
#include "leftist_heap.h" // swap the left and the right in priority queue. void swap(PriorityQueue h1) { PriorityQueue temp; temp = h1->left; h1->left = h1->right; h1->right = temp; } // analog print directories and files name in the BinaryTree, which involves postorder traversal. void printPreorder(int depth, TreeNode root) { int i; if(root) { for(i = 0; i < depth; i++) printf(" "); printf("%d\n", root->value); printPreorder(depth + 1, root->left); // Attention: there's difference between traversing binary tree and common tree. printPreorder(depth + 1, root->right); } else { for(i = 0; i < depth; i++) printf(" "); printf("NULL\n"); } } // insert an element with value into the priority queue. PriorityQueue insert(ElementType value, PriorityQueue pq) { TreeNode node; node = (TreeNode)malloc(sizeof(struct TreeNode)); if(!node) { Error("failed inserting, for out of space !"); return pq; } node->left = NULL; node->right = NULL; node->nullPathLen = 0; node->value = value; if(pq == NULL) // means that just only creating a node with value. { return node; } else { return merge(node, pq); } } // return the minimal between a and b. int minimal(int a, int b) { return a > b ? b : a; } // merge the priority queue h1 and h2. PriorityQueue merge(PriorityQueue h1, PriorityQueue h2) { if(h1 == NULL) { return h2; } else if(h2 == NULL) { return h1; } if(h1->value > h2->value) { return innerMerge(h2, h1); } else { return innerMerge(h1, h2); } } // merge the priority queue h1 and h2. PriorityQueue innerMerge(PriorityQueue h1, PriorityQueue h2) { if(h1->left == NULL) { h1->left = h2; } else { h1->right = merge(h1->right, h2); } // update the null path length if(h1->right == NULL) { h1->nullPathLen = 0; } else { h1->nullPathLen = minimal(h1->left->nullPathLen, h1->right->nullPathLen) + 1; // exchange the left and the right if(h1->left->nullPathLen < h1->right->nullPathLen) { swap(h1); } } return h1; } // delete the minimal element in the priority queue. PriorityQueue deleteMin(PriorityQueue h1) { PriorityQueue left; PriorityQueue right; if(!h1) { Error("failed deleteMin, for the root doesn't point to any position!"); return NULL; } left = h1->left; right = h1->right; free(h1); return merge(left, right); } int main() { PriorityQueue h1; PriorityQueue h2; int data[] = {21, 10, 23, 14, 3, 26, 17, 8}; int data2[] = {18, 12, 33, 24, 6, 37, 7, 18}; int i; h1 = insert(data[0], NULL); for(i=1; i<8; i++) { h1 = insert(data[i], h1); } printf("\n=== after the leftist heap h1 is merged===\n"); printPreorder(1, h1); h2 = insert(data2[0], NULL); for(i=1; i<8; i++) { h2 = insert(data2[i], h2); } printf("\n=== after the leftist heap h2 is merged===\n"); printPreorder(1, h2); h1 = merge(h1, h2); printf("\n=== after both h1 and h2 are merged===\n"); printPreorder(1, h1); h1 = deleteMin(h1); printf("\n=== after executing deleteMin operation ===\n"); printPreorder(1, h1); return 0; }
printing results are as follows) 遞歸
Attention for analog between results and the 2 images above.