C語言_堆的基本操作
阿新 • • 發佈:2018-11-04
本片部落格主要包含一下幾個內容:
1、建立堆
void CreateHeap(Heap *hp, HPDataType* arr, int size, Compare Com) { int cur = 0; assert (hp != NULL); hp->_hp = (HPDataType*)malloc (size * sizeof (HPDataType)); if (hp->_hp == NULL) { assert (0); return ; } //拷貝元素 memcpy (hp->_hp, arr, size*sizeof (HPDataType)); hp->size = size; hp->capacity = size; hp->_com = Com; //調整成堆 cur = ((size-1-1)>>1); //size-1為最大下標,再減一除二為最後一個節點的雙親節點 for (; cur>=0; cur--) { AdjustDown (hp, cur);//向下調整堆 } }
2、調整堆(向下調整)
void AdjustDown (Heap* hp, int parent)//parent 為開始調整的節點 { int child = 0; assert (hp != NULL); child = (parent<<1) + 1; //孩子節點等於雙親節點乘二加一 while (child < hp->size) { if (child+1 < hp->size)//如果右孩子存在,找左右孩子中最小的孩子 { if (hp->_com (hp->_hp[child], hp->_hp[child+1])) { child += 1; } } if (hp->_com(hp->_hp[parent], hp->_hp[child])) { Swap (&hp->_hp[parent], &hp->_hp[child]); } else { return; } parent = child; child = (parent<<1) + 1; } }
3、插入
void InsertHeap (Heap* hp, HPDataType data) //插入元素
{
assert (hp != NULL);
//判斷還有沒有空間,有的話就插入元素,沒有就增容再插入元素
CheakHeap (hp);
hp->_hp[hp->size] = data;
hp->size++;
//向上調整堆
AdjustUp (hp, (hp->size)-1);
}
4、移除堆頂元素
//移除元素,(把堆頂元素和最後一個元素交換,size--就把堆頂元素刪除了,最後在調整一下堆頂元素) void RemoveHeap (Heap* hp) { assert (hp != NULL); Swap (&hp->_hp[0], &hp->_hp[hp->size-1]); hp->size--; AdjustDown (hp, 0, hp->_com); }
5、返回堆元素個數
int SizeHeap (Heap* hp) //返回堆元素個數
{
assert (hp != NULL);
return hp->size;
}
6、判斷是不是空堆
int IsHeapEmpty (Heap* hp) //判斷是不是空堆,空堆返回1,非空返回0
{
assert (hp != NULL);
return (hp->size == 0);
}
7、返回堆頂元素
HPDataType HeapTop (Heap* hp) //返回堆頂元素
{
assert (hp != NULL);
return hp->_hp[0];
}
8、向上調整堆
void AdjustUp (Heap* hp, int child)
{
int parent = 0;
assert (hp != NULL);
parent = (child - 1)/2;
while (child)
{
if (!(hp->_com(hp->_hp[child], hp->_hp[parent])))
{
Swap (&hp->_hp[child], &hp->_hp[parent]);
}
child = parent;
parent = (child - 1)/2;
}
}
9、交換兩個數
void Swap (HPDataType*p, HPDataType* q)
{
HPDataType tmp;
assert (p != NULL && q != NULL);
tmp = *p;
*p = *q;
*q = tmp;
}
10、判斷堆是否已滿,如果滿了,就增容;如果沒有滿,就返回
void CheakHeap (Heap* hp) //判斷堆是否已滿,如果滿了,就增容;如果沒有滿,就返回
{
int newCapacity = 0;
int i = 0;
HPDataType* temp;
assert (hp != NULL);
if (hp->capacity > hp->size)
{
return ;
}
//如果堆已滿,增容
newCapacity = 2 * (hp->capacity)+3;
temp = (HPDataType*)malloc (newCapacity * sizeof (HPDataType)); //開闢新空間
if (temp == NULL)
{
perror ("CheakHeap::malloc>>");
return ;
}
//拷貝元素
for (; i<hp->size; ++i)
{
temp[i] = hp->_hp[i];
}
//釋放原空間
free (hp->_hp);
hp->_hp = NULL;
//讓原空間指向新開闢的空間
hp->_hp = temp;
hp->capacity = newCapacity;
}
11、銷燬堆
void DestroyHeap (Heap* hp)
{
assert (hp != NULL);
free (hp->_hp);
hp->_hp = NULL;
hp->capacity = 0;
hp->size = 0;
printf ("銷燬成功\n");
}
12、小於比較
//Less 和 Greater兩個函式用來比較兩個數的大小,在建堆時用函式指標的形式呼叫,用來分別建大堆小堆
int Less (HPDataType pLeft, HPDataType pRight) //小於比較
{
assert (pLeft != NULL && pRight != NULL);
if (pLeft > pRight)
{
return 0;
}
else
{
return 1;
}
}
13、大於比較
int Greater (HPDataType pLeft, HPDataType pRight) //大於比較
{
if (pLeft > pRight)
{
return 1;
}
else
{
return 0;
}
}
14、標頭檔案程式碼
#ifndef __HEAP_H__
#define __HEAP_H__
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//堆:是一個數組,其中的元素是按照二叉樹的順序在陣列中存放的
//任意一個節點的資料都比其左右孩子都小---小堆
//任意一個節點的資料都比它的左右孩子大---大堆
typedef int HPDataType;
typedef int (*Compare) (HPDataType pLeft, HPDataType pRight);
typedef struct Heap
{
HPDataType* _hp;
int capacity;
int size;
Compare _com;
}Heap;
void CreateHeap(Heap *hp, HPDataType* arr, int size, Compare Com); //建立堆
void AdjustDown (Heap* hp, int parent); //調整堆(向下調整)
void InsertHeap (Heap* hp, HPDataType data); //插入
void RemoveHeap (Heap* hp); //移除元素,(把堆頂元素和最後一個元素交換,size--就把堆頂元素刪除了,最後在調整一下堆頂元素)
int SizeHeap (Heap* hp); //返回堆元素個數
int IsHeapEmpty (Heap* hp); //判斷是不是空堆
HPDataType HeapTop (Heap* hp); //返回堆頂元素
void AdjustUp (Heap* hp, int child); //向上調整堆
void Swap (HPDataType* p, HPDataType*q); //交換兩個數
void CheakHeap (Heap* hp); //判斷堆是否已滿,如果滿了,就增容;如果沒有滿,就返回
void DestroyHeap (Heap* hp); //銷燬堆
int Less (HPDataType pLeft, HPDataType pRight); //小於比較
int Greater (HPDataType pLeft, HPDataType pRight); //大於比較
#endif
15、測試程式碼
#include "Heap.h"
void test_Heap()
{
//test_CreateHeap
int ret = 0;
HPDataType top = 0;
int arr[] = {53, 17, 78, 9, 45, 65, 87, 23, 31};
Heap hp;
CreateHeap (&hp, arr, sizeof(arr)/sizeof(arr[0]), Less);
//test_SizeEmptyTopHeap
ret = SizeHeap(&hp);
printf ("堆的大小為:%d\n", ret);
ret = IsHeapEmpty(&hp);
if (ret == 1)
{
printf ("這是空堆!\n");
}
else
{
printf ("不是空堆!\n");
}
top = HeapTop(&hp);
printf ("堆頂元素是:%d\n", top);
//test_InsertHeap
InsertHeap(&hp, 5);
//test_RemoveHeap
RemoveHeap(&hp);
DestroyHeap (&hp);
}
int main ()
{
test_Heap();
return 0;
}