前言?
數(shù)據(jù)結(jié)構(gòu)(初階)第一節(jié):數(shù)據(jù)結(jié)構(gòu)概論-CSDN博客
數(shù)據(jù)結(jié)構(gòu)(初階)第二節(jié):順序表-CSDN博客
????????本文將以C語(yǔ)言和順序表實(shí)現(xiàn)通訊錄基礎(chǔ)管理,實(shí)現(xiàn)功能包括增、刪、改、查等,在實(shí)現(xiàn)相關(guān)功能時(shí)需要用到在第二節(jié)中順序表的相關(guān)內(nèi)容,需要友友們掌握順序表的相關(guān)內(nèi)容以及函數(shù)的實(shí)現(xiàn)方式。
目錄
前言?
要用到的兩個(gè)文件
正文
文件包含關(guān)系
Contact.h
Contast.c
頭文件
菜單
初始化
銷毀
添加
判斷名字是否存在
刪除
顯示
修改
查找
測(cè)試文件test.c
要用到的兩個(gè)文件
SeqList.h
//.h文件定義 #include "Contact.h"http://頭文件互相包含會(huì)報(bào)錯(cuò) #include <malloc.h> #include <assert.h> #include <string.h> #include <stdio.h> typedef peoInfo SLDataType; //定義順序表 typedef struct SeqList { SLDataType* a;//數(shù)組 int size;//有效元素 int capacity;//容量 }SL; //初始化 void SLinit(SL* p1); //銷毀 void SLdestory(SL* p1); //擴(kuò)容 void SLcheckCapcity(SL* p1); //尾插 void SLpushBack(SL* p1, SLDataType x); //打印順序表 void SLprint(SL* p1); //頭插 void SLpushFront(SL* p1, SLDataType x); //尾刪 void SLpopBack(SL* p1); //頭刪 void SLpopFront(SL* p1); //指定插入 void SLinsert(SL* p1, int pos, SLDataType x); //指定刪除 void SLerase(SL* p1, int pos); //查詢 //int SLfind(SL* p1, SLDataType x);
SeqList.c
#include "SeqList.h" //初始化 void SLinit(SL* p1) { p1->a = (SLDataType*)malloc((sizeof(SLDataType)) * 4); if (p1->a == NULL) { perror("malloc fail"); return; } p1->capacity = 4; p1->size = 0; } //銷毀 void SLdestory(SL* p1) { free(p1->a); p1->a = NULL; p1->capacity = 0; p1->size = 0; } //擴(kuò)容 void SLcheckCapcity(SL* p1) { if (p1->size >= p1->capacity) { SLDataType* tmp = (SLDataType*)realloc(p1->a, sizeof(SLDataType) * p1->capacity * 2); if (tmp == NULL) { perror("realloc fail"); return; } p1->a = tmp; p1->capacity *= 2; } } //尾插 void SLpushBack(SL* p1, SLDataType x) { assert(p1); SLcheckCapcity(p1);//檢查是否需要擴(kuò)容 p1->a[(p1->size)++] = x;//在size處插入數(shù)據(jù) } //打印順序表 void SLprint(SL* p1) { for (int i = 0; i < p1->size; i++) { printf("%d\n", p1->a[i]); } } //頭插 void SLpushFront(SL* p1, SLDataType x) { assert(p1); SLcheckCapcity(p1); for (int i = p1->size; i > 0; i--) { p1->a[i] = p1->a[i - 1]; } p1->a[0] = x; p1->size++; } //尾刪 void SLpopBack(SL* p1) { assert(p1); assert(p1->size);//順序表不為空 //p1->a[p1->size - 1] = -1; p1->size--; } //頭刪 void SLpopFront(SL* p1) { assert(p1); assert(p1->size); for (int i = 1; i < p1->size; i++) { p1->a[i - 1] = p1->a[i]; } p1->size--; } //指定下標(biāo)添加 void SLinsert(SL* p1, int pos, SLDataType x) { //要注意p1->size指向的是最后一個(gè)有效數(shù)據(jù)的下一位 //pos是指定的插入位置的下標(biāo)(如果為0則是頭插,如果為ps->size-1則為尾插) //x是待插入的數(shù)據(jù) assert(p1 && pos >= 0 && pos < p1->size); SLcheckCapcity(p1); for (int i = p1->size; i > pos; i--) { p1->a[i] = p1->a[i - 1]; } p1->a[pos] = x; p1->size++; } //指定下標(biāo)刪除 void SLerase(SL* p1, int pos) { assert(p1 && pos >= 0 && pos < p1->size); for (int i = pos; i < p1->size - 1; i++) { p1->a[i] = p1->a[i + 1]; } p1->size--; } //查詢 //int SLfind(SL* p1, SLDataType x) //{ // assert(p1); // for (int i = 0; i < p1->size; i++) // { // if (p1->a[i] == x) // { // return i;//找到后返回下標(biāo) // } // } // return -1;//沒(méi)有找到返回-1 //}
正文
文件包含關(guān)系
在實(shí)現(xiàn)通訊錄的工程文件中一共包含了5個(gè)子文件,分別是
- test.c:用于在編寫(xiě)過(guò)程中測(cè)試代碼能否正常運(yùn)行
- SeqList.h:用于在實(shí)現(xiàn)順序表的過(guò)程中定義結(jié)構(gòu)體和各種方法
- SeqList.c:用于實(shí)現(xiàn)在頭文件中定義的方法
- Contact.h:定義通訊錄中實(shí)現(xiàn)功能的函數(shù)
- Contact.c:實(shí)現(xiàn)頭文件中定義的函數(shù)
? ? ? ? 通訊錄實(shí)質(zhì)上就是順序表,只不過(guò)是改了名字(換湯不換藥),我們只需要在實(shí)現(xiàn)順序表的基礎(chǔ)上給他起個(gè)別名通訊錄(Contact)即可。
????????在順序表中,數(shù)組中存儲(chǔ)的是單一的元素,在通訊錄中,原數(shù)組中的元素變成了存儲(chǔ)聯(lián)系人數(shù)據(jù)的結(jié)構(gòu)體(personInfo),數(shù)組中的每個(gè)元素都是結(jié)構(gòu)體類型,包括姓名、電話、性別、住址等,本質(zhì)上是兩個(gè)結(jié)構(gòu)體的嵌套。
在Contact.h中我們定義好聯(lián)系人結(jié)構(gòu)體和要用到的方法
#define NAME_MAX 20 #define GENDER_MAX 5 #define PHONE_MAX 20 #define ADDS_MAX 20 typedef struct personInfo { char name[NAME_MAX]; char gender[GENDER_MAX]; int age; char phoneNum[PHONE_MAX]; char adds[ADDS_MAX]; }peoInfo; //前置聲明 typedef struct SeqList Contact;//將順序表命名為"通訊錄" //菜單 void menu(); //初始化 void ContactInit(Contact* p); //銷毀 void ContactDestory(Contact* p); //添加 void ContactAdd(Contact* p); //刪除 void ContactDle(Contact* p); //修改 void ContactModify(Contact* p); //查找 void ContactFind(Contact* p); //顯示 void ContactShow(Contact* p);
? ? ? ??typedef struct SeqList Contact;在這一句代碼中使用前置聲明將Seqlist重命名為Contact,在該文件中我們并沒(méi)有定義結(jié)構(gòu)體SeqList,使用前置聲明只是為了讓編譯器知道有這個(gè)結(jié)構(gòu)體的存在,而無(wú)法直接對(duì)之前重命名過(guò)的SL(typedef struct SeqList SL;)再命名的原因是編譯器不能識(shí)別到SL的存在,如果想要識(shí)別必須包含"SeqList.h",但是頭文件相互包含會(huì)導(dǎo)致報(bào)錯(cuò),后面會(huì)講到。
????????在SeqList.h中將SLDateType自定義類型更改為perInfo,需要將"Contact.h"包含進(jìn)文件,不能將"SeqList.h"同時(shí)包含進(jìn)Contact.h中,這樣會(huì)導(dǎo)致程序報(bào)錯(cuò)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-853053.html
typedef peoInfo SLDataType; //定義順序表 typedef struct SeqList { SLDataType* a;//數(shù)組 int size;//有效元素 int capacity;//容量 }SL;
? ? ? ? 在Contact.h中對(duì)SeqList重命名,在SeqList.h中更改自定義數(shù)據(jù)類型,此時(shí)我們通過(guò)Contact*p和SL*p定義的兩種結(jié)構(gòu)體指針都會(huì)被程序正確識(shí)別,本質(zhì)上Contact*p等價(jià)于SL*p。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-853053.html
Contact.h
#define NAME_MAX 20
#define GENDER_MAX 5
#define PHONE_MAX 20
#define ADDS_MAX 20
typedef struct personInfo
{
char name[NAME_MAX];
char gender[GENDER_MAX];
int age;
char phoneNum[PHONE_MAX];
char adds[ADDS_MAX];
}peoInfo;
//前置聲明
typedef struct SeqList Contact;//將順序表命名為"通訊錄"
//菜單
void menu();
//初始化
void ContactInit(Contact* p);
//銷毀
void ContactDestory(Contact* p);
//添加
void ContactAdd(Contact* p);
//刪除
void ContactDle(Contact* p);
//修改
void ContactModify(Contact* p);
//查找
void ContactFind(Contact* p);
//顯示
void ContactShow(Contact* p);
Contast.c
頭文件
#include "Contact.h" #include "SeqList.h"
菜單
void menu() { printf("-----------------------\n"); printf(" 1.添加 \n"); printf(" 2.刪除 \n"); printf(" 3.查找 \n"); printf(" 4.顯示 \n"); printf(" 5.修改 \n"); printf(" 0.退出 \n"); printf("-----------------------\n"); }
初始化
//初始化 void ContactInit(Contact* p) { SLinit(p);//直接調(diào)用已經(jīng)在SeqList.c中實(shí)現(xiàn)好的初始化函數(shù)即可 }
銷毀
void ContactDestory(Contact* p) { SLdestory(p); }
添加
void ContactAdd(Contact* p) { peoInfo info;//聯(lián)系人結(jié)構(gòu)體變量 printf("請(qǐng)輸入聯(lián)系人的姓名:\n"); scanf("%s", info.name); printf("請(qǐng)輸入聯(lián)系人的性別:\n"); scanf("%s", info.gender); printf("請(qǐng)輸入聯(lián)系人的年齡:\n"); scanf("%d", &info.age); printf("請(qǐng)輸入聯(lián)系人的電話號(hào)碼:\n"); scanf("%s", info.phoneNum); printf("請(qǐng)輸入聯(lián)系人的住址:\n"); scanf("%s", info.adds); SLpushBack(p, info);//這里選擇尾插 printf("添加成功!\n\n"); }
判斷名字是否存在
int FindName(Contact* p, char* name) { for (int i = 0; i < p->size; i++) { if (strcmp(p->a[i].name, name) == 0) return i;//返回下標(biāo) } return -1; }
刪除
void ContactDle(Contact* p) { char n[NAME_MAX]; printf("請(qǐng)輸入要?jiǎng)h除的聯(lián)系人姓名:\n"); scanf("%s", n); int ret = FindName(p, n); if (ret < 0) { printf("刪除對(duì)象不存在!\n"); return; } SLerase(p, ret); printf("刪除成功!\n"); }
顯示
void ContactShow(Contact* p) { printf("%-15s%-15s%-15s%-15s%-15s\n", "姓名", "性別", "年齡", "電話", "地址"); for (int i = 0; i < p->size; i++) { printf("%-15s%-15s%-15d%-15s%-15s\n", p->a[i].name, p->a[i].gender, p->a[i].age, p->a[i].phoneNum, p->a[i].adds); } }
修改
void ContactModify(Contact* p) { char name[NAME_MAX]; printf("請(qǐng)輸入要修改的聯(lián)系人姓名:\n"); scanf("%s", name); int ret = FindName(p, name); if (ret < 0) { printf("修改對(duì)象不存在!\n"); return; } printf("請(qǐng)輸入新的姓名:\n"); scanf("%s", p->a[ret].name); printf("請(qǐng)輸入新的性別:\n"); scanf("%s", p->a[ret].gender); printf("請(qǐng)輸入新的年齡:\n"); scanf("%d", &p->a[ret].age); printf("請(qǐng)輸入新的電話:\n"); scanf("%s", p->a[ret].phoneNum); printf("請(qǐng)輸入新的地址:\n"); scanf("%s", p->a[ret].adds); printf("修改成功!\n\n"); }
查找
void ContactFind(Contact* p) { char name[NAME_MAX]; printf("請(qǐng)輸入要查找的聯(lián)系人姓名:\n"); scanf("%s", name); int ret = FindName(p, name); if (ret < 0) { printf("聯(lián)系人不存在!\n"); return; } printf("%-15s%-15s%-15s%-15s%-15s\n", "姓名", "性別", "年齡", "電話", "地址"); printf("%-15s%-15s%-15d%-15s%-15s\n", p->a[ret].name, p->a[ret].gender, p->a[ret].age, p->a[ret].phoneNum, p->a[ret].adds); printf("查詢成功!\n\n"); }
測(cè)試文件test.c
#include "SeqList.h"
int main()
{
Contact con;
ContactInit(&con);
while (1)
{
menu();
int i = 0;
printf("請(qǐng)選擇你的操作:");
scanf("%d", &i);
switch (i)
{
case 1:
ContactAdd(&con);
break;
case 2:
ContactDle(&con);
break;
case 3:
ContactFind(&con);
break;
case 4:
ContactShow(&con);
break;
case 5:
ContactModify(&con);
break;
case 0:
printf("程序已退出!\n");
break;
}
}
return 0;
}
到了這里,關(guān)于數(shù)據(jù)結(jié)構(gòu)(初階):順序表實(shí)戰(zhàn)通訊錄的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!