算法导论代码 第24章 单源最源路径

来源:互联网 发布:淘宝虚拟试衣间入口 编辑:程序博客网 时间:2024/05/20 09:09

24章 单源最源路径

24.1 Bellman-Ford算法

#include <stdio.h>#include <stdbool.h>#include <limits.h>#include <stdlib.h>#include <string.h>typedef struct graph_type *graph;struct edge {int u;int v;int w;};struct graph_node {int key;int w;struct graph_node *next;};void graph_node_ini(struct graph_node *x, int key, int w){x->key = key;x->w = w;x->next = NULL;}struct vertex {int dis;int parent;char str_vertex[256];//顶点的字符串表示,显示用};void vertex_ini(struct vertex *v){v->dis = INT_MAX;v->parent = -1;strcpy(v->str_vertex, "");}struct graph_type {struct graph_node **adj;struct vertex *vertex_array;int v_num;int e_num;};//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用graph graph_create(int v_num, char *str_vertex[]){graph g = malloc(sizeof(struct graph_type));g->v_num = v_num;g->e_num = 0;g->adj = malloc(sizeof(struct graph_node *) * v_num);g->vertex_array = malloc(sizeof(struct vertex) * v_num);for (int i = 0; i < v_num; i++) {g->adj[i] = NULL;strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);}return g;}void graph_destroy(graph g){for (int i = 0; i < g->v_num; i++) {for (struct graph_node * x = g->adj[i]; x != NULL;) {struct graph_node *del = x;x = x->next;free(del);}}free(g->adj);free(g->vertex_array);free(g);}void graph_insert_edge(graph g, struct edge e){struct graph_node *v = malloc(sizeof(struct graph_node));graph_node_ini(v, e.v, e.w);//从表头插入,将v插入到表头uv->next = g->adj[e.u];g->adj[e.u] = v;++g->e_num;}void graph_display(graph g){printf("%d vertices,%d edges\n", g->v_num, g->e_num);for (int i = 0; i < g->v_num; i++) {printf("%s: ", g->vertex_array[i].str_vertex);for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {printf("%s,%d ", g->vertex_array[x->key].str_vertex,       x->w);}printf("\n");}}void initialize_single_source(graph g, int s){for (int i = 0; i < g->v_num; i++) {g->vertex_array[i].dis = INT_MAX;g->vertex_array[i].parent = -1;}g->vertex_array[s].dis = 0;}void relax(graph g, int u, int v, int w){int dis = g->vertex_array[u].dis ==    INT_MAX ? INT_MAX : g->vertex_array[u].dis + w;if (g->vertex_array[v].dis > dis) {g->vertex_array[v].dis = dis;g->vertex_array[v].parent = u;}}bool graph_bellman_ford(graph g, int s){initialize_single_source(g, s);for (int i = 0; i < g->v_num - 1; i++) {for (int u = 0; u < g->v_num; u++) {for (struct graph_node * x = g->adj[u]; x != NULL;     x = x->next) {relax(g, u, x->key, x->w);}}}for (int u = 0; u < g->v_num; u++) {for (struct graph_node * x = g->adj[u]; x != NULL; x = x->next) {if (g->vertex_array[x->key].dis >    g->vertex_array[u].dis + x->w) {return false;}}}return true;}void graph_display_vertex(graph g){printf("各个顶点的数据:\n");for (int i = 0; i < g->v_num; i++) {printf("%s:%d\n", g->vertex_array[i].str_vertex,       g->vertex_array[i].dis);}}int main(){//数据根据书上的图24-4char *str_vertex[5] = { "s", "t", "x", "y", "z" };graph g = graph_create(5, str_vertex);struct edge edges[] = { {0, 1, 6}, {0, 3, 7}, {1, 2, 5},{1, 3, 8}, {1, 4, -4}, {2, 1, -2}, {3, 2, -3},{3, 4, 9}, {4, 0, 2}, {4, 2, 7}};for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {graph_insert_edge(g, edges[i]);}graph_display(g);graph_bellman_ford(g, 0);graph_display_vertex(g);}

24.2 有向无回路图中的单源最短路径

#include <stdio.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>typedef struct graph_type *graph;struct edge {int u;int v;int w;};struct graph_node {int key;int w;struct graph_node *next;};void graph_node_ini(struct graph_node *x, int key, int w){x->key = key;x->w = w;x->next = NULL;}struct vertex {int dis;int parent;bool in_queue;//是否在队列里面char str_vertex[256];//顶点的字符串表示,显示用};void vertex_ini(struct vertex *v){v->dis = INT_MAX;v->parent = -1;v->in_queue = false;strcpy(v->str_vertex, "");}struct graph_type {struct graph_node **adj;struct vertex *vertex_array;int v_num;int e_num;};//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用graph graph_create(int v_num, char *str_vertex[]){graph g = malloc(sizeof(struct graph_type));g->v_num = v_num;g->e_num = 0;g->adj = malloc(sizeof(struct graph_node *) * v_num);g->vertex_array = malloc(sizeof(struct vertex) * v_num);for (int i = 0; i < v_num; i++) {g->adj[i] = NULL;strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);}return g;}void graph_destroy(graph g){for (int i = 0; i < g->v_num; i++) {for (struct graph_node * x = g->adj[i]; x != NULL;) {struct graph_node *del = x;x = x->next;free(del);}}free(g->adj);free(g->vertex_array);free(g);}void graph_insert_edge(graph g, struct edge e){struct graph_node *v = malloc(sizeof(struct graph_node));graph_node_ini(v, e.v, e.w);//从表头插入,将v插入到表头uv->next = g->adj[e.u];g->adj[e.u] = v;++g->e_num;}void graph_display(graph g){printf("%d vertices,%d edges\n", g->v_num, g->e_num);for (int i = 0; i < g->v_num; i++) {printf("%s: ", g->vertex_array[i].str_vertex);for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {printf("%s,%d ", g->vertex_array[x->key].str_vertex,       x->w);}printf("\n");}}void graph_display_vertex(graph g){printf("各个顶点的数据:\n");for (int i = 0; i < g->v_num; i++) {printf("%s:%d\n", g->vertex_array[i].str_vertex,       g->vertex_array[i].dis);}}void swap(void *a, void *b, size_t elem_size){if (a == NULL || b == NULL || a == b)return;char temp[elem_size];/*变长数组 */memcpy(temp, a, elem_size);memcpy(a, b, elem_size);memcpy(b, temp, elem_size);}/*基于索引堆的优先队列*/typedef struct priority_queue_index_type *priority_queue;struct priority_queue_index_type {int heap_size;int *index_array;int *index_pos_array;/*这个数组记录了索引在堆中位置 */void *data_array;size_t elem_size;int (*comp) (const void *, const void *);};int parent(int i){return (i - 1) / 2;}int left_child(int i){return i * 2 + 1;}int right_child(int i){return i * 2 + 2;}void swap_index(priority_queue pq, int i, int j){swap(&pq->index_pos_array[i], &pq->index_pos_array[j], sizeof(int));pq->index_array[pq->index_pos_array[i]] = i;pq->index_array[pq->index_pos_array[j]] = j;}/*最小堆用的比较函数*/bool compare(priority_queue pq, int left, int right){if (pq->data_array == NULL)return false;char *pc_array = pq->data_array;return pq->comp(&pc_array[left * pq->elem_size],&pc_array[right * pq->elem_size]) > 0;}void heapify(priority_queue pq, int i){int left = left_child(i);int right = right_child(i);int largest = i;if (left < pq->heap_size    && compare(pq, pq->index_array[largest], pq->index_array[left])) {largest = left;}if (right < pq->heap_size    && compare(pq, pq->index_array[largest], pq->index_array[right])) {largest = right;}if (largest != i) {swap_index(pq, pq->index_array[i], pq->index_array[largest]);heapify(pq, largest);}}void fix_up(priority_queue pq, int i){while (i > 0       && compare(pq, pq->index_array[parent(i)], pq->index_array[i])) {swap_index(pq, pq->index_array[parent(i)], pq->index_array[i]);i = parent(i);}}priority_queue priority_queue_create(void *p_data_array, size_t elem_size,     int length, int (*comp) (const void *,      const void *)){priority_queue pq = malloc(sizeof(struct priority_queue_index_type));pq->index_array = malloc(sizeof(int) * length);pq->index_pos_array = malloc(sizeof(int) * length);pq->data_array = p_data_array;pq->elem_size = elem_size;pq->heap_size = 0;pq->comp = comp;return pq;}void priority_queue_destroy(priority_queue pq){free(pq->index_array);free(pq->index_pos_array);free(pq);}int priority_queue_top(priority_queue pq){return pq->index_array[0];}/*去掉并返回堆的第一个元素 */int priority_queue_extract_top(priority_queue pq){swap_index(pq, pq->index_array[0], pq->index_array[pq->heap_size - 1]);--pq->heap_size;heapify(pq, 0);return pq->index_array[pq->heap_size];}/*把元素的索引插入队列 */void priority_queue_insert(priority_queue pq, int index){++pq->heap_size;int i = pq->heap_size - 1;pq->index_array[i] = index;pq->index_pos_array[index] = i;fix_up(pq, i);}bool priority_queue_is_empty(priority_queue pq){return pq->heap_size == 0;}/*下标为index的数据修改了,调用这个函数来修复索引堆*/void priority_queue_change_index(priority_queue pq, int index){fix_up(pq, pq->index_pos_array[index]);heapify(pq, pq->index_pos_array[index]);}int cmp_vertex(const void *p1, const void *p2){const struct vertex *pa = p1;const struct vertex *pb = p2;if (pa->dis < pb->dis)return -1;if (pa->dis == pb->dis)return 0;return 1;}void initialize_single_source(graph g, int s){for (int i = 0; i < g->v_num; i++) {g->vertex_array[i].dis = INT_MAX;g->vertex_array[i].parent = -1;}g->vertex_array[s].dis = 0;}void relax(graph g, int u, int v, int w){int dis = g->vertex_array[u].dis ==    INT_MAX ? INT_MAX : g->vertex_array[u].dis + w;if (g->vertex_array[v].dis > dis) {g->vertex_array[v].dis = dis;g->vertex_array[v].parent = u;}}void dijkstra(graph g, int s){initialize_single_source(g, s);priority_queue pq =    priority_queue_create(g->vertex_array, sizeof(struct vertex),  g->v_num, cmp_vertex);for (int i = 0; i < g->v_num; i++) {priority_queue_insert(pq, i);}priority_queue_change_index(pq, s);while (!priority_queue_is_empty(pq)) {int u = priority_queue_extract_top(pq);for (struct graph_node * x = g->adj[u]; x != NULL; x = x->next) {int v = x->key;relax(g, u, v, x->w);priority_queue_change_index(pq, v);}}priority_queue_destroy(pq);}int main(){//数据根据书上的图24-6char *str_vertex[5] = { "s", "t", "x", "y", "z" };graph g = graph_create(5, str_vertex);struct edge edges[] =    { {0, 1, 10}, {0, 3, 5}, {1, 2, 1}, {1, 3, 2}, {2, 4, 4}, {3, 1, 3},{3, 4, 2}, {3, 2, 9}, {4, 0, 7}, {4, 2, 6}};for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {graph_insert_edge(g, edges[i]);}graph_display(g);dijkstra(g, 0);graph_display_vertex(g);graph_destroy(g);}

24.3 Dijkstra算法

24.3.1 Dijkstra算法,使用最小优先级队列实现

#include <stdio.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>typedef struct graph_type *graph;struct edge {int u;int v;int w;};struct graph_node {int key;int w;struct graph_node *next;};void graph_node_ini(struct graph_node *x, int key, int w){x->key = key;x->w = w;x->next = NULL;}struct vertex {int dis;int parent;char str_vertex[256];//顶点的字符串表示,显示用};void vertex_ini(struct vertex *v){v->dis = INT_MAX;v->parent = -1;strcpy(v->str_vertex, "");}struct graph_type {struct graph_node **adj;struct vertex *vertex_array;int v_num;int e_num;};//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用graph graph_create(int v_num, char *str_vertex[]){graph g = malloc(sizeof(struct graph_type));g->v_num = v_num;g->e_num = 0;g->adj = malloc(sizeof(struct graph_node *) * v_num);g->vertex_array = malloc(sizeof(struct vertex) * v_num);for (int i = 0; i < v_num; i++) {g->adj[i] = NULL;strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);}return g;}void graph_destroy(graph g){for (int i = 0; i < g->v_num; i++) {for (struct graph_node * x = g->adj[i]; x != NULL;) {struct graph_node *del = x;x = x->next;free(del);}}free(g->adj);free(g->vertex_array);free(g);}void graph_insert_edge(graph g, struct edge e){struct graph_node *v = malloc(sizeof(struct graph_node));graph_node_ini(v, e.v, e.w);//从表头插入,将v插入到表头uv->next = g->adj[e.u];g->adj[e.u] = v;++g->e_num;}void graph_display(graph g){printf("%d vertices,%d edges\n", g->v_num, g->e_num);for (int i = 0; i < g->v_num; i++) {printf("%s: ", g->vertex_array[i].str_vertex);for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {printf("%s,%d ", g->vertex_array[x->key].str_vertex,       x->w);}printf("\n");}}void graph_display_vertex(graph g){printf("各个顶点的数据:\n");for (int i = 0; i < g->v_num; i++) {printf("%s:%d\n", g->vertex_array[i].str_vertex,       g->vertex_array[i].dis);}}void swap(void *a, void *b, size_t elem_size){if (a == NULL || b == NULL || a == b)return;char temp[elem_size];/*变长数组 */memcpy(temp, a, elem_size);memcpy(a, b, elem_size);memcpy(b, temp, elem_size);}/*基于索引堆的优先队列*/typedef struct priority_queue_index_type *priority_queue;struct priority_queue_index_type {int heap_size;int *index_array;int *index_pos_array;/*这个数组记录了索引在堆中位置 */void *data_array;size_t elem_size;int (*comp) (const void *, const void *);};int parent(int i){return (i - 1) / 2;}int left_child(int i){return i * 2 + 1;}int right_child(int i){return i * 2 + 2;}void swap_index(priority_queue pq, int i, int j){swap(&pq->index_pos_array[i], &pq->index_pos_array[j], sizeof(int));pq->index_array[pq->index_pos_array[i]] = i;pq->index_array[pq->index_pos_array[j]] = j;}/*最小堆用的比较函数*/bool compare(priority_queue pq, int left, int right){if (pq->data_array == NULL)return false;char *pc_array = pq->data_array;return pq->comp(&pc_array[left * pq->elem_size],&pc_array[right * pq->elem_size]) > 0;}void heapify(priority_queue pq, int i){int left = left_child(i);int right = right_child(i);int largest = i;if (left < pq->heap_size    && compare(pq, pq->index_array[largest], pq->index_array[left])) {largest = left;}if (right < pq->heap_size    && compare(pq, pq->index_array[largest], pq->index_array[right])) {largest = right;}if (largest != i) {swap_index(pq, pq->index_array[i], pq->index_array[largest]);heapify(pq, largest);}}void fix_up(priority_queue pq, int i){while (i > 0       && compare(pq, pq->index_array[parent(i)], pq->index_array[i])) {swap_index(pq, pq->index_array[parent(i)], pq->index_array[i]);i = parent(i);}}priority_queue priority_queue_create(void *p_data_array, size_t elem_size,     int length, int (*comp) (const void *,      const void *)){priority_queue pq = malloc(sizeof(struct priority_queue_index_type));pq->index_array = malloc(sizeof(int) * length);pq->index_pos_array = malloc(sizeof(int) * length);pq->data_array = p_data_array;pq->elem_size = elem_size;pq->heap_size = 0;pq->comp = comp;return pq;}void priority_queue_destroy(priority_queue pq){free(pq->index_array);free(pq->index_pos_array);free(pq);}int priority_queue_top(priority_queue pq){return pq->index_array[0];}/*去掉并返回堆的第一个元素 */int priority_queue_extract_top(priority_queue pq){swap_index(pq, pq->index_array[0], pq->index_array[pq->heap_size - 1]);--pq->heap_size;heapify(pq, 0);return pq->index_array[pq->heap_size];}/*把元素的索引插入队列 */void priority_queue_insert(priority_queue pq, int index){++pq->heap_size;int i = pq->heap_size - 1;pq->index_array[i] = index;pq->index_pos_array[index] = i;fix_up(pq, i);}bool priority_queue_is_empty(priority_queue pq){return pq->heap_size == 0;}/*下标为index的数据修改了,调用这个函数来修复索引堆*/void priority_queue_change_index(priority_queue pq, int index){fix_up(pq, pq->index_pos_array[index]);heapify(pq, pq->index_pos_array[index]);}int cmp_vertex(const void *p1, const void *p2){const struct vertex *pa = p1;const struct vertex *pb = p2;if (pa->dis < pb->dis)return -1;if (pa->dis == pb->dis)return 0;return 1;}void initialize_single_source(graph g, int s){for (int i = 0; i < g->v_num; i++) {g->vertex_array[i].dis = INT_MAX;g->vertex_array[i].parent = -1;}g->vertex_array[s].dis = 0;}void relax(graph g, int u, int v, int w){int dis = g->vertex_array[u].dis ==    INT_MAX ? INT_MAX : g->vertex_array[u].dis + w;if (g->vertex_array[v].dis > dis) {g->vertex_array[v].dis = dis;g->vertex_array[v].parent = u;}}void dijkstra(graph g, int s){initialize_single_source(g, s);priority_queue pq =    priority_queue_create(g->vertex_array, sizeof(struct vertex),  g->v_num, cmp_vertex);for (int i = 0; i < g->v_num; i++) {priority_queue_insert(pq, i);}priority_queue_change_index(pq, s);while (!priority_queue_is_empty(pq)) {int u = priority_queue_extract_top(pq);for (struct graph_node * x = g->adj[u]; x != NULL; x = x->next) {int v = x->key;relax(g, u, v, x->w);priority_queue_change_index(pq, v);}}priority_queue_destroy(pq);}int main(){//数据根据书上的图24-6char *str_vertex[5] = { "s", "t", "x", "y", "z" };graph g = graph_create(5, str_vertex);struct edge edges[] =    { {0, 1, 10}, {0, 3, 5}, {1, 2, 1}, {1, 3, 2}, {2, 4, 4}, {3, 1, 3},{3, 4, 2}, {3, 2, 9}, {4, 0, 7}, {4, 2, 6}};for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {graph_insert_edge(g, edges[i]);}graph_display(g);dijkstra(g, 0);graph_display_vertex(g);graph_destroy(g);return 0;}

24.3.2 Dijkstra算法,使用斐波那契堆实现

#include <stdio.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>#include <math.h>typedef struct graph_type *graph;struct edge {int u;int v;int w;};struct graph_node {int key;int w;struct graph_node *next;};void graph_node_ini(struct graph_node *x, int key, int w){x->key = key;x->w = w;x->next = NULL;}struct vertex {int v;//顶点int dis;int parent;char str_vertex[256];//顶点的字符串表示,显示用};void vertex_ini(struct vertex *v){v->v = -1;v->dis = INT_MAX;v->parent = -1;strcpy(v->str_vertex, "");}struct graph_type {struct graph_node **adj;struct vertex *vertex_array;int v_num;int e_num;};//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用graph graph_create(int v_num, char *str_vertex[]){graph g = malloc(sizeof(struct graph_type));g->v_num = v_num;g->e_num = 0;g->adj = malloc(sizeof(struct graph_node *) * v_num);g->vertex_array = malloc(sizeof(struct vertex) * v_num);for (int i = 0; i < v_num; i++) {g->adj[i] = NULL;strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);}return g;}void graph_destroy(graph g){for (int i = 0; i < g->v_num; i++) {for (struct graph_node * x = g->adj[i]; x != NULL;) {struct graph_node *del = x;x = x->next;free(del);}}free(g->adj);free(g->vertex_array);free(g);}void graph_insert_edge(graph g, struct edge e){struct graph_node *v = malloc(sizeof(struct graph_node));graph_node_ini(v, e.v, e.w);//从表头插入,将v插入到表头uv->next = g->adj[e.u];g->adj[e.u] = v;++g->e_num;}void graph_display(graph g){printf("%d vertices,%d edges\n", g->v_num, g->e_num);for (int i = 0; i < g->v_num; i++) {printf("%s: ", g->vertex_array[i].str_vertex);for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {printf("%s,%d ", g->vertex_array[x->key].str_vertex,       x->w);}printf("\n");}}void graph_display_vertex(graph g){printf("各个顶点的数据:\n");for (int i = 0; i < g->v_num; i++) {printf("%s:%d\n", g->vertex_array[i].str_vertex,       g->vertex_array[i].dis);}}typedef struct heap *heap;struct heap_node {void *key;int degree;bool mark;struct heap_node *child;struct heap_node *left;struct heap_node *right;struct heap_node *parent;};struct heap {int (*comp) (const void *, const void *);struct heap_node *min;int num;};void heap_node_ini(struct heap_node *x, void *key){x->key = key;x->degree = 0;x->mark = false;x->parent = NULL;x->child = NULL;x->left = x;x->right = x;}void swap(void *a, void *b, size_t elem_size){if (a == NULL || b == NULL || a == b)return;char temp[elem_size];/*变长数组 */memcpy(temp, a, elem_size);memcpy(a, b, elem_size);memcpy(b, temp, elem_size);}heap heap_create(int (*comp) (const void *, const void *)){heap h = malloc(sizeof(struct heap));h->comp = comp;h->num = 0;h->min = NULL;return h;}//删除结点,如果只有x一个结点的话,这个函数无效void list_delete(struct heap_node **pos, struct heap_node *x){if (x->right == x)//只有一个结点{*pos = NULL;return;}x->left->right = x->right;x->right->left = x->left;if (*pos == x) {*pos = x->right;}}//插入结点x到pos的左边,如果pos为空,pos=xvoid list_insert(struct heap_node **pos, struct heap_node *x){if (*pos == NULL) {*pos = x;x->left = x;x->right = x;} else {x->left = (*pos)->left;(*pos)->left->right = x;x->right = (*pos);(*pos)->left = x;}}void add_root(heap h, struct heap_node *x){list_insert(&h->min, x);x->parent = NULL;x->mark = false;if (h->comp(x->key, h->min->key) < 0) {h->min = x;}}//下面的过程将结点x插入斐波那契堆中,假定结点x已被分配,且key[x]也已填有内容void heap_insert(heap h, struct heap_node *x){x->degree = 0;x->parent = NULL;x->child = NULL;x->left = x;x->right = x;add_root(h, x);++h->num;}//最小结点struct heap_node *heap_minimum(heap h){return h->min;}void heap_destroy(heap h);//将另一个斐波那契堆合并到当前堆,另一堆合并到当前最小结点的右边void heap_union(heap ha, heap hb){if (hb == NULL || hb->min == NULL) {return;}if (ha->min == NULL) {ha->min = hb->min;} else {//最小结点的右边结点struct heap_node *ha_min_right = ha->min->right;ha->min->right = hb->min;//另一个堆最小结点的左结点,即最后一个结点struct heap_node *hb_min_left = hb->min->left;hb->min->left = ha->min;hb_min_left->right = ha_min_right;ha_min_right->left = hb_min_left;}if (ha->min == NULL    || (hb->min != NULL && ha->comp(hb->min->key, ha->min->key) < 0)) {ha->min = hb->min;}ha->num += hb->num;hb->min = NULL;heap_destroy(hb);}void link(heap h, struct heap_node *y, struct heap_node *x){list_delete(&h->min, y);list_insert(&x->child, y);y->parent = x;y->mark = false;++x->degree;}//合并根表void consolidate(heap h){if (h->min == NULL)return;int D = floor(log(h->num) / log(1.618));//计算D值struct heap_node *A[D];for (int i = 0; i < D; i++) {A[i] = NULL;}struct heap_node *x = NULL;struct heap_node *y = NULL;int d;struct heap_node *w = h->min;struct heap_node *end = h->min->left;bool loop_flag = true;while (loop_flag) {x = w;if (w != end) {w = w->right;} else {loop_flag = false;//w到达最后一个结点,循环结束}d = x->degree;while (A[d] != NULL) {y = A[d];if (h->comp(x->key, y->key) > 0) {swap(&x, &y, sizeof(struct heap_node *));}link(h, y, x);A[d] = NULL;++d;}A[d] = x;}h->min = NULL;for (int i = 0; i < D; ++i) {if (A[i] != NULL) {add_root(h, A[i]);}}}//抽取具有最小关键字的结点,并返回一个指向该结点的指针struct heap_node *heap_extract_min(heap h){struct heap_node *z = h->min;if (z == NULL)return NULL;struct heap_node *x = NULL;while (z->degree > 0) {x = z->child;if (x->right == x) {z->child = NULL;} else {z->child = z->child->right;}list_delete(&z->child, x);add_root(h, x);--z->degree;}if (z == z->right) {list_delete(&h->min, z);} else {list_delete(&h->min, z);consolidate(h);}--h->num;return z;}void cut(heap h, struct heap_node *x, struct heap_node *y){list_delete(&y->child, x);add_root(h, x);--y->degree;}void cascading_cut(heap h, struct heap_node *y){struct heap_node *z = y->parent;if (z == NULL)return;if (y->mark == false) {y->mark = true;} else {cut(h, y, z);cascading_cut(h, z);}}//将斐波那契堆中的某一结点x的关键字减少为一个新值k,如果k大于x的当前关键字值,直接返回void heap_decrease_key(heap h, struct heap_node *x){struct heap_node *y = x->parent;if (y != NULL && h->comp(x->key, y->key) < 0) {cut(h, x, y);cascading_cut(h, y);}if (h->comp(x->key, h->min->key) < 0) {h->min = x;}}bool heap_is_empty(heap h){return h->min == NULL;}void heap_destroy(heap h){while (!heap_is_empty(h)) {struct heap_node *x = heap_extract_min(h);free(x->key);free(x);}free(h);}int cmp_vertex(const void *p1, const void *p2){const struct vertex *pa = p1;const struct vertex *pb = p2;if (pa->dis < pb->dis)return -1;if (pa->dis == pb->dis)return 0;return 1;}void initialize_single_source(graph g, int s){for (int i = 0; i < g->v_num; i++) {g->vertex_array[i].dis = INT_MAX;g->vertex_array[i].parent = -1;}g->vertex_array[s].dis = 0;}void relax(graph g, int u, int v, int w){int dis = g->vertex_array[u].dis ==    INT_MAX ? INT_MAX : g->vertex_array[u].dis + w;if (g->vertex_array[v].dis > dis) {g->vertex_array[v].dis = dis;g->vertex_array[v].parent = u;}}void dijkstra(graph g, int s){heap h = heap_create(cmp_vertex);struct heap_node *x = NULL;struct heap_node *node_array[g->v_num];struct vertex *p_vertex;initialize_single_source(g, s);for (int i = 0; i < g->v_num; i++) {x = malloc(sizeof(struct heap_node));heap_node_ini(x,&g->vertex_array[i]);p_vertex = x->key;p_vertex->v = i;node_array[i] = x;heap_insert(h, x);}heap_decrease_key(h, node_array[s]);while (!heap_is_empty(h)) {x = heap_extract_min(h);p_vertex = x->key;int u = p_vertex->v;free(x);node_array[u] = NULL;for (struct graph_node * x = g->adj[u]; x != NULL; x = x->next) {int v = x->key;if (node_array[v] != NULL) {relax(g, u, v, x->w);heap_decrease_key(h, node_array[v]);}}}heap_destroy(h);}int main(){//数据根据书上的图24-6char *str_vertex[5] = { "s", "t", "x", "y", "z" };graph g = graph_create(5, str_vertex);struct edge edges[] =    { {0, 1, 10}, {0, 3, 5}, {1, 2, 1}, {1, 3, 2}, {2, 4, 4}, {3, 1, 3},{3, 4, 2}, {3, 2, 9}, {4, 0, 7}, {4, 2, 6}};for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {graph_insert_edge(g, edges[i]);}graph_display(g);dijkstra(g, 0);graph_display_vertex(g);graph_destroy(g);}