图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)

原创 2015年11月19日 09:40:48

【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("\n error: %s \n",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("\n error: %s \n",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("\n\t 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("\n");   
}  

//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("\n\t index[%d] = ", i);
        if(i < bh->size)
            printf("%d", bh->elements[i]->distance);
        else
            printf("NULL");
    }
    printf("\n");
}  

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("\tindexOfVertexInHeap[%d] = %d\n", 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("\n\t=== test for inserting the binary heap with {85, 80, 40, 30, 10, 70, 110} in turn ===\n");
    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("\n\t=== test for inserting the binary heap with element {100, 20, 90} in turn ===\n");

    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("\n\t=== test for inserting the binary heap with 5 ===\n");  
    tempDisStruct->distance = 5;
    tempDisStruct->vertexIndex = size+3;
    insert(tempDisStruct, bh, indexOfVertexInHeap); 
    printBinaryHeap(bh);

    printf("\n\t=== test for 3 deletings towards the minimum in binary heap ===\n");
    deleteMin(bh, indexOfVertexInHeap); 
    printBinaryHeap(bh);
    deleteMin(bh, indexOfVertexInHeap);     
    printBinaryHeap(bh);
    deleteMin(bh, indexOfVertexInHeap); 
    printBinaryHeap(bh);
}

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

最小生成树之Prim算法 优先队列版本

优先队列之Prim
  • xinwen1995
  • xinwen1995
  • 2016年04月06日 20:48
  • 1660

eoj1817 dijkstra单元最短路径 普通方法+二叉堆优化

求出有n(1 Input 第一行有2个整数n和m(0 Output 输出结点1到结点n之间的最短路径,如果1到n之间不存在路径,输出 -1。 Sample Input 3 3 ...
  • FANGPINLEI
  • FANGPINLEI
  • 2014年12月31日 08:38
  • 1444

EOJ 1848 你是ACM吗? 用二叉堆优化dijkstra + spfa算法的学习

Description  随着中国经济的腾飞,中国的物流产业迎来了发展的春天。特别是在上海这样一个拥有广阔国内腹地的国际化大都市,物流业以空前的速度膨胀。 当然是大蛋糕就会吸引许多馋嘴猫,馋嘴猫多了...
  • FANGPINLEI
  • FANGPINLEI
  • 2014年12月17日 17:08
  • 1039

Prim算法实现最小生成树(图模型+小根堆)

Prim算法实现最小生成树的思想是:在图中取一个顶点为起始点,找出其邻接的所有顶点,将该点和邻接的顶点和边的权值一一压入小根堆中,接着从小根堆中退出小根堆的根,将没访问过的两个顶点及其关联边的权值插入...
  • iqRocket
  • iqRocket
  • 2012年12月05日 18:04
  • 3462

最小生成树之Prim算法

普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。该算法于1930年由捷...
  • luomingjun12315
  • luomingjun12315
  • 2015年08月23日 07:28
  • 2666

映射二叉堆+Dijkstra

幽幽子 #include #include #define N 100010 #define M 400010 #define INF 999999999 int n,m,s,a,b; int ...
  • liujie619406439
  • liujie619406439
  • 2013年05月17日 14:52
  • 1071

优先队列优化prim算法

POJ 1251 #include #include #include #include #include #include #include #include #include ...
  • Acceptedxukai
  • Acceptedxukai
  • 2011年11月16日 21:37
  • 3746

Prim堆优化

好久没写博客了,想坚持下来真是挺不容易的呢,这段时间没做什么呢,从今天起继续写博客,加油,为今年区域赛好好准备,以前一直不太明白prim怎么堆优化,今天终于想明白了。 #1109 : 最...
  • u013268685
  • u013268685
  • 2015年04月01日 23:40
  • 980

hihoCoder_#1109_堆优化的Prim算法

#1109 : 最小生成树三·堆优化的Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 回到两个星期之前,在成功的使用Kruscal算法解决了问...
  • jhgkjhg_ugtdk77
  • jhgkjhg_ugtdk77
  • 2015年07月27日 10:42
  • 1958

图基本算法 最小生成树 Prim算法(邻接表/邻接矩阵+优先队列STL)

这篇文章是对《算法导论》上Prim算法求无向连通图最小生成树的一个总结,其中有关于我的一点点小看法。   最小生成树的具体问题可以用下面的语言阐述:     输入:一个无向带权图G=(V,E)...
  • tham_
  • tham_
  • 2015年05月27日 16:47
  • 3135
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)
举报原因:
原因补充:

(最多只允许输入30个字)