資料結構之單鏈表
從今天起開始資料結構系列的分享,今天分享的是單鏈表。單鏈表大概是大概是每個資料結構 初學者的必經之路,下面結合一個小小的工程深入學習單鏈表的使用–簡易客戶管理系統。 ps:如果還不清楚單鏈表是什麼的小夥伴自行百度,在此不在贅述
專案結構
如圖所示 大致瞭解了專案架構後,下面開始從零編寫程式碼 注:增、刪、改這三個部分同時包含了將變動後的資訊寫入到檔案中的操作
程式碼編寫
專案基礎程式碼
俗話說得好,“萬丈高樓平地起”,先來編寫專案的預定義程式碼部分,主要是標頭檔案 包含、結構體定義、全域性變數定義等
標頭檔案包含
#include<stdio.h> //C程式基礎庫
#include<stdlib.h> //包含函式exit()
#include<string.h> //包含函式strcmp()
結構體定義
typedef struct item{ char name[20]; //儲存客戶姓名 char gender[20]; //儲存客戶性別 int age; //儲存客戶年齡 char tel[20]; //儲存客戶號碼 } guest;
結構體定義不要多說了哈,這裡typedef...guest
是給結構體item起別名的意思,也就是
struct item
guest
typedef struct node { guest data; //資料域 struct node * next; //指標域 }* link;
這裡是給指向結構體node的指標起別名
全域性變數定義
link T;//頭指標
這個頭指標T是整個系統的索引,六個模組共有一個,雖然有儘量少定義全域性變數的原則,但這裡
的全域性變數T可以避免各個函式間複雜的引數傳遞問題,犧牲了空間,換取了執行時間的減少;
同時要注意我在後面對T的初始化程式碼
//初始化頭指標 T=(link)malloc(sizeof(struct node)); T->next = NULL;
這裡並沒有給T安排資料域,T不是第一個儲存客戶資訊的節點指標,T->next才是,初始化頭指標
時還沒有儲存客戶資訊的結點加入,所以T->next=NULL;
,這是一個程式設計者應該養成的好習慣;為
什麼不給T安排資料域呢,這裡主要考慮到後面的刪除模組的編寫,我們知道,刪除一個結點,要先
找到這個結點的前驅指標p和後驅指標q,然後p->next = q->next;
,如果給T安排資料域的話,
T的前驅是什麼呢?就算不用上面我說的那套刪除邏輯,用if...else...
語句和另外一套邏輯
完成對T的刪除,程式碼明顯複雜些。
專案核心程式碼
一、載入檔案
程式碼如下
void init() { link p,s; FILE *fp; int i = 0; s = p=(link)malloc(sizeof(struct node)); p->next = NULL; if((fp=fopen("1.txt","r"))==NULL) { printf("load error!"); exit(1); } while(!feof(fp)) { fscanf(fp,"%s\t%s\t%d\t%s\t\n",p->data.name,p->data.gender,&p->data.age,p->data.tel); i++; if(i!=1) { s->next = p; s=p; } else{ T->next = p; } p=(link)malloc(sizeof(struct node)); p->next = NULL; } printf("總人數i=====%d\n",i); if(fclose(fp)) { printf("Can't close the file!\n"); exit(1); } }
介紹下程式碼邏輯,新開闢記憶體空間,並使s、p指向它,開啟檔案,如果檔案指標沒有到檔案尾,將 從檔案讀取到的一個客戶資訊賦給p的資料域,如果是讀取第一個客戶資訊,將p指向的結點連在頭 指標T後面,否則,將p連在s後面,因為這個時候s是p的前驅指標,連線成功後將p賦值給s,p又 指向一個新開闢的結點… 圖示:
二、增加客戶
程式碼如下:
//新增 void create() { link p,s; FILE *fp; int yn; s=T; while(s->next!=NULL) { s=s->next; } do { p=(link)malloc(sizeof(struct node)); printf("請輸入客戶姓名:\n"); scanf("%s",p->data.name); printf("請輸入客戶性別:\n"); scanf("%s",p->data.gender); printf("請輸入客戶年齡:\n"); scanf("%d",&p->data.age); printf("請輸入客戶聯絡方式:\n"); scanf("%s",p->data.tel); p->next=NULL; s->next=p; s=p; if((fp=fopen("1.txt","at"))==NULL) { printf("write error!\n"); exit(0); } printf("寫了一次\n"); fprintf(fp,"%s\t%s\t%d\t%s\n",p->data.name,p->data.gender,p->data.age,p->data.tel); if(fclose(fp)) { printf("can't close the file!\n"); exit(0); } printf("新增成功!\n"); printf("是否繼續新增請輸入0或1:"); scanf("%d",&yn); } while(yn); }
程式碼邏輯很簡單,新增結點,並連在尾節點後面,同時寫入檔案,如果前一片程式碼看懂了,這不是什麼 大問題…
三、刪除客戶
程式碼如下
//刪除 int del() { link p,q; FILE *fp; char mod[25]; printf("請輸入需要刪除的客戶名稱:\n"); scanf("%s",mod); p=T; while(p->next!=NULL&&strcmp(p->next->data.name,mod)!=0) p=p->next; if(p->next==NULL) { printf("並無此人!\n"); return 0; } q = p; p = p->next; q->next = p->next; delete(p); printf("刪除成功!\n"); if((fp=fopen("1.txt","wt"))==NULL) { printf("error!\n"); exit(0); } p=T->next; while(p!=NULL) { printf("%s",p->data.name); fprintf(fp,"%s\t%s\t%d\t%s\t\n",p->data.name,p->data.gender,p->data.age,p->data.tel); p = p->next; } if(fclose(fp)) { printf("can't close the file!\n"); exit(1); } }
模組三、四、五、六道理類似,不再贅述 附上程式碼地址: github 歡迎star 如有疑問,歡迎進群討論: