日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【数据结构】堆 笔记

發布時間:2024/4/11 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【数据结构】堆 笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是堆

優先隊列(Priority Queue):特殊的“隊列”,取出元素的順序是依照元素的優先權(關鍵字)大小,而不是元素進入隊列的先后順序。

若采用數組或鏈表實現優先隊列

數組 :

插入 — 元素總是插入尾部 ~ Θ\ThetaΘ ( 1 )
刪除 — 查找最大(或最小)關鍵字 ~ Θ\ThetaΘ ( n )
從數組中刪去需要移動元素 ~ O( n )

鏈表:

插入 — 元素總是插入鏈表的頭部 ~ Θ\ThetaΘ ( 1 )
刪除 — 查找最大(或最小)關鍵字 ~ Θ\ThetaΘ ( n )
刪去結點 ~ Θ\ThetaΘ ( 1 )

有序數組:

插入 — 找到合適的位置 ~ O( n ) 或 O(log2log_2log2? n )
移動元素并插入 ~ O( n )
刪除 — 刪去最后一個元素 ~ Θ\ThetaΘ ( 1 )

有序鏈表:

插入 — 找到合適的位置 ~ O( n )
插入元素 ~ Θ\ThetaΘ ( 1 )
刪除 — 刪除首元素或最后元素 ~ Θ\ThetaΘ ( 1 )

是否可以采用二叉樹存儲結構?

二叉搜索樹? 一直刪除最大的結點導致樹變斜,不能采用

如果采用二叉樹結構,需要做兩個操作:插入任何結點、刪除最大值,其中更應關注刪除最大值(因為更難做)。可以考慮將樹構造成 將最大值放在樹根,刪除最大值就將根結點拿掉,這就是最大堆。使用完全二叉樹存儲。

優先隊列的完全二叉樹表示

堆的兩個特性

  • 結構性:用數組表示的完全二叉樹;
  • 有序性:任一結點的關鍵字是其子樹所有結點的最大值(或最小值)
    最大堆(MaxHeap)”,也稱“大頂堆”:最大值
    最小堆(MinHeap)”,也稱“小頂堆” :最小值
  • 【例子】:
    最大堆:

    最小堆:

    不是堆:

    不是完全二叉樹
    不滿足根結點是最大的/最小的

    注意:從根結點到任意結點路徑上結點序列的有序性!

    堆的抽象數據類型描述

    類型名稱:最大堆(MaxHeap)
    數據對象集:完全二叉樹,每個結點的元素值不小于其子結點的元素值
    操作集:最大堆H ∈\inMaxHeap,元素item ∈\in ElementType,主要操作有:
    ?MaxHeap Create( int MaxSize ):創建一個空的最大堆。
    ?Boolean IsFull( MaxHeap H ):判斷最大堆H是否已滿。
    ?Insert( MaxHeap H, ElementType item ):將元素item插入最大堆H。
    ?Boolean IsEmpty( MaxHeap H ):判斷最大堆H是否為空。
    ?ElementType DeleteMax( MaxHeap H ):返回H中最大元素(高優先級)。

    最大堆的操作

    創建

    typedef struct HeapStruct *MaxHeap;struct HeapStruct {ElementType *Elements; /* 存儲堆元素的數組 */int Size; /* 堆的當前元素個數 */int Capacity; /* 堆的最大容量 */ }; MaxHeap Create( int MaxSize ) { /* 創建容量為MaxSize的空的最大堆 */MaxHeap H = malloc( sizeof( struct HeapStruct ) );H->Elements = malloc( (MaxSize+1) * sizeof(ElementType));H->Size = 0;H->Capacity = MaxSize;H->Elements[0] = MaxData;/* 定義“哨兵”為大于堆中所有可能元素的值,便于以后更快操作 */return H; }

    插入

    算法:將新增結點插入到從其父結點到根結點的有序序列中

    void Insert( MaxHeap H, ElementType item ) { /* 將元素item 插入最大堆H, 其中H->Elements[0]已經定義為哨兵 */int i;if ( IsFull(H) ) {printf("最大堆已滿");return; } i= ++H->Size; /* i指向插入后堆中的最后一個元素的位置 */ for ( ; H->Elements[i/2] < item; i/=2 )H->Elements[i] = H->Elements[i/2]; /* 向下過濾結點 */ H->Elements[i] = item; /* 將item 插入 */ }

    我們設置H->Element[ 0 ] 是哨兵元素,它不小于堆中的最大元素,控制循環結束。
    時間復雜度T(N) = log2log_2log2? N (樹的高度)

    刪除

    ElementType DeleteMax( MaxHeap H ) { /* 從最大堆H中取出鍵值為最大的元素, 并刪除一個結點 */int Parent, Child;ElementType MaxItem, temp;if ( IsEmpty(H) ) {printf("最大堆已為空");return;}MaxItem = H->Elements[1]; /* 取出根結點最大值 *//* 用最大堆中最后一個元素從根結點開始向上過濾下層結點 */temp = H->Elements[H->Size--];for( Parent=1; Parent*2<=H->Size; Parent=Child ) {Child = Parent * 2;if( (Child!= H->Size) &&(H->Elements[Child] < H->Elements[Child+1]) )Child++; /* Child指向左右子結點的較大者 */if( temp >= H->Elements[Child] ) break;else /* 移動temp元素到下一層 */H->Elements[Parent] = H->Elements[Child];} H->Elements[Parent] = temp;return MaxItem;

    最大堆的建立

    建立最大堆: 將已經存在的N個元素按最大堆的要求存放在一個一維數組中

    方法1: 通過插入操作,將N個元素一個個相繼插入到一個初
    始為空的堆中去,其時間代價最大為O(N logN)。

    方法2: 在線性時間復雜度下建立最大堆。
    (1)將N個元素按輸入順序存入,先滿足完全二叉樹的結構特性
    (2)調整各結點位置,以滿足最大堆的有序特性

    完整代碼

    typedef struct HNode *Heap; /* 堆的類型定義 */ struct HNode {ElementType *Data; /* 存儲元素的數組 */int Size; /* 堆中當前元素個數 */int Capacity; /* 堆的最大容量 */ }; typedef Heap MaxHeap; /* 最大堆 */ typedef Heap MinHeap; /* 最小堆 */#define MAXDATA 1000 /* 該值應根據具體情況定義為大于堆中所有可能元素的值 */MaxHeap CreateHeap( int MaxSize ) { /* 創建容量為MaxSize的空的最大堆 */MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode));H->Data = (ElementType *)malloc((MaxSize+1)*sizeof(ElementType));H->Size = 0;H->Capacity = MaxSize;H->Data[0] = MAXDATA; /* 定義"哨兵"為大于堆中所有可能元素的值*/return H; }bool IsFull( MaxHeap H ) {return (H->Size == H->Capacity); }bool Insert( MaxHeap H, ElementType X ) { /* 將元素X插入最大堆H,其中H->Data[0]已經定義為哨兵 */int i;if ( IsFull(H) ) { printf("最大堆已滿");return false;}i = ++H->Size; /* i指向插入后堆中的最后一個元素的位置 */for ( ; H->Data[i/2] < X; i/=2 )H->Data[i] = H->Data[i/2]; /* 上濾X */H->Data[i] = X; /* 將X插入 */return true; }#define ERROR -1 /* 錯誤標識應根據具體情況定義為堆中不可能出現的元素值 */bool IsEmpty( MaxHeap H ) {return (H->Size == 0); }ElementType DeleteMax( MaxHeap H ) { /* 從最大堆H中取出鍵值為最大的元素,并刪除一個結點 */int Parent, Child;ElementType MaxItem, X;if ( IsEmpty(H) ) {printf("最大堆已為空");return ERROR;}MaxItem = H->Data[1]; /* 取出根結點存放的最大值 *//* 用最大堆中最后一個元素從根結點開始向上過濾下層結點 */X = H->Data[H->Size--]; /* 注意當前堆的規模要減小 */for( Parent=1; Parent*2<=H->Size; Parent=Child ) {Child = Parent * 2;if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )Child++; /* Child指向左右子結點的較大者 */if( X >= H->Data[Child] ) break; /* 找到了合適位置 */else /* 下濾X */H->Data[Parent] = H->Data[Child];}H->Data[Parent] = X;return MaxItem; } /*----------- 建造最大堆 -----------*/ void PercDown( MaxHeap H, int p ) { /* 下濾:將H中以H->Data[p]為根的子堆調整為最大堆 */int Parent, Child;ElementType X;X = H->Data[p]; /* 取出根結點存放的值 */for( Parent=p; Parent*2<=H->Size; Parent=Child ) {Child = Parent * 2;if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )Child++; /* Child指向左右子結點的較大者 */if( X >= H->Data[Child] ) break; /* 找到了合適位置 */else /* 下濾X */H->Data[Parent] = H->Data[Child];}H->Data[Parent] = X; }void BuildHeap( MaxHeap H ) { /* 調整H->Data[]中的元素,使滿足最大堆的有序性 *//* 這里假設所有H->Size個元素已經存在H->Data[]中 */int i;/* 從最后一個結點的父節點開始,到根結點1 */for( i = H->Size/2; i>0; i-- )PercDown( H, i ); }

    總結

    以上是生活随笔為你收集整理的【数据结构】堆 笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。