程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 最小-最大堆的實現

最小-最大堆的實現

編輯:C++入門知識

[cpp]   最小-最大堆的實現:   [cpp]   /*  最小最大堆的性質:  1. 對於在偶數深度上的任意節點X,存儲在X上的關鍵字小於它的父親但是大於它的祖父  2. 對於在奇數深度上的任意節點X,存儲在X上的關鍵字大於它的父親但是小於它的祖父    從其中可以推理出:  1.任意節點X,其關鍵字的值必定在它的父親和其祖父之間,也就是說X所在的層上所有關鍵字    的值必定處於它的父親層和它的祖父層之間  2.所有偶數層從根向下關鍵字的值遞增,所有奇數層從根向下關鍵字的值遞減  3.所有奇數層的關鍵字值大於偶數層的關鍵字值  4.如何判定一個節點X是在奇數層還是偶數層:就是判定X節點的祖父節點在奇數層還是偶數層,    遞歸的方法就可以實現,{ while(i>1) i/=4; if(i==1) 偶數層 ; if(i==0) 奇數層 ; } 其中    i是節點X的位置。時間復雜度是O(logN)    另外一種方法,根據3.如果X的節點值小於其父親的節點值,則X在偶數層上,前提是X的值滿足最大最小    堆的性質,同時X的值和其父親的值不相等  5.一個最大最小堆的例子                            1               /                    \              19                    15          /        \            /        \         2          4          3          6      /     \    /     \    /     \    /     \     16     18  9      10  7      12  13     14    /  \   /  \   5   11 8   17    */      #include <stdio.h>   #include <string.h>   #include <stdlib.h>         typedef struct MinMaxStruct* MinMaxHeap;   typedef int Position;   typedef int ElementType;   #define MinElement 0   #define MaxElement 0x00ffffff   struct MinMaxStruct   {       int Capacity;       int Size;       ElementType* Elements;   };      static int   IsEmpty(MinMaxHeap H)   {       return H->Size ? 0 : 1;   }   static int   IsFull(MinMaxHeap H)   {       return H->Size == H->Capacity;   }      static MinMaxHeap   Initalize(int MaxElements)   {       MinMaxHeap H;       int Size;       Size = sizeof(struct MinMaxStruct) + (MaxElements + 1) * sizeof(ElementType);       H = malloc(Size);       if(H == NULL) return NULL;       H->Capacity = MaxElements;       H->Size = 0;       H->Elements = (ElementType*)(H + 1);       H->Elements[0] = MinElement;       return H;   }   static void   Destroy(MinMaxHeap H)   {       H->Capacity = 0;       H->Size = 0;       free(H);   }         /*   * 上濾:節點值從大變小的過程叫做上濾   * 上濾的過程包括從根開始向下的所有奇數層,轉換到偶數層後   * 再從底部向上經歷所有的偶數層   * 插入:在樹的底端進行,要麼經過上濾到偶數層上,要麼   * 下濾到奇數層上   * 刪除最大值:從堆的2或3的位置求出最大值,把對最後一個   * 數據放到最大值的位置,然後經過一個完整的上濾過程   * DecreaseKey:減小關鍵字的值,是將關鍵字位置減少後,對   * 其經歷一個完整的上濾過程   */   static Position   PercolateUp(Position i, MinMaxHeap H)   {       Position j = i;       ElementType X;          H->Elements[0] = MinElement;       X = H->Elements[i];          while(j>1) j = j >> 2;          /* 奇數層,先下濾,再上濾,偶數層直接上濾 */       if(j==0)       {           /* 下濾到一個奇數層上 */           for( ; i*4 < H->Size; i = j)           {               int k;               j = k = 4*i;               if(H->Size>=k+1 && H->Elements[j] < H->Elements[k+1]) j = k+1;               if(H->Size>=k+2 && H->Elements[j] < H->Elements[k+2]) j = k+2;               if(H->Size>=k+3 && H->Elements[j] < H->Elements[k+3]) j = k+3;               if(H->Elements[j] > X)                   H->Elements[i] = H->Elements[j];               else                   break;           }           H->Elements[i] = X;           /* 進行奇偶層互換,把偶數層上的一個最大值替換到奇數層上 */           j = i*2;           if(j < H->Size)  //j的值最大可以是H->Size-1為偶數,H->Size是奇數值           {               if(H->Elements[j] < H->Elements[j+1]) j++;           }           else if(j > H->Size) j = i/2;              if(H->Elements[j] > X)           {               H->Elements[i] = H->Elements[j];               i = j;           }           else               return i;       }       /* 上濾 */       for( ; H->Elements[i/4] > X ; i /= 4)           H->Elements[i] = H->Elements[i/4];       H->Elements[i] = X;       return i;   }   /*   * 下濾:節點值從小變大的過程叫做下濾   * 下濾的過程包括從根開始向下的所有偶數層,轉換到奇數層後   * 再從底部向上經歷所有的奇數層   * 插入:在樹的底端進行,要麼經過上濾到偶數層上,要麼   * 下濾到奇數層上   * 刪除最小值:從堆的1位置求出最小值,把對最後一個   * 數據放到1位置上,然後經過一個完整的下濾過程   * IncreaseKey:增大關鍵字的值,是將關鍵字位置增加後,對   * 其經歷一個完整的下濾過程   */   static Position   PercolateDown(Position i, MinMaxHeap H)   {       int j = i;       ElementType X;          H->Elements[0] = MaxElement;       X = H->Elements[i];          while(j>1) j = j >> 2;          /* 偶數層,先下濾,再上濾,奇數層直接上濾 */       if(j==1)       {           /* 下濾到一個偶數層上 */           for( ; i*4 < H->Size; i = j)           {               int k;               j = k = 4*i;               if(H->Size>=k+1 && H->Elements[j] > H->Elements[k+1]) j = k+1;               if(H->Size>=k+2 && H->Elements[j] > H->Elements[k+2]) j = k+2;               if(H->Size>=k+3 && H->Elements[j] > H->Elements[k+3]) j = k+3;               if(H->Elements[j] < X)                   H->Elements[i] = H->Elements[j];               else                   break;           }           H->Elements[i] = X;           /* 進行奇偶層互換,把奇數層上的一個最小值替換到偶數層上 */           j = i*2;           if(j < H->Size)  //j的值最大可以是H->Size-1為偶數,H->Size是奇數值           {               if(H->Elements[j] > H->Elements[j+1]) j++;           }           else if(j > H->Size) j = i/2;              if(H->Elements[j] < X)           {               H->Elements[i] = H->Elements[j];               i = j;           }           else               return i;       }       /* 上濾 */       for( ; H->Elements[i/4] < X ; i /= 4)           H->Elements[i] = H->Elements[i/4];       H->Elements[i] = X;       return i;   }      /*   * 插入:   * 在堆的最後的位置插入關鍵字,要麼經歷上濾過程   * 要麼經歷下濾過程   */   static void   Insert(ElementType X, MinMaxHeap H)   {       Position i;       if(IsFull(H)) return ;          i = ++H->Size;       H->Elements[i] = X;       i=PercolateUp(i, H);       if(i==H->Size)           PercolateDown(i, H);   }      /*   * 刪除最小值:   * 將1號位置的值取下來,把最後一個元素放到此處   * 然後經歷一個完整的下濾過程   */   static ElementType   DeleteMin(MinMaxHeap H)   {       ElementType Min;       if(IsEmpty(H)) return MinElement;          Min = H->Elements[1];       H->Elements[1] = H->Elements[H->Size--];       PercolateDown(1, H);       return Min;   }      /*   * 查找最小值   */   static ElementType   FindMin(MinMaxHeap H)   {       return H->Elements[1];   }      /*   * 刪除最大值:   * 對2和3號位置比較大小後,把最後一個元素放到此處   * 然後經歷一個完整的上濾過程   */   static ElementType   DeleteMax(MinMaxHeap H)   {       int i;       ElementType Max;       if(IsEmpty(H)) return MaxElement;          if(H->Elements[2] < H->Elements[3])       {           Max = H->Elements[3];           i = 3;       }       else       {           Max = H->Elements[2];           i = 2;       }       H->Elements[i] = H->Elements[H->Size--];       PercolateUp(i, H);       return Max;   }      /*   * 查找最大值   */   static ElementType   FindMax(MinMaxHeap H)   {       return H->Elements[2] < H->Elements[3] ?           H->Elements[3] : H->Elements[2];   }         /*   * 減小關鍵字的值   * 對i位置的值減小後執行上濾過程   */   static void   DecreaseKey(Position i, ElementType Delta, MinMaxHeap H)   {       if(i <= H->Size)       {           H->Elements[i] -= Delta;           PercolateUp(i, H);       }   }      /*   * 增加關鍵字的值   * 對i位置的值增加後執行下濾過程   */   static void   IncreaseKey(Position i, ElementType Delta, MinMaxHeap H)   {       if(i <= H->Size)       {           H->Elements[i] += Delta;           PercolateDown(i, H);       }   }      /*   * 刪除關鍵字   * 把最後一個位置的值放到i位置   * 如果刪除值比最後一個值小,相當於增加了i位置的值,   * 執行下濾過程   * 如果刪除值比最後一個值大,相當於減小了i位置的值,   * 執行上濾過程   */   static void   Delete(Position i, MinMaxHeap H)   {       ElementType Del;       if(i <= H->Size)       {           Del = H->Elements[i];           H->Elements[i] = H->Elements[H->Size--];           if(Del < H->Elements[i])               PercolateDown(i, H);           else if(Del > H->Elements[i])               PercolateUp(i, H);       }   }                  /*   * 測試例程    */   void MinMaxHeapTest(void)   {       int i;       MinMaxHeap H;          H = Initalize(1000);       if(H==NULL) return;          for(i=1; i<1000; i++)           Insert(i,H);              IncreaseKey(1,1000,H);          for(i=0; i<400; i++)       {           printf("% 3d--% 3d\n",DeleteMin(H), DeleteMax(H));       }       Destroy(H);   }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved