#include <stdio.h>
#include <stdlib.h>
#define MaxNum 100 //最大頂點數
#define STACKSIZE 100
typedef struct ArcNode //表結點
{
int adjvex; //存放表結點的頂點域
struct ArcNode * nextarc; //指向下一個表結點的指標
} ArcNode;
typedef struct VexNode
{
char data; //頂點資訊
ArcNode * firstarc; //指向第一個表結點的指標
} VexNode, AdjList[MaxNum]; //AdjList表示鄰接表型別
typedef struct
{
AdjList vertices; //頭結點陣列
int vexnum, arcnum; //圖的當前頂點數和邊數
} ALGraph;
typedef struct
{
int *top;
int *base;
int stacksize;
} stack;
typedef struct
{
char *top;
char *base;
int nodesize;
} Node;
int main()
{
int i,num,a;
int choice;//選擇選單變數
ALGraph G;//定義鄰接表結構體G
stack p;//定義堆疊結構體p
do
{
printf(" \n 任務一 \n");
printf(" 1、無向圖創建鄰接表\n");
printf(" 2、存盤\n");
printf(" 3、讀盤\n");
printf(" 4、堆疊的初始化和入堆疊\n");
printf(" 5、出堆疊\n");
printf(" 6、銷毀堆疊\n");
printf(" 7、深度優先搜索遍歷無向圖\n");
printf(" 8、列印鄰接表\n");
printf("請輸入你的選擇\n");
scanf("%d",&choice);
system("cls");//清屏
fflush(stdin); //清除輸入緩沖區
switch (choice) //根據選擇,呼叫不同的函式來完成不同的任務
{
case 1:
CreatGraph(&G);
break;
case 2:
filewrite(G);
break;
case 3:
fileread(G);
break;
case 4:
if(InitStack(&p)==1)
{
printf("你想輸入多少個元素入堆疊:");
scanf("%d",&num);
printf("請輸入%d個元素(輸入一個元素后按回車鍵繼續輸入下一個):\n",num);
for(i=1; i<=num; i++)
{
scanf("%d",&a);
push(&p,a);
}
print(&p);
printf("\n堆疊頂元素:%d \n",getTop(&p,num));
}
break;
case 5:
printf("出堆疊后");
pop(&p,num);
print(&p);
break;
case 6:
destorystack(&p);
break;
case 8:
printGraph(G);
break;
default:
printf("無效的選擇!!!請重新輸入!!!\n");
break;
}
}
while (choice!=99);
return 0;
}
void CreatGraph(ALGraph *G)//創建鄰接表
{
int i,j,k;
char m,n;
ArcNode *s;
printf("輸入總頂點數和總邊數,輸入完成后回車(如:4 2)\n");
scanf("%d%d",&G->vexnum,&G->arcnum); //輸入總頂點數,總邊數
getchar(); //按下回車后每次只讀一個字符
printf("輸入各頂點的值,輸入完成后回車(如:abcd)\n");
for(i=0; i<G->vexnum; i++) //輸入各點,構造表頭節點表
{
scanf("%c", &G->vertices[i].data); //輸入頂點值
}
for(i=0; i<G->vexnum; i++)
{
G->vertices[i].firstarc = NULL; //初始化表頭節點的指標域為NULL
}
int length;
length=G->vexnum;
for(k=0; k<G->arcnum; k++) //輸入各邊,構造鄰接表,回圈次數=邊數
{
printf("輸入每條邊的兩個節點,輸入完成后回車繼續輸入(如:a b)\n");
scanf(" %c %c",&m,&n); //輸入一條邊的兩個節點m和n
s=(ArcNode*)malloc(sizeof(ArcNode)); // 生成一個新節點
s->adjvex=n;//n存放到表結點的頂點域
for(i=0; i<length; i++)//進入回圈,匹配頂點資訊和頭節點的資訊是否一致
{
if(m==G->vertices[i].data)//若一致則執行
{
s->nextarc=G->vertices[i].firstarc; //頭插法建立新節點
//下一個頭節點 //頭節點陣列i指向第一個表結點的指標
//每回圈一次指標s的下一個頭節點都是每組的第一個表結點
G->vertices[i].firstarc = s;//指標s賦值到頭節點陣列的第一個表結點
}
}
s=(ArcNode*)malloc(sizeof(ArcNode)); //生成另一個對稱的新的邊節點
s->adjvex=m;//m存放到表結點的頂點域
for(j=0; j<length; j++)//進入回圈,匹配頂點資訊和頭節點的資訊是否一致
{
if(n==G->vertices[j].data)//若一致則執行
{
s->nextarc=G->vertices[j].firstarc; //下一個頭節點 //頭節點陣列j指向第一個表結點的指標
G->vertices[j].firstarc = s;
}
}
}
}
void printGraph(ALGraph G)//列印鄰接表
{
int i;//回圈變數
ArcNode *p;
printf("鄰接表已創建!\n");
for(i=0; i<G.vexnum; i++)//回圈次數為頂點數
{
printf("%c:",G.vertices[i].data);//列印表頭結點
for(p=G.vertices[i].firstarc; p; p=p->nextarc)//指標p初值為每組鄰接表的第一個元素,指標p不斷向后面的延伸,只到指標p指向空
{
printf("%c",p->adjvex);//列印頂點域
}
printf("\n");//退出回圈后列印換行
}
}
int InitStack(stack *p)//初始化
{
p->base=(int *)malloc(sizeof(int)*STACKSIZE);
if(!p->base)
return 0;
p->top=p->base;
p->stacksize=STACKSIZE;
return 1;
}
int push(stack *p,int e)//入堆疊
{
if((p->top-p->base)>=p->stacksize)
{
p->base=realloc(p->base,(STACKSIZE+10)*sizeof(int));
if(!p->base)
exit(0);
p->top=p->base+p->stacksize;
p->stacksize=STACKSIZE+10;
}
*(p->top)++=e;
return 1;
}
int pop(stack *p,int e)//出堆疊
{
if(p->base==p->top)
exit(0);
e=*(--p->top);
return 1;
}
int getTop(stack *p,int e)//取堆疊頂元素
{
if(p->base==p->top)
exit(0);
e=*(p->top-1);
return e;
}
int destorystack(stack *p)//毀壞
{
free(p->base);
p->base=NULL;
p->top=NULL;
p->stacksize=0;
if(!p->base)
printf("堆疊被毀壞成功!!!\n");
return 1;
}
void print(stack *p)//列印堆疊中的元素
{
int *p1;
p1=p->top;
printf("堆疊內元素如下:\n");
if(p->base==p->top)
printf("空堆疊!!!\n");
while(p->base<p1)
{
printf("%d \n",*(p1-1));
p1--;
}
}
void filewrite(ALGraph G) //寫入檔案函式定義
{
ArcNode *p;//定義結構體的指標變數
int j=0;//回圈變數
char c;
FILE *fp;//定義檔案指標
printf("請選擇是否要存入已輸入的鄰接表資訊:'y'還是'n'???\n");
scanf("%c",&c);
fflush(stdin);
while(c!='y'&&c!='n')
{
if (c!='y'&&c!='n')//報錯指令
printf("輸入錯誤,請重新輸入\n");
printf("以下操作將會覆寫已存盤的資料,確定請輸入'y'或'n'???\n");
scanf("%c",&c);
fflush(stdin);
}
if (c=='y')
{
if((fp=fopen("c:lin.txt","w"))==NULL)//如果該路徑下檔案不存在則報錯
{
printf("檔案打開錯誤,程式無法進行\n");
exit(0);
}
for(j=0; j<G.vexnum; j++)
{
fwrite(&G.vertices[j].data,sizeof( struct VexNode),1,fp);//新建一個節點,寫入每組的頭節點資料
printf("%c:",G.vertices[j].data);//列印寫入的資訊
for(p=G.vertices[j].firstarc; p; p=p->nextarc)//指標p初值為每組鄰接表的第一個元素,指標p不斷向后面的延伸,只到指標p指向空
{
fwrite(&p->adjvex,sizeof( struct VexNode),1,fp);//寫入每組鄰接表中的頂點資訊
printf("%c",p->adjvex);//列印頂點資訊
}
printf("\n");//退出回圈后列印換行
}
fclose(fp);//關閉檔案指標
if(G.vexnum==0)//如果總頂點數為0
printf("沒有檔案,無法保存\n");
else
printf("資料存盤完畢\n");
system("pause");
}
else
return;
}
void fileread(ALGraph G) //讀取檔案資訊函式定義
{
ArcNode *p;//定義結構體的指標變數p
int j=0;//回圈變數
char c;
FILE *fp;//檔案指標
system("cls");//清屏
printf("請選擇是否要讀取已輸入的鄰接表資訊:'y'還是'n'???\n");
scanf("%c",&c);
fflush(stdin);
while(c!='y'&&c!='n')
{
if (c!='y'&&c!='n')
printf("輸入錯誤,請重新輸入\n");
printf("以下操作將會覆寫已存盤的資料,確定請輸入'y'或'n'???\n");
scanf("%c",&c);
fflush(stdin);
}
if (c=='y')
{
if((fp=fopen("c:lin.txt","r"))==NULL)//如果該路徑下檔案不存在
{
printf("檔案打開錯誤,程式無法進行\n");
exit(0);
}
while(fread(&G.vertices[j].data,sizeof( struct VexNode),1,fp))//當該檔案下的頭節點資料為可讀狀態時
{
printf("%c:",G.vertices[j].data);//列印頭節點資料
for(p=G.vertices[j].firstarc; p; p=p->nextarc)//回圈讀取并列印每組的頂點資訊
{
fread(&p->adjvex,sizeof(struct VexNode),1,fp);
printf("%c",p->adjvex);//列印頂點域
printf("\t\t p=%c\t\t",*p);
printf("G.vertices[%d]=%c",j,G.vertices[j]);
}
printf("\n");//退出回圈后列印換行
j++;
}
printf("%d",j);
fclose(fp);//關閉檔案指標
printf("資料讀取完畢!!!\n");
system("pause");
}
else
return;
}


創建好鄰接表好后,可以正常列印所讀取的資訊,關閉程式重新讀取就會報錯
uj5u.com熱心網友回復:
應該是讀寫檔案出錯了uj5u.com熱心網友回復:
方便具體說一下是哪個地方嗎,要怎么修改,俺是個大一的編程小白,謝謝喜喜!uj5u.com熱心網友回復:
推薦使用WinHex軟體查看硬碟或檔案或記憶體中的原始位元組內容。不要把
fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //讀時把\r\n替換成\n,寫時把\n替換成\r\n;讀到\x1a就設定EOF;讀寫的內容當字符看待
和
fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替換,遇到\x1a仍繼續讀;讀寫的內容當位元組看待
弄混了
uj5u.com熱心網友回復:
具體應該如何修改?轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/34199.html
標籤:新手樂園
上一篇:請大家再給我一天時間~
