icoding复习6 图
icoding復習6?
1. 鄰接表1
 試在鄰接表存儲結構上實現圖的基本操作 insert_vertex 和 insert_arc,相關定義如下:
 typedef int VertexType;
 typedef enum{
 ? ? DG, UDG
 }GraphType;
 typedef struct ArcNode{
 ? ? int adjvex;
 ? ? InfoPtr *info;
 ? ? struct ArcNode *nextarc;
 }ArcNode;
 typedef struct VNode{
 ? ? VertexType data;
 ? ? ArcNode *firstarc;
 }VNode;
 typedef struct{
 ? ? VNode vertex[MAX_VERTEX_NUM];
 ? ? int vexnum, arcnum;
 ? ? GraphType type;
 }ListGraph;
 int locate_vertex(ListGraph* G, VertexType v); //返回頂點 v 在vertex數組中的下標,如果v不存在,返回-1
 bool insert_vertex(ListGraph *G, VertexType v);
 bool insert_arc(ListGraph *G, VertexType v, VertexType w);
 當成功插入頂點或邊時,函數返回true,否則(如頂點或邊已存在、插入邊時頂點v或w不存在)返回false。
//寫下locate函數
 int locate_vertex(ListGraph *G, VertexType v){
 ?? ?int i;
 ?? ?for(i = 0; i < G->vexnum; i++)
 ?? ??? ?if(G->vertex[i].data == v)
 ?? ??? ??? ?return i;
 ?? ?return -1;
 }?
 #include 
 #include
 //記得加這個頭文件消除黃色警告?
 #include "graph.h" //請勿刪除,否則檢查不通過
 bool insert_vertex(ListGraph *G, VertexType v){
 ?? ?int ?i = 0;
 ?? ?//2個易錯點: 指針置空,可以省略; 點運算符!!務必區分?
 ?? ?i = locate_vertex(G, v);
 ?? ?if(i != -1) return false;
 ?? ?G->vertex[G->vexnum].data = v;
 ?? ?G->vertex[G->vexnum].firstarc = NULL;
 ?? ?G->vexnum++;
 ?? ?return true;?
 }
bool insert_arc(ListGraph *G, VertexType v, VertexType w){
 ?? ?int i = locate_vertex(G, v);
 ?? ?int j = locate_vertex(G, w);
 ?? ?
 ?? ?//點不存在?
 ?? ?if(i == -1 || j == -1) return false;
 ?? ?//邊已經存在
 ?? ?ArcNode *p = G->vertex[i].firstarc;
 ?? ?for(; p; p = p->nextarc)
 ?? ??? ?if(p->adjvex == j)
 ?? ??? ??? ?return false;?
 ?? ??? ?
 ?? ?ArcNode *q;
 ?? ?p = G->vertex[i].firstarc;
 ?? ?if(!(q = (ArcNode *)malloc(sizeof(ArcNode)))) return false;?? ?
 ?? ?q->adjvex = j;
 ?? ?if(!p){
 ?? ??? ?G->vertex[i]->firstarc = q;
 ?? ??? ?q->nextarc = NULL;
 ?? ?}
 ?? ?else{
 ?? ??? ?q->nextarc = p->nextarc;
 ?? ??? ?p->nextarc = q;?
 ?? ?}
 ?? ?G->arcnum++;?
 ?? ?return true;
 }
//第一次的思路
 bool insert_arc(ListGraph *G, VertexType v, VertexType w){
 ?? ?int i, j;
 ?? ?ArcNode *p;
 ?? ?
 ?? ?i = locate_vertex(G, v);
 ?? ?j = locate_vertex(G, w);
 ?? ?
 ?? ?//判結點是否存在,不存在就返回false?
 ?? ?if(i == -1|| j == -1)
 ?? ??? ?return false;
 ?? ??? ?
 ?? ?//判邊是否存在,存在就返回false?
 ?? ?//需要注意的是p->adjvex = j這個判斷條件,一個是int類型,一個是不要把這個判斷條件放到for里面?
 ?? ?for(p = G->vertex[i].firstarc; ?p; p = p->nextarc)
 ?? ??? ?if(p->adjvex == j) ?? ?return false;
 ?? ?
 ?? ?//!!!!!需要注意的是這里是單項插入,不考慮有向無向
 ?? ?//插入到方向就是v-->w?
 //?? ?for(p = G->vertex[j].firstarc; ?p; p = p->nextarc)
 //?? ?if(p->adjvex == i) ?return false;
?? ?
 //?? ?if(G->type == UDG){
 //?? ??? ?p->nextarc = G->vertex[j].firstarc->nextarc;
 //?? ??? ?p->adjvex = v;
 //?? ??? ?G->vertex[j].firstarc = p;?
 //?? ?}
//!!!別忘了分配空間,這個是建立一個新的節點?
 ?? ?p = (ArcNode *)malloc(sizeof(ArcNode));
 ?? ?p->adjvex = j;
 ?? ?G->arcnum++;?
 ?? ?if(!G->vertex[i].firstarc)//空的情況?
 ?? ??? ?G->vertex[i].firstarc = p;
 ?? ?else{//頭插 G->vertex[i].firstarc是頭結點?
 ?? ??? ?p->nextarc = G->vertex[i].firstarc->nextarc;
 ?? ??? ?G->vertex[i].firstarc = p;
 ?? ?}
 ?? ?return true;?? ?
 }?
 2. 鄰接表2
