1. 程式人生 > >堆及堆的應用

堆及堆的應用

Heap.h

#ifndef __HEAP_H__
#define __HEAP_H__

typedef int HPDataType;
typedef struct Heap
{
   HPDataType* _hp;
   int _capacity;
   int _size;

}Heap;


typedef struct PriorityQueue 
{ 
    Heap hp; 
}PriorityQueue; 

void CreatHeap(Heap* hp, int* array, int size);//建立堆
void InitHeap(Heap* hp); // 初始化堆 
void PrintHeap(Heap hp);//列印堆 void InsertHeap(Heap* hp, HPDataType data);//插入資料 void RemoveHeap(Heap* hp);//刪除堆頂元素 int SizeHeap(Heap*hp);//堆大小 int EmptyHeap(Heap* hp);//判空 HPDataType TopHeap(Heap* hp);//找出堆頂元素 void AdjustDown(Heap* hp, int parent);//向下調整 void AdjustUp(Heap* hp, int child);//向上調整 void _CheakCapacity(Heap* hp);//擴容
void DestroyHeap(Heap* hp); // 銷燬堆 int Less(HPDataType left, HPDataType right); // 小於比較 int Greater(HPDataType left, HPDataType right); // 大於比較 void InitPriorityQueue(PriorityQueue* q); void PushPriorityQueue(PriorityQueue* q, HPDataType data); void PopPriorityQueue(PriorityQueue* q); int TopPriorityQueue(PriorityQueue* q); int
SizePriorityQueue(PriorityQueue* q); int EmptyPriorityQueue(PriorityQueue* q); void Topk(Heap* q, int k);//海量資料中的topk問題 void HeapSort(Heap *q);//堆排序

Heap.c

#include "Heap.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>


void CreatHeap(Heap* hp, int* array, int size)
{
    int i = 0;
    int root = (size-2)/2;
    assert(hp);
    hp->_hp = (HPDataType*)malloc(sizeof(HPDataType)*size);
    if(NULL == hp->_hp)
    {
        assert(hp);
        return;
    }

    hp->_capacity = size;
    hp->_size = size;
    for(i=0;i<size;i++)
    {
        hp->_hp[i] = array[i];
    }
    for(i=root;i>=0;i--)
    {
      AdjustDown(hp,i);
    }

}
void InitHeap(Heap* hp)
{
    assert(hp);
    hp->_hp = (HPDataType*)malloc(sizeof(HPDataType));
    if(NULL == hp->_hp)
    {
       return;
    }
    hp->_capacity = 1;
    hp->_size = 0;

}
void PrintHeap(Heap hp)
{
    int i = 0;
    for(i=0;i< hp._size;i++)
      {
        printf("%d ", hp._hp[i]);
      }

}
void Swap(int* left,int* right)
{
    int temp = 0;
     temp = *left;
     *left = *right;
     *right = temp;

}

int Greater(HPDataType left, HPDataType right)
{
    if (left > right)
        return 1;
    return 0;
}


int Less(HPDataType left, HPDataType right)
{
    if (left < right)
        return 1;
    return 0;
}
void AdjustDown(Heap* hp, int parent)
{
   int child = 2*parent+1;
   assert(hp);
   while(child < hp->_size)
   {
       if(Greater(hp->_hp[child],hp->_hp[child+1]) && (child+1) < hp->_size)
       {
         child = child+1;
       } 
       if(Greater(hp->_hp[parent] , hp->_hp[child]))
           {
            Swap(&hp->_hp[parent],&hp->_hp[child]);
             parent = child;
             child = 2*parent+1;
           }
       else
           return;

   }

}
void AdjustUp(Heap* hp, int child)
{
   int parent = (child-1)/2;
   assert(hp);
   while(child != 0)
   {
       if(Greater(hp->_hp[parent],hp->_hp[child]))
       {
           Swap(&hp->_hp[parent],&hp->_hp[child]);
               child = parent;
               parent = (child-1)/2;

       }
       else
           return;
   }

}
void _CheakCapacity(Heap* hp)
{
    int i = 0;
    assert(hp);
    if(hp->_capacity == hp->_size)
   {
       hp->_hp = (HPDataType*)realloc(hp->_hp,sizeof(HPDataType)*(hp->_capacity)*2); 
       if(NULL == hp->_hp)
       {

        return;
       }
       hp->_capacity = 2*hp->_capacity;
   }


}
void InsertHeap(Heap* hp, HPDataType data)
{
    int i = 0;
   assert(hp);
   _CheakCapacity(hp);
   hp->_hp[hp->_size++] = data;
   AdjustUp(hp,hp->_size-1);

}
int EmptyHeap(Heap* hp)
{
    assert(hp);
    if (hp->_size == 0)
        return 1;

    return 0;

}
void RemoveHeap(Heap* hp)
{
    assert(hp);

    //判斷堆是否為空
    if (EmptyHeap(hp))
        return;

    //先將堆頂元素和堆尾元素交換,並刪除堆尾元素
    Swap(&(hp->_hp[0]), &hp->_hp[hp->_size - 1]);
    hp->_size--;

    //用向下調整法調整佇列
    AdjustDown(hp, 0);


}
int SizeHeap(Heap*hp)
{
    assert(hp);
    return hp->_size;
}
HPDataType TopHeap(Heap* hp)
{
    assert(hp);

    if (hp->_size == 0)
    {
        return 0;
    }

    return hp->_hp[0];
}
void DestroyHeap(Heap* hp)
{
    assert(hp);

    hp->_size = 0;
    hp->_capacity = 0;
    free(hp->_hp);
    hp->_hp = NULL;

    return;

}
///////////優先順序佇列
void InitPriorityQueue(PriorityQueue* q)
{
    InitHeap(&q->hp);
}
void PushPriorityQueue(PriorityQueue* q, HPDataType data)
{
    InsertHeap(&q->hp, data);

}
void PopPriorityQueue(PriorityQueue* q)
{
    int i = 0;
    int root = (q->hp._size-2)/2;  
    RemoveHeap(&q->hp); 
    for(i=root;i>=0;i--)
    {
      AdjustDown(&q->hp,i);
    }

}
int TopPriorityQueue(PriorityQueue* q) 
{

    return TopHeap(&q->hp); 
}
int SizePriorityQueue(PriorityQueue* q)
{
    return SizeHeap(&q->hp);
}
int EmptyPriorityQueue(PriorityQueue* q)
{
    return EmptyHeap(&q->hp);
}
//topk問題
void Topk(Heap* q, int k)
{
    int i = 0;
    int j = 0;
    assert(q);
    q->_hp = (HPDataType*)malloc(sizeof(HPDataType)*k);
    if(q->_hp == NULL)
    {
      assert(0);
      return;
    }

    //首先取前K個數,用著K個數來建立一個小堆
    for(i=0;i<k;i++)
    {
      int temp = rand()%10000;
      q->_hp[i] = temp;
    }

    q->_size = k;
    for(i=(k-2)/2;i>=0;i--)
    {
        AdjustDown(q,i);
    }
    //然後,一個一個的取陣列內剩下的數,取出的數與堆頂的元素比較,如果比堆頂的元素大的話,就用取出的元素
    //代替堆頂的元素,代替之後再進行向下的調整,使堆重新滿足小堆的特性,然後再從陣列內取資料,重複上述操作,直到所有的陣列為空時
      for(j=k;j<10000;j++)
    {
      int temp = rand()%10000;
      if(temp > q->_hp[0])
      {
          Swap(&temp,&q->_hp[0]);
          AdjustDown(q,0);

      }

    }
    PrintHeap(*q);
}
//堆排序
//如果是降序的話, 建一個小堆
//然後,先將小堆的堆頂的值與堆底的值交換,這樣最小值就到了堆底,然後調整的元素個數-1,向下法調整交換後的堆
//調整好的堆最小值又在堆頂,然後再次與最後的元素交換,直到元素個數為0時停止
void HeapSort(Heap *q)
{
    int  i = q->_size;
    assert(q);
    i = q->_size;
    while(i)
    {
        //交換堆底和堆頂的元素
        Swap(&q->_hp[i-1], &q->_hp[0]);
        //把最小值放到堆底之後,元素個數-1;
        --i;
        //調整剩下的幾個元素的堆
        AdjustDown(q,0);
    }
}