zoukankan      html  css  js  c++  java
  • 图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)

    【0】README

    0.1)为什么有这篇文章?因为 Dijkstra算法的优先队列实现 涉及到了一种新的数据结构,即优先队列(二叉堆)的操作需要更改以适应这种新的数据结构,我们暂且吧它定义为Distance, 而不是单纯的int类型;
    0.2)本文源代码均为原创, int类型的优先队列(二叉堆)的操作实现,参见http://blog.csdn.net/PacosonSWJTU/article/details/49498255, (并比较他们的打印结果,很有必要)


    【1】因为 Dijkstra算法的优先队列实现, 需要用到二叉堆的相关操作,但是操作的元素类型(ElementType 不是 单纯的int类型), 而是如下:

    struct Distance
    {
     int vertexIndex; //当前顶点下标
     int distance; //初始顶点到当前顶点的distance
    };
    

    【2】看个荔枝

    2.1)需要特别说明的是: indexOfVertexInHeap 数组记录的是顶点vertex在 heap中的位置, 如 indexOfVertexInHeap [1] = 4;表明heap的第4个位置记录这 编号为1的vertex;
    2.2)优先队列的insert和deleteMin 的执行演示(请将我的手动演示结果同我的代码打印结果做对比,经过对比,你发现它们的效果是一致的,恰好说明了我的代码的可行性):

    Attention)

    • A1)其实本文中的二叉堆优先队列的实现源代码和 int类型的优先队列源代码类似,只不过它们操作的数据类型不一样罢了,当然, 这只需要简单的修改即可;
    • A2)打印结果在文末,可以看到,ElementType采用int 和 Distance的打印效果一样,这正证明了我们采用Distance结构体对源码的修改是无误的,相比于单纯的int 类型,只不过Distance又多了一个 顶点下标vertexIndex成员变量而已;

    【3】source code + printing results

    3.1)download source code:
    https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter9/binaryHeap_dijkstra_prim
    3.2)source code at a glance:(for complete code , please click the given link above)

    1st file:distance.h

    #include <stdio.h>
    
    #define Error(str) printf("
     error: %s 
    ",str)   
    
    struct Distance;
    typedef struct Distance *Distance;
    struct Distance
    {
    	int vertexIndex;
    	int distance;
    };
    
    Distance makeEmptyDistance();
    

    2nd file:distance.c

    #include "distance.h"
    #include <malloc.h>
    
    // allocate the memory for Distance struct
    Distance makeEmptyDistance()
    {
    	Distance element;
    
    	element = (Distance)malloc(sizeof(struct Distance));
    	if(!element)
    	{
    		Error("out of space ,from func makeEmptyDistance");
    		return NULL;
    	}		
    
    	return element;
    }
    
    

    3rd file:binaryheap.h

    #include <stdio.h>
    #include <malloc.h>
    #include "distance.h"
    
    #define ElementType Distance
    
    #define Error(str) printf("
     error: %s 
    ",str)   
    
    struct BinaryHeap;
    typedef struct BinaryHeap *BinaryHeap;
    
    void swap(ElementType x, ElementType y);
    BinaryHeap initBinaryHeap(int capacity);
    void insert(ElementType value, BinaryHeap bh, int*);
    ElementType deleteMin(BinaryHeap, int*);
    int isFull(BinaryHeap bh);
    int isEmpty(BinaryHeap bh);
    void percolateUp(int index, BinaryHeap bh);
    void percolateDownFromOne(int index, BinaryHeap bh, int*);
    void printBinaryHeap(BinaryHeap bh);
    void printBinaryHeapFromZero(BinaryHeap bh);
    
    struct BinaryHeap 
    {
    	int capacity;
    	int size;	
    	ElementType *elements;		
    };
    

    4th file:binaryheap.c

    #include "binaryheap.h"
    #include <math.h>
    
    #define MaxInt (int)pow(2, 16)
    //judge whether the BinaryHeap is full or not , also 1 or 0 
    int isFull(BinaryHeap bh)
    {
    	return bh->size == bh->capacity - 1; 
    }
    
    //judge whether the BinaryHeap is empty or not , also 1 or 0 
    int isEmpty(BinaryHeap bh)
    {
    	return bh->size == 0;
    }
    
    // get the left child of node under index with startup 1
    int leftChildFromOne(int index)
    {
    	return index * 2;
    }
    
    void printBinaryHeap(BinaryHeap bh)
    {
    	int i;
    	ElementType *temp;
    	
    	if(!bh)
    		Error("printing execution failure, for binary heap is null, from func printBinaryHeap");	
    
    	temp = bh->elements;
    	for(i = 1; i < bh->capacity; i++)
    	{
    		printf("
    	 heap[%d] = ", i);
    		if(i <= bh->size)
    			printf("vertex[%d] + distance[%d]", bh->elements[i]->vertexIndex+1, bh->elements[i]->distance);		
    		else
    			printf("NULL");
    	}
    	printf("
    ");	
    }  
    
    //print the binary heap who starts from index 0
    void printBinaryHeapFromZero(BinaryHeap bh)
    {
    	int i;
    	ElementType *temp;
    	
    	if(!bh)
    		Error("printing execution failure, for binary heap is null, from func printBinaryHeap");	
    
    	temp = bh->elements;
    	for(i = 0; i < bh->capacity; i++)
    	{
    		printf("
    	 index[%d] = ", i);
    		if(i < bh->size)
    			printf("%d", bh->elements[i]->distance);
    		else
    			printf("NULL");
    	}
    	printf("
    ");
    }  
    
    void swap(ElementType x, ElementType y)
    {
    	struct Distance temp;
    	
    	temp = *x;
    	*x = *y;
    	*y = temp;	
    }
    
    ElementType deleteMin(BinaryHeap bh, int* heapIndexRecord)
    {	
    	ElementType minimum;
    	ElementType *data;	
    	
    	if(isEmpty(bh))
    	{
    		Error("failed deleting minimum , for the BinaryHeap is empty, from func deleteMin !");
    		return NULL;	
    	}
    
    	data = bh->elements;	 
    	minimum = data[1];
    	
    	swap(data[1], data[bh->size]);		
    	bh->size-- ; // size-- occurs prior to percolateDownFromOne 
    	percolateDownFromOne(1, bh, heapIndexRecord) ;	
    	return minimum;
    } 
    
    // percolating down the element when its value is greater than children (minimal heap)
     //Attention: all of bh->elements starts from index 1
     void percolateDownFromOne(int index, BinaryHeap bh, int* heapIndexRecord)
     {	
    	ElementType *data;
    	int size;
    	struct Distance temp;
    	int child;
    
    	data = bh->elements;
    	size = bh->size;	
    
    	for(temp = *data[index]; leftChildFromOne(index) <= size; index = child)
    	{
    		child = leftChildFromOne(index);
    		if(child < size && data[child]->distance > data[child+1]->distance)
    			child++;
    		if(temp.distance > data[child]->distance)
    		{			
    			*data[index] = *data[child];			
    			heapIndexRecord[bh->elements[index]->vertexIndex] = index; //update the heapIndexRecord
    		}
    		else
    			break;
    	}	
    	*data[index] = temp;	
    	heapIndexRecord[bh->elements[index]->vertexIndex] = index; //update the heapIndexRecord
     }
    
    // Attention, the index of the heap starts from 1
    // return the index the element inserted into the binary heap
    void insert(ElementType value, BinaryHeap bh, int* heapIndexRecord)
    {
    	int i;
    	
    	if(isFull(bh))
    	{
    		Error("failed insertion , for the BinaryHeap is full, from func insert!");
    		return ;	
    	}	
    	if(!isEmpty(bh))
    		for(i = ++bh->size; bh->elements[i/2]->distance > value->distance; i /= 2)		 			
    		{
    			//copyElement(bh->elements[i/2], bh->elements[i]);		 
    			*bh->elements[i] = *bh->elements[i/2];
    			heapIndexRecord[bh->elements[i]->vertexIndex] = i; //update the heapIndexRecord
    		}
    	else
    		i = ++bh->size;		
    	*bh->elements[i] = *value;
    	heapIndexRecord[bh->elements[i]->vertexIndex] = i; //update the heapIndexRecord
    }
    
    BinaryHeap initBinaryHeap(int capacity)
    {
    	BinaryHeap bh;
    	ElementType *temp;
    	int i;
    
    	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(Distance));
    	if(!temp) {
            Error("out of space, from func initBinaryHeap");        
            return NULL;
        } 
    	bh->elements = temp;
    	
    	for(i=0; i < capacity; i++)
    	{
    		temp[i] = (ElementType)malloc(sizeof(struct Distance));
    		if(!temp[i]) {
    			Error("out of space, from func initBinaryHeap");        
    			return NULL;
    		} 		
    	}
    
    	return bh;
    }
    
    // allocate the memory for storing index of  vertex in heap and let every element -1
    int *makeEmptyArray(int size)
    {
    	int *array;
    	int i;
    
    	array = (int*)malloc(size * sizeof(int));
    	if(!array)
    	{
    		Error("out of space ,from func makeEmptyArray");
    		return NULL;
    	}		
    	for(i=0; i<size; i++)
    		array[i] = -1;
    
    	return array;
    } 
    
    
    void printIndexOfVertexInHeap(int size, int *array)
    {
    	int i;
    
    	for(i=0; i<size; i++)	 
    		printf("	indexOfVertexInHeap[%d] = %d
    ", i+1, array[i]);	 
    }
    
    int main()
    {
    	int data[] = {85, 80, 40, 30, 10, 70, 110}; // P141	
    	int buildHeapData[] = {150, 80, 40, 30, 10, 70, 110, 100, 20, 90, 60, 50, 120, 140, 130};
    	BinaryHeap bh;	
    	int size;
    	int i;	
    	int capacity;
    	Distance tempDisStruct;
    	int *indexOfVertexInHeap;
    	
    	printf("
    	=== test for inserting the binary heap with {85, 80, 40, 30, 10, 70, 110} in turn ===
    ");
    	capacity = 14;
    	bh = initBinaryHeap(capacity);
    	size = 7;	
    	
    	tempDisStruct = makeEmptyDistance(); 
    	indexOfVertexInHeap = makeEmptyArray(size);
    
    	for(i = 0; i < size; i++) 
    	{
    		tempDisStruct->distance = data[i];
    		tempDisStruct->vertexIndex = i;
    		insert(tempDisStruct, bh, indexOfVertexInHeap);
    	}	
    	printBinaryHeap(bh);
    	printIndexOfVertexInHeap(bh->size, indexOfVertexInHeap);
    
    	printf("
    	=== test for inserting the binary heap with element {100, 20, 90} in turn ===
    ");
    	
    	tempDisStruct->distance = 100;
    	tempDisStruct->vertexIndex = size;
    	insert(tempDisStruct, bh, indexOfVertexInHeap);	
    	printBinaryHeap(bh);
    
    	tempDisStruct->distance = 20;
    	tempDisStruct->vertexIndex = size+1;
    	insert(tempDisStruct, bh, indexOfVertexInHeap);	
    	printBinaryHeap(bh);
    
    	tempDisStruct->distance = 90;
    	tempDisStruct->vertexIndex = size+2;
    	insert(tempDisStruct, bh, indexOfVertexInHeap);	
    	printBinaryHeap(bh);
    
    	printIndexOfVertexInHeap(bh->size, indexOfVertexInHeap);
    
    	printf("
    	=== test for inserting the binary heap with 5 ===
    ");	
    	tempDisStruct->distance = 5;
    	tempDisStruct->vertexIndex = size+3;
    	insert(tempDisStruct, bh, indexOfVertexInHeap);	
    	printBinaryHeap(bh);
    
    	printf("
    	=== test for 3 deletings towards the minimum in binary heap ===
    ");
    	deleteMin(bh, indexOfVertexInHeap);	
    	printBinaryHeap(bh);
    	deleteMin(bh, indexOfVertexInHeap);		
    	printBinaryHeap(bh);
    	deleteMin(bh, indexOfVertexInHeap);	
    	printBinaryHeap(bh);
    }
    
    
    

    3.3)printing results:
    这里写图片描述
    这里写图片描述
    这里写图片描述

  • 相关阅读:
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    linux中的cd ..和cd -命令有什么区别?
    GCC使用
  • 原文地址:https://www.cnblogs.com/pacoson/p/4976629.html
Copyright © 2011-2022 走看看