試在鄰接表存儲結構上實現圖的基本操作 del_vertex,相關定義如下:
typedef int VertexType;
typedef enum{
 ? ? DG, UDG
 }GraphType;
typedef struct ArcNode{
 ? ? int adjvex;
 ? ? InfoPtr *info;
 ? ? struct ArcNode *nextarc;
 }ArcNode;
typedef struct VNode{
 ? ? VertexType data;
 ? ? ArcNode *firstarc;
 }VNode;
 typedef struct{
 ? ? VNode vertex[MAX_VERTEX_NUM];
 ? ? int vexnum, arcnum;
 ? ? GraphType type;
 }ListGraph;
int locate_vertex(ListGraph *G, VertexType v); //返回頂點 v 在vertex數組中的下標,如果v不存在,返回-1
 bool del_vertex(ListGraph *G, VertexType v); //刪除頂點 v
 當成功刪除頂點或邊時,函數返回true,否則(如頂點或邊不存在、刪除邊時頂點v或w不存在)返回false。
#include ?
 #include 
 #include "graph.h" //請勿刪除,否則檢查不通過
 bool del_vertex(ListGraph* G, VertexType v){
 ?? ?int i = locate_vertex(G, v), j;
 ?? ?if(i == -1) return false;
 ?? ?j = i;
 ?? ?ArcNode *p, *q;
 ?? ?
 ?? ?
 ?? ?for(p = G->vertex[i].firstarc; p;){
 ?? ??? ?q = p;
 ?? ??? ?p = p->nextarc;
 ?? ??? ?free(q);
 ?? ??? ?G->arcnum--;
 ?? ?}?
 ?? ?free(G->vertex[i].firstarc); G->arcnum--;//在最后丟表頭, 注意點, 這里不能理解為沒有數據的頭結點?
 ?? ?
 ?? ?for(; i < G->vexnum; i++)
 ?? ??? ?G->vertex[i] = G->vertex[i+1];
 ?? ?G->vexnum--;
 ?? ?
 ?? ?for(i = 0; i < G->vexnum; i++){
 ?? ??? ?for(p = G->vertex[i].firstarc, q = p; p->adjvex != j && p ;q = p, p = p->nextarc)
 ?? ??? ??? ?;
 ?? ??? ?if(p->adjvex == j){
 ?? ??? ??? ?if(p == G->vertex[i].firstarc)
 ?? ??? ??? ??? ?G->vertex[i].firstarc = p->nextarc;//隱含q == p?
 ?? ??? ??? ?else
 ?? ??? ??? ??? ?q->nextarc = p->nextarc;
 ?? ??? ??? ?free(p);
 ?? ??? ??? ?G->arcnum--;
 ?? ??? ?}?
 ?? ?}
 }
//答案如下?
 //思路整理
 //1. 定位該節點是否存在,若存在
 //2. 刪除該結點以之為弧尾的鏈表, 挨著刪,最后刪除表頭, 邊數減少?
 //3. 結點序列前移, 結點總數減少?
 //4. 遍歷鄰接表找以刪除結點為弧頭的鏈, 刪除...?
 bool del_vertex(ListGraph* G, VertexType v)
 {
 ? ? int i, j = locate_vertex(G, v);
 ? ? if (j == -1) //檢查是否存在該節點
 ? ? ? ? return false;?
 ? ??
 ? ? //先刪除從該節點出發的邊和該節點
 ? ? while (G->vertex[j].firstarc) {?
 ? ? ? ? ArcNode* p = G->vertex[j].firstarc;
 ? ? ? ? if (p->nextarc) { //先free表頭結點后面的
 ? ? ? ? ? ? ArcNode* q = p->nextarc;
 ? ? ? ? ? ? p->nextarc = q->nextarc;
 ? ? ? ? ? ? free(q);
 ? ? ? ? } else {
 ? ? ? ? ? ? free(p); //free表頭結點
 ? ? ? ? ? ? G->vertex[j].firstarc = NULL;
 ? ? ? ? }
 ? ? ? ? G->arcnum--; //邊的數量-1
 ? ? }
 ? ? G->vexnum--; //結點的數量-1
 ? ? for (i = j; i < G->vexnum; i++) { //表頭結點中,后面的向前移動
 ? ? ? ? G->vertex[i] = G->vertex[i + 1];
 ? ? }
 ? ??
 ? ? //再刪除到該節點的邊
 ? ? for (i = 0; i < G->vexnum; i++) {
 ? ? ? ? ArcNode *p = G->vertex[i].firstarc, *pNode = NULL;
 ? ? ? ? ArcNode* q; //存儲要被刪掉的結點
 ? ? ? ? while (p) {
 ? ? ? ? ? ? if (p->adjvex == j) { //P的下個結點是V
 ? ? ? ? ? ? ? ? if (!pNode) { //P是表頭結點
 ? ? ? ? ? ? ? ? ? ? q = G->vertex[i].firstarc;
 ? ? ? ? ? ? ? ? ? ? G->vertex[i].firstarc = p->nextarc;
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? ? else {
 ? ? ? ? ? ? ? ? ? ? pNode->nextarc = p->nextarc;
 ? ? ? ? ? ? ? ? ? ? q = p;
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? ? p = p->nextarc;
 ? ? ? ? ? ? ? ? free(q);
 ? ? ? ? ? ? ? ? G->arcnum--;
 ? ? ? ? ? ? } else {
 ? ? ? ? ? ? ? ? pNode = p;
 ? ? ? ? ? ? ? ? p = p->nextarc;
 ? ? ? ? ? ? }
 ? ? ? ? }
 ? ? }
 ? ? return true;
 }
3. 鄰接矩陣
試在鄰接矩陣存儲結構上實現圖的基本操作 matrix_insert_vertex 和matrix_insert_arc,相關定義如下:
typedef int VertexType;
typedef enum{
 ? ? DG, UDG
 }GraphType;
typedef struct{
 ? ? VertexType vertex[MAX_VERTEX_NUM]; //頂點向量
 ? ? int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //鄰接矩陣
 ? ? int vexnum, arcnum; ? //圖的當前頂點數和弧數
 ? ? GraphType type; ? ? //圖的種類標志
 }MatrixGraph;
int matrix_locate_vertex(MatrixGraph *MG, VertexType vex); //返回頂點 v 在vertex數組中的下標,
 //如果v不存在,返回-1
 bool matrix_insert_vertex(MatrixGraph *G, VertexType v);
 bool matrix_insert_arc(MatrixGraph *G, VertexType v, VertexType w);
 當成功插入頂點或邊時,函數返回true,否則(如頂點或邊已存在、插入邊時頂點v或w不存在)返回false。
#include ?
 #include "graph.h" // 請不要刪除,否則檢查不通過
bool matrix_insert_vertex(MatrixGraph *G, VertexType v){
 ?? ?int i = matrix_locate_vertex(G, v);
 ?? ?
 ?? ?if(i != -1 || G->vexnum == MAX_VERTEX_NUM - 1) return false;
 ?? ?
 ?? ?G->vertex[G->vexnum] = v;
 ?? ?for(i = 0; i < G->vexnum; i++){
 ?? ??? ?G->arcs[G->vexnum][i] = 0;
 ?? ??? ?G->arcs[i][G->vexnum] = 0;
 ?? ?}
 ?? ?G->arcnum++;
 ?? ?return true;
 }
bool matrix_insert_arc(MatrixGraph *G, VertexType v, VertexType w){
 ?? ?int i = matrix_locate_vertex(G, v);
 ?? ?int j = matrix_locate_vertex(G, w);
 ?? ?
 ?? ?if(i == -1 || j == -1 || G->arcs[i][j] == 1) return false;
 //如果加上判斷圖的類型?
 //?? ?if(G->type == UDG &&( G->arcs[i][j] == 1 || G->arcs[j][i] == 1))
 //?? ??? ?return false;
 //?? ?else if(G->arcs[i][j] == 1)?? ?
 //?? ??? ?return false;
 ?? ?G->arcs[i][j] = 1;
 ?? ?if(G->type == UDG)
 ?? ??? ?G->arcs[j][i] = 1;
 ?? ?G->arcnum++;
 ?? ?return true;
 }
 ?
總結
以上是生活随笔為你收集整理的icoding复习6 图的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: icoding复习1,2
- 下一篇: icoding复习3
