ReviewForJob——二叉堆优先队列的实现(三种堆节点类型——int + struct HeapNode + struct HeapNode*)

【0】README

1)本文旨在给出 二叉堆优先队列的实现 的代码实现和分析, 而堆节点类型 不外乎三种: 一, 基本类型如int; 二,结构体类型 struct HeapNode; 三,结构体指针类型 struct HeapNode* 类型;

2)为什么要给出 结构体指针类型的 二叉堆实现 ? 因为 小生我在 实现 克鲁斯卡尔算法 求 最小生成树的时候,需要用到 二叉堆优先队列 选取 权值最小的边,所以要用到 结构体指针类型的 二叉堆实现, 哥子 今天一上午 也 没有 吧 kruskal alg 实现出来,原因就在于 结构体指针类型 的 二叉堆 没有 弄清楚;

3)本文末尾对三种堆节点类型的源码实现 进行了分析和比较;

4)for full source code, please visit https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter6/review

5)wc, 刚才填了一个大坑,你懂的。

// for循环的 leftChild(index) <= size 必须要取 等号.
    for(temp = data[index]; leftChild(index) <= size; index = child)
    {
        child = leftChild(index);
        if(child < size && data[child] < data[child+1]) // if 语句里的 child < size 不取等号.

【1】二叉堆基本操作

操作1)初始化堆;

操作2)基于上滤操作的插入操作;

操作3)基于下滤操作的删除最小值 (deleteMin);

操作4)decreaseKey 操作;

操作5)increaseKey 操作;


【2】基本类型(int)为堆节点的堆实现

1)堆结构体

// 堆节点类型为 int.
#define ElementType int

struct BinaryHeap;
typedef struct BinaryHeap *BinaryHeap;
struct BinaryHeap 
{
	int capacity;
	int size;	
	ElementType *array;		
};
2)源码实现

// judge whether the BinaryHeap is full or not , also 1 or 0 .
// you should know the element under index 0 don't store any content.
int isFull(BinaryHeap bh)
{
	return bh->size == bh->capacity - 1 ? 1 : 0 ;
}

// judge whether the BinaryHeap is empty or not , also 1 or 0 
int isEmpty(BinaryHeap bh)
{
	return bh->size == 0 ? 1 : 0 ;
}

void swap(ElementType *x, ElementType *y)
{
	ElementType temp;

	temp = *x;
	*x = *y;
	*y = temp;
}

// get the left child of node under index with startup 1
int leftChild(int index)
{
	return index*2;
}

// initialize binary heap with given capacity.
BinaryHeap initBinaryHeap(int capacity)
{
	BinaryHeap bh;
	ElementType *temp;

	bh = (BinaryHeap)malloc(sizeof(struct BinaryHeap));
	if(!bh) 
	{
        Error("out of space, from func initBinaryHeap");        
        return NULL;
    }  
	bh->capacity = capacity;
	bh->size = 0;

	temp = (ElementType *)malloc(capacity * sizeof(ElementType));
	if(!temp) 
	{
        Error("out of space, from func initBinaryHeap");        
        return NULL;
    } 
	bh->array = temp;
	bh->array[0] = INT_MIN; // let bh->array[0] be the minimum integer.

	return bh;
}

// Attention, the index of the heap starts from 1
// insert the value into binary heap based on percolateUp().
void insert(ElementType value, BinaryHeap bh)
{	
	if(isFull(bh))
	{
		Error("failed insertion , for the BinaryHeap is full, from func insert!");
		return ;	
	}
	bh->array[++bh->size] = value; // startup is 1 not 0.
	percolateUp(bh->size, bh);
}

 // percolating up the element when its value is greater than children (minimal heap)
 //Attention: all of bh->array starts from index 1
void percolateUp(int i, BinaryHeap bh)
{	
	ElementType temp = bh->array[i];
	
	for(; temp < bh->array[i/2]; i/=2)
	{
		bh->array[i] = bh->array[i/2];
	}
	bh->array[i] = temp;
}

// delete minimal from binary heap based on percolateDown().
ElementType deleteMin(BinaryHeap bh)
{	
	ElementType minimum;
	ElementType *data;	
		
	if(isEmpty(bh))
	{
		Error("failed deleting minimum , for the BinaryHeap is empty, from func deleteMin !");
		return -1;	
	}

	data = bh->array;	
	minimum = data[1];

	swap(&data[1], &data[bh->size]); // &variable means nickname of the variable
	bh->size-- ; // size-- occurs prior to percolateDown(). 
	percolateDown(1, bh) ;	

	return minimum;
} 

// percolating down the element when its value is greater than children (minimal heap)
 //Attention: all of bh->array starts from index 1
 void percolateDown(int index, BinaryHeap bh)
 {  
    ElementType *data;
    int size;
    ElementType temp;
    int child;

    data = bh->array;
    size = bh->size;

    for(temp = data[index]; leftChild(index) < size; index = child)
    {
        child = leftChild(index);
        if(child < size && data[child] > data[child+1])
		{
            child++;
		}
        if(temp > data[child])
		{
            data[index] = data[child];
		}
		else
		{
            break;
		}
    }
    data[index] = temp;
 }

// print binary heap.
void printBinaryHeap(BinaryHeap bh)
{
	int i;
	ElementType *temp;
	
	if(!bh)
	{
		Error("printing execution failure, for binary heap is null, from func printBinaryHeap");	
	}

	temp = bh->array;
	for(i=1; i <= bh->size; i++)
	{
		printf("\n\t index[%d] = ", i);				
		printf("%d", bh->array[i]);		
	}
	printf("\n");
}  

// increase element's value
void increaseKey(int index, ElementType increment, BinaryHeap bh)
{   
    if(index > bh->size || index < 1)
    {
        Error(" failed increaseKey, since overstep the boundary! ");
        return ;
    }

    bh->array[index] += increment; // update the element under given index
    percolateDown(index, bh);
}

//decreasing value of the element under index by increment
void decreaseKey(int index, ElementType decrement, BinaryHeap bh)
{   
    if(index > bh->size || index < 1)
    {
        Error(" failed decreaseKey, since overstep the boundary! ");
        return ;
    }

    bh->array[index] -= decrement; // update the element under given index
    percolateUp(index, bh);
}

3)测试用例

int main()
{
	int i;
	BinaryHeap bh;
	int capacity;
	int size;
	ElementType data[] =  {85, 80, 40, 30, 10, 70, 110};

	capacity = 15;
	size = 7;
	bh = initBinaryHeap(capacity);

	printf("\ninsert {85, 80, 40, 30, 10, 70, 110} into binary heap.");
	for(i = 0; i < size; i++)
	{
		insert(data[i], bh);
	}	
	printBinaryHeap(bh);

	printf("\ninsert {100, 20, 90, 5} into binary heap\n");
	insert(100, bh);
	insert(20, bh);
	insert(90, bh);
	insert(5, bh);
	printBinaryHeap(bh);

	printf("\ndeleteMin from binary heap\n");
    deleteMin(bh);  
    printBinaryHeap(bh);    
     
	// other operations in bianry heap      
    printf("\nincreaseKey(2, 85, bh) [increaseKey(index, increment, binary heap)]\n");
    increaseKey(2, 85, bh);
    printBinaryHeap(bh);
	
	printf("\ndecreaseKey(9, 85, bh) [decreaseKey(index, decrement, binary heap)]\n");
    decreaseKey(9, 85, bh);
    printBinaryHeap(bh);
	
	return 0;
}

【3】结构体类型(struct HeapNode)为堆节点的堆实现

1)堆结构体

// 堆节点类型是结构体.
struct HeapNode; 
typedef struct HeapNode* HeapNode;
struct HeapNode
{
	int value;
};

// 二叉堆的结构体.
struct BinaryHeap;
typedef struct BinaryHeap *BinaryHeap;
struct BinaryHeap 
{
	int capacity;
	int size;	
	HeapNode array; // 二叉堆实现为结构体数组.
};
// 堆节点类型是 结构体类型 而不是单纯的 int类型.
#define ElementType struct HeapNode 
2)源码实现

ElementType createElementType(int value)
{
	struct HeapNode node;
	
	node.value = value;
	return node;
}

// judge whether the BinaryHeap is full or not , also 1 or 0 .
// you should know the element under index 0 don't store any content.
int isFull(BinaryHeap bh)
{
	return bh->size == bh->capacity - 1 ? 1 : 0 ;
}

// judge whether the BinaryHeap is empty or not , also 1 or 0 
int isEmpty(BinaryHeap bh)
{
	return bh->size == 0 ? 1 : 0 ;
}

void swap(ElementType *x, ElementType *y)
{
	ElementType temp;

	temp = *x;
	*x = *y;
	*y = temp;
}

// get the left child of node under index with startup 1
int leftChild(int index)
{
	return index*2;
}

// initialize binary heap with given capacity.
BinaryHeap initBinaryHeap(int capacity)
{
	BinaryHeap bh;
	ElementType *temp;

	bh = (BinaryHeap)malloc(sizeof(struct BinaryHeap));
	if(!bh) 
	{
        Error("out of space, from func initBinaryHeap");        
        return NULL;
    }  
	bh->capacity = capacity;
	bh->size = 0;

	temp = (ElementType *)malloc(capacity * sizeof(ElementType));
	if(!temp) 
	{
        Error("out of space, from func initBinaryHeap");        
        return NULL;
    } 
	bh->array = temp;
	bh->array[0].value = INT_MIN; // update: let bh->array[0]->value be the minimum integer.

	return bh;
}

// Attention, the index of the heap starts from 1
// insert the value into binary heap based on percolateUp().
void insert(ElementType e, BinaryHeap bh)
{		
	if(isFull(bh))
	{
		Error("failed insertion , for the BinaryHeap is full.");
		return ;	
	}
	bh->array[++bh->size] = e; // startup is 1 not 0.
	percolateUp(bh->size, bh);
}

 // percolating up the element when its value is greater than children (minimal heap)
 //Attention: all of bh->array starts from index 1
void percolateUp(int i, BinaryHeap bh)
{	
	ElementType temp = bh->array[i];
	
	for(; temp.value < bh->array[i/2].value; i/=2) // update.
	{
		bh->array[i] = bh->array[i/2];
	}
	bh->array[i] = temp;
}

// delete minimal from binary heap based on percolateDown().
ElementType deleteMin(BinaryHeap bh)
{	
	ElementType minimum;
	ElementType *data;				

	data = bh->array;	
	minimum = data[1];

	swap(&data[1], &data[bh->size]); // &variable means nickname of the variable
	bh->size-- ; // size-- occurs prior to percolateDown(). 
	percolateDown(1, bh) ;	

	return minimum;
} 

// percolating down the element when its value is greater than children (minimal heap)
 //Attention: all of bh->array starts from index 1
 void percolateDown(int index, BinaryHeap bh)
 {  
    ElementType* array; 
    int size;
    ElementType temp;
    int child;

    array = bh->array;
    size = bh->size;

    for(temp = array[index]; leftChild(index) <= size; index = child)
    {
        child = leftChild(index);
        if(child < size && array[child].value > array[child+1].value)
		{
            child++;
		}
        if(temp.value > array[child].value)
		{
            array[index] = array[child];
		}
		else
		{
            break;
		}
    }
    array[index] = temp;
 }

// print binary heap.
void printBinaryHeap(BinaryHeap bh)
{
	int i;
	ElementType *temp;
	
	if(!bh)
	{
		Error("printing execution failure, for binary heap is NULL.");	
	}

	temp = bh->array;
	for(i = 1; i <= bh->size; i++)
	{
		printf("\n\t index[%d] = ", i);				
		printf("%d", bh->array[i]);
	}
	printf("\n");
}  

// increase element's value
void increaseKey(int index, int increment, BinaryHeap bh)
{   
    if(index > bh->size || index < 1)
    {
        Error(" failed increaseKey, since overstep the boundary! ");
        return ;
    }

    bh->array[index].value += increment; // update the element under given index
    percolateDown(index, bh);
}

//decreasing value of the element under index by increment
void decreaseKey(int index, int decrement, BinaryHeap bh)
{   
    if(index > bh->size || index < 1)
    {
        Error(" failed decreaseKey, since overstep the boundary! ");
        return ;
    }

    bh->array[index].value -= decrement; // update the element under given index
    percolateUp(index, bh);
}

3)测试用例

// 堆节点是结构体类型.
int main()
{	
	BinaryHeap bh;
	int i, capacity, size;	
	int data[] =  {85, 80, 40, 30, 10, 70, 110};

	capacity = 15;
	size = 7;
	bh = initBinaryHeap(capacity);

	printf("\ninsert {85, 80, 40, 30, 10, 70, 110} into binary heap with heap node being struct.");
	for(i = 0; i < size; i++)
	{
		insert(createElementType(data[i]), bh);
	}	
	printBinaryHeap(bh);

	
	printf("\ninsert {100, 20, 90, 5} into binary heap\n");
	insert(createElementType(100), bh);
	insert(createElementType(20), bh);
	insert(createElementType(90), bh);
	insert(createElementType(5), bh);
	printBinaryHeap(bh);

	printf("\ndeleteMin from binary heap\n");
    deleteMin(bh);  
    printBinaryHeap(bh);    
     

	// other operations in bianry heap      
    printf("\nincreaseKey(2, 85, bh) [increaseKey(index, increment, binary heap)]\n");
    increaseKey(2, 85, bh);
    printBinaryHeap(bh);
	
	printf("\ndecreaseKey(9, 85, bh) [decreaseKey(index, decrement, binary heap)]\n");
    decreaseKey(9, 85, bh);
    printBinaryHeap(bh);
	
	return 0;
}

【4】结构体类型指针(struct HeapNode*)为堆节点的堆实现

1)堆结构体

struct HeapNode; 
typedef struct HeapNode* HeapNode;
struct HeapNode
{
	int value;
};

// 二叉堆的结构体.
struct BinaryHeap;
typedef struct BinaryHeap *BinaryHeap;
struct BinaryHeap 
{
	int capacity;
	int size;	
	HeapNode* array;  // 堆节点类型是结构体指针. 而优先队列是结构体指针数组.
};
// 堆节点类型是 结构体指针类型 而不是单纯的 int类型.
#define ElementType HeapNode 

2)源码实现

ElementType createElementType(int value)
{
	HeapNode node = (HeapNode)malloc(sizeof(struct HeapNode));
	if(node == NULL)
	{
		Error("failed createElementType() for out of space.");        
        return NULL;
	}
	node->value = value;
	return node;
}

// judge whether the BinaryHeap is full or not , also 1 or 0 .
// you should know the element under index 0 don't store any content.
int isFull(BinaryHeap bh)
{
	return bh->size == bh->capacity - 1 ? 1 : 0 ;
}

// judge whether the BinaryHeap is empty or not , also 1 or 0 
int isEmpty(BinaryHeap bh)
{
	return bh->size == 0 ? 1 : 0 ;
}

void swap(ElementType x, ElementType y)
{
	struct HeapNode temp;

	temp = *x;
	*x = *y;
	*y = temp;
}

// get the left child of node under index with startup 1
int leftChild(int index)
{
	return index*2;
}

// initialize binary heap with given capacity.
BinaryHeap initBinaryHeap(int capacity)
{
	BinaryHeap bh;
	ElementType* temp;

	bh = (BinaryHeap)malloc(sizeof(struct BinaryHeap));
	if(!bh) 
	{
        Error("out of space, from func initBinaryHeap");        
        return NULL;
    }  
	bh->capacity = capacity;
	bh->size = 0;

	temp = (ElementType *)malloc(capacity * sizeof(ElementType));
	if(!temp) 
	{
        Error("out of space, from func initBinaryHeap");        
        return NULL;
    } 
	bh->array = temp;
	// bh->array[0] = INT_MIN; 
	bh->array[0] = (ElementType)malloc(sizeof(struct HeapNode));
	if(bh->array[0] == NULL)
	{
		Error("out of space, from func initBinaryHeap");        
        return NULL;
	}
	bh->array[0]->value = INT_MIN; 
	return bh;
}

// Attention, the index of the heap starts from 1
// insert the value into binary heap based on percolateUp().
void insert(ElementType e, BinaryHeap bh)
{		
	if(e == NULL)
	{
		Error("failed insertion , for e is NULL.");
		return;
	}
	if(isFull(bh))
	{
		Error("failed insertion , for the BinaryHeap is full.");
		return ;	
	}
	bh->array[++bh->size] = e; // startup is 1 not 0.
	percolateUp(bh->size, bh);
}

 // percolating up the element when its value is greater than children (minimal heap)
 //Attention: all of bh->array starts from index 1
void percolateUp(int i, BinaryHeap bh)
{	
	ElementType temp = bh->array[i];
	
	for(; temp->value < bh->array[i/2]->value; i/=2) // update.
	{
		bh->array[i] = bh->array[i/2];
	}
	bh->array[i] = temp;
}

// delete minimal from binary heap based on percolateDown().
ElementType deleteMin(BinaryHeap bh)
{	
	ElementType minimum;
	ElementType* array;				

	array = bh->array;	
	minimum = array[1];

	swap(array[1], array[bh->size]); // &variable means nickname of the variable
	bh->size-- ; // size-- 在下滤函数执行之前发生.
	percolateDown(1, bh) ;	

	return minimum;
} 

// percolating down the element when its value is greater than children (minimal heap)
 //Attention: all of bh->array starts from index 1
 void percolateDown(int index, BinaryHeap bh)
 {  
    ElementType* array; 
    int size;
    ElementType temp;
    int child;

    array = bh->array;
    size = bh->size;

    for(temp = array[index]; leftChild(index) <= size; index = child)
    {
        child = leftChild(index);
        if(child < size && array[child]->value > array[child+1]->value)
		{
            child++;
		}
        if(temp->value > array[child]->value)
		{
            array[index] = array[child];
		}
		else
		{
            break;
		}
    }
    array[index] = temp;
 }

// print binary heap.
void printBinaryHeap(BinaryHeap bh)
{
	int i;
	
	if(!bh)
	{
		Error("printing execution failure, for binary heap is NULL.");	
		return;
	}
	
	for(i=1; i <= bh->size; i++)
	{
		printf("\n\t index[%d] = ", i);				
		printf("%d", bh->array[i]->value);		
	}
	printf("\n");
}  

// increase element's value
void increaseKey(int index, int increment, BinaryHeap bh)
{   
    if(index > bh->size || index < 1)
    {
        Error(" failed increaseKey, since overstep the boundary! ");
        return ;
    }

    bh->array[index]->value += increment; // update the element under given index
    percolateDown(index, bh);
}

//decreasing value of the element under index by increment
void decreaseKey(int index, int decrement, BinaryHeap bh)
{   
    if(index > bh->size || index < 1)
    {
        Error(" failed decreaseKey, since overstep the boundary! ");
        return ;
    }

    bh->array[index]->value -= decrement; // update the element under given index
    percolateUp(index, bh);
}

3)测试用例

// 堆节点是结构体指针类型.
int main()
{	
	BinaryHeap bh;
	int i, capacity, size;	
	int data[] =  {85, 80, 40, 30, 10, 70, 110};

	capacity = 15;
	size = 7;
	bh = initBinaryHeap(capacity);

	printf("\ninsert {85, 80, 40, 30, 10, 70, 110} into binary heap.");
	for(i = 0; i < size; i++)
	{
		insert(createElementType(data[i]), bh);
	}	
	printBinaryHeap(bh);

	
	printf("\ninsert {100, 20, 90, 5} into binary heap\n");
	insert(createElementType(100), bh);
	insert(createElementType(20), bh);
	insert(createElementType(90), bh);
	insert(createElementType(5), bh);
	printBinaryHeap(bh);

	printf("\ndeleteMin from binary heap\n");
    deleteMin(bh);  
    printBinaryHeap(bh);    
     

	// other operations in bianry heap      
    printf("\nincreaseKey(2, 85, bh) [increaseKey(index, increment, binary heap)]\n");
    increaseKey(2, 85, bh);
    printBinaryHeap(bh);
	
	printf("\ndecreaseKey(9, 85, bh) [decreaseKey(index, decrement, binary heap)]\n");
    decreaseKey(9, 85, bh);
    printBinaryHeap(bh);
	
	return 0;
}

【5】堆节点为 或者int类型 或者结构体类型 或者 结构体指针类型 的源码分析和总结 

1)注意在以上实现中, 哪些函数是相同的,哪些函数是不同的, 就算有些函数声明相同,但是函数体是不同的;

2)要知道 堆的第一个存储空间不用(index == 0):对于int 类型的处理方式是 设置 array[0]=INT_MIN, 对于 struct 类型的处理方式是 array[0].value = INT_MIN,对于 struct* 类型的处理方式是 array[0]->value = INT_MIN,这都是为了 上滤的时候 便于比较;而对于 array[0] 的初始化都是在 初始化堆中的函数完成的;

3)还有一个需要注意的是 swap() 函数:deleteMin() 函数 需要用到 swap()函数,因为 在 删除最小元元素的时候,是吧 第一个元素 和 最后一个元素进行交换,然后size--,然后再对 index=1 的元素进行下滤操作;所以 swap() 交换函数特别重要;

void swap(ElementType x, ElementType y) // struct HeapNode* 的 swap函数.(堆节点类型是 结构体指针类型)
{
	struct HeapNode temp;

	temp = *x;
	*x = *y;
	*y = temp;
}
void swap(ElementType *x, ElementType *y) // struct HeapNode 的swap函数.(堆节点类型是 结构体类型)
{
	ElementType temp;

	temp = *x;
	*x = *y;
	*y = temp;
}
void swap(ElementType *x, ElementType *y) // int 类型的swap函数(堆节点类型是 int基本类型)
{
	ElementType temp;

	temp = *x;
	*x = *y;
	*y = temp;
}
4)测试用例中,插入元素进堆,传入的参数不一样:虽然 他们的 insert 函数都是 void insert(ElementType value, BinaryHeap bh),对于 int类型来说, ElementType 就是 int, 对于 struct HeapNode 来说,ElementType 就是 struct HeapNode, 而对于 struct HeapNode* 来说, ElementType 就是  struct HeapNode*;所以你看到在不同测试用例中,除开 int 基本类型 都是要 创建 堆节点的,然后再传入;

ElementType createElementType(int value) // struct HeapNode 类型的 createElementType() 函数体
{
	struct HeapNode node;
	
	node.value = value;
	return node;
}
ElementType createElementType(int value) // struct HeapNode* 类型的 createElemnetType() 函数体. 是很不一样的,这是我们需要注意的.
{
	HeapNode node = (HeapNode)malloc(sizeof(struct HeapNode));
	if(node == NULL)
	{
		Error("failed createElementType() for out of space.");        
        return NULL;
	}
	node->value = value;
	return node;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值