點擊(此處)摺疊或打開
-
#ifndef __BINARYHEAP_H_H_
-
#define __BINARYHEAP_H_H_
-
-
#include <stdlib.h>
-
#include <assert.h>
-
-
#define bool int
-
#define true 1
-
#define false 0
-
-
/*打算採用數組的方式實現完全二叉堆*/
-
typedef struct _binaryheap
-
{
-
/*因爲需要動態擴展,
-
*採用靜態數組不方便*/
-
int * parray;
-
/*目前存在的結點*/
-
int currentSize;
-
/*樹的實際容量*/
-
int capacity;
-
}BinaryHeap_t, *BinaryHeap_handle_t;
-
-
#ifdef __cplusplus
-
extern "C"
-
{
-
#endif
-
-
bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity);
-
bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity);
-
void delete_BinaryHeap(BinaryHeap_handle_t heap);
-
void free_BinaryHeap(BinaryHeap_handle_t *heap);
-
-
bool insert(BinaryHeap_handle_t heap,int value);
-
int deleteMin(BinaryHeap_handle_t heap);
-
bool isEmpty(BinaryHeap_handle_t heap);
-
-
#ifdef __cplusplus
-
}
-
#endif
-
- #endif
點擊(此處)摺疊或打開
-
#include "binaryheap.h"
-
-
bool isEmpty(BinaryHeap_handle_t heap)
-
{
-
assert(heap != NULL);
-
return heap->currentSize == 0;
-
}
-
-
bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity)
-
{
-
int *parray = NULL;
-
-
if(heap == NULL)
-
return false;
-
-
parray = (int *)calloc(capacity+1,sizeof(int));
-
if(parray == NULL)
-
return false;
-
-
heap->parray = parray;
-
heap->capacity = capacity;
-
heap->currentSize = 0;
-
-
return true;
-
}
-
-
void delete_BinaryHeap(BinaryHeap_handle_t heap)
-
{
-
assert(heap != NULL && heap->parray != NULL);
-
-
heap->capacity = 0;
-
heap->currentSize = 0;
-
-
free(heap->parray);
-
heap->parray = NULL;
-
}
-
-
void free_BinaryHeap(BinaryHeap_handle_t *heap)
-
{
-
assert(*heap != NULL);
-
-
(*heap)->capacity = 0;
-
(*heap)->currentSize = 0;
-
-
free((*heap)->parray);
-
(*heap)->parray = NULL;
-
-
free(*heap);
-
*heap = NULL;
-
}
-
-
bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity)
-
{
-
int *parray = NULL;
-
-
if(*heap != NULL)
-
return false;
-
-
*heap = (int *)calloc(1, sizeof(BinaryHeap_t));
-
if(*heap == NULL)
-
return false;
-
-
/*其中的1,主要是爲了使得數組從下標1開始計算*/
-
parray =(int *)calloc(capacity + 1, sizeof(int));
-
if(parray == NULL)
-
return false;
-
-
(*heap)->parray = parray;
-
(*heap)->capacity = capacity;
-
(*heap)->currentSize = 0;
-
-
return true;
-
}
-
-
/**************************************************
-
* 採用上慮法實現數據的插入操作
-
* 上慮法的實現方式比較簡單,首先創建一個空節點
-
* 然後將需要插入的值與當前空穴的父結點進行比較
-
* 如果大於父結點,直接插入空穴中
-
* 如果小於父結點的值,則將父結點的值下拉到空穴中
-
* 之前父結點的位置就是空穴,接着與上層比較
-
* 直到找到父結點大於當前插入值的情況
-
**************************************************/
-
bool insert(BinaryHeap_handle_t heap, int value)
-
{
-
int index = 0;
-
-
if(heap == NULL || heap->parray == NULL)
-
return false;
-
-
/*得到一個新的空穴下標*/
-
index = ++heap->currentSize;
-
/*條件是不是第一個下標和插入值比對應父結點小*/
-
while(index > 1 && value < heap->parray[index/2])
-
{
-
/*將父結點保存到當前結點處*/
-
heap->parray[index] = heap->parray[index/2];
-
/*得到父結點的空穴位置*/
-
index /= 2;
-
}
-
/*將插入的值保存到剩餘的空穴中*/
-
heap->parray[index] = value;
-
-
return true;
-
}
-
-
/***********************************************************
-
* 下慮法實現數據的重排序操作
-
* 實現的方式,將子結點的兩個兒子進行比較,將小的提升
-
* 需要注意的是如何讓判斷節點是否一定存在右兒子
-
* 實現的方式主要是利用了二叉堆的特性:
-
* 2*pare = L_child
-
* 2*pare + 1 = R_child;
-
***********************************************************/
-
static void presort_BinaryHeap(BinaryHeap_handle_t heap,int hole)
-
{
-
/*這是二叉堆的特性*/
-
int child = hole * 2;
-
/*保存當前數據操作*/
-
int tmp = 0;
-
-
assert(heap != NULL && heap->parray != NULL);
-
-
tmp = heap->parray[hole];
-
/*hold * 2 <= heap->currentSize
判斷了當前結點是否爲最低層*/
-
for(; hole * 2 <= heap->currentSize; hole = child)
-
{
-
child = hole * 2;
-
-
/*******************************
-
*這句代碼解決是否存在右結點的問題
-
*並確定了那個子結點提升的問題
-
*******************************/
-
if((child != heap->currentSize)
-
&& (heap->parray[child + 1] < heap->parray[child]))
-
child ++;
-
-
if(heap->parray[child] < tmp)
-
{
-
/*將子結點提升爲父結點*/
-
heap->parray[hole] = heap->parray[child];
-
}
-
}
-
/*到達了最低的層,也就是樹葉*/
-
heap->parray[hole] = tmp;
-
}
-
-
/*實現數據的下慮法實現數據的刪除操作*/
-
int deleteMin(BinaryHeap_handle_t heap)
-
{
-
int ret = 0;
-
int index = 0;
-
-
assert(!isEmpty(heap));
-
/*需要返回的值*/
-
ret = heap->parray[1];
-
-
/*將最後需要釋放內存空間的值保存到第一個內存空間中*/
-
heap->parray[1] = heap->parray[heap->currentSize --];
-
/*從表頭開始將新的二叉樹進行重新排序*/
-
presort_BinaryHeap(heap, 1);
-
-
return ret;
- }
點擊(此處)摺疊或打開
-
#include "binaryheap.h"
-
#include <stdio.h>
-
#include <time.h>
-
-
void print_binaryheap(BinaryHeap_handle_t heap)
-
{
-
int i = 0;
-
-
assert(heap != NULL && heap->parray != NULL);
-
-
for(i = 1; i <= heap->currentSize; ++ i)
-
{
-
if(i %6)
-
printf("%d\t",heap->parray[i]);
-
else
-
printf("\n%d\t",heap->parray[i]);
-
}
-
printf("\n");
-
}
-
-
int main()
-
{
-
int i = 0;
-
int value = 0;
-
-
srand((int)time(0));
-
printf("********Test Binaryheap**************\n");
-
-
BinaryHeap_t bheap;
-
BinaryHeap_handle_t *pheap = NULL;
-
-
printf("init and alloc test:\n");
-
if(init_BinaryHeap(&bheap,10))
-
{
-
printf("init_BinaryHeap() successed!\n");
-
}
-
if (alloc_BinaryHeap(&pheap,15));
-
{
-
printf("alloc_BInaryHeap() successed!\n");
-
}
-
-
printf("***insert test*****\n");
-
for(; i < 10; ++ i)
-
{
-
if(!insert(&bheap,5 * i - rand()%20))
-
{
-
printf("i = %d:insert failed !!\n",i);
-
}
-
}
-
for(i = 0; i < 15; ++ i)
-
{
-
if(!insert(pheap,i * 8 - rand()%20))
-
{
-
printf("i = %d:insert failed!!\n",i);
-
}
-
}
-
-
print_binaryheap(&bheap);
-
print_binaryheap(pheap);
-
-
printf("****deleteMin test****\n");
-
for(i = 0; i < 5; ++ i)
-
{
-
value = deleteMin(&bheap);
-
printf("bheap deleted:%d\n",value);
-
value = deleteMin(pheap);
-
printf("pheap deleted:%d\n",value);
-
}
-
print_binaryheap(&bheap);
-
print_binaryheap(pheap);
-
-
printf("deleteMin test successed\n");
-
-
printf("****delete and free test:*******\n");
-
delete_BinaryHeap(&bheap);
-
-
printf("Is the bheap empty ? %s\n",
-
isEmpty(&bheap)?"Yes":"No");
-
-
free_BinaryHeap(&pheap);
-
-
printf("*********Test successed!***********\n");
-
pheap = NULL;
-
return 0;
- }
點擊(此處)摺疊或打開
-
[gong@Gong-Computer c_binaryheap]$ ./testbinaryheap
-
********Test
Binaryheap**************
-
init and alloc test:
-
init_BinaryHeap()
-
alloc_BInaryHeap()
-
***insert test*****
-
-11 -9 -9 14 15
-
10 21 23 40 26
-
-16 2 14 20 13
-
21 33 49 61 67 76
-
86 83 95 109
-
****deleteMin
test****
-
bheap deleted:-11
-
pheap deleted:-16
-
bheap deleted:-9
-
pheap deleted:2
-
bheap deleted:-9
-
pheap deleted:13
-
bheap deleted:10
-
pheap deleted:14
-
bheap deleted:14
-
pheap deleted:20
-
15 23 21 40 26
-
21 49 21 61 67
-
76 33 95 83 109
-
deleteMin test successed
-
****delete and free
test:*******
-
Is the bheap empty ? Yes
- *********Test
從上面的測試結果可知,基本上實現了二叉堆的基本插入、刪除操作。代碼的關鍵點在於刪除中的下慮和插入過程中的上慮操作。以及如何判斷代碼是否存在右兒子,如何充分運用二叉堆的特性。