数据结构—单链表实现通讯录

通过以上3节内容,让我们来实现一下用单链表的方式来实现通讯录

以下是我的代码

仅供大家参考!

1.SList.h

//SList.h
#include "Contact.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

typedef struct personInfo SLTDataType;
typedef struct SListNode
{
    struct  personInfo a;
    struct SListNode* next;
}SLTNode;

void SLTPrint(SLTNode* phead);

//尾插
void SLPushBack(SLTNode** pphead, SLTDataType x);

// 单链表查找
SLTNode* STFind(SLTNode* phead, SLTDataType x);


// 删除pos位置的值
void SLErase(SLTNode** pphead, SLTNode* pos);

//单链表销毁
void SListDesTroy(SLTNode** pphead);

2. SList.c

#include "SList.h"

//void SLTPrint(SLTNode* phead)
//{
//    SLTNode* cur=phead;
//    while(cur!=NULL)
//    {
//        printf("%d->",cur->a);
//        cur=cur->next;
//    }
//    printf("NULL\n");
//
//}

//创建一个新的动态内存
SLTNode* BuyLTNode(SLTDataType x)
{
    SLTNode * newnode=(SLTNode*)malloc(sizeof(SLTNode));
    if(newnode==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    newnode->a=x;
    newnode->next=NULL;//初始化

    return newnode;
}

//尾插
//第一个尾插需要二级指针,接下来就不用二级指针
//第一次是改变结构的指针plist
//第二次是改变结构体尾结点
void SLPushBack(SLTNode** pphead, SLTDataType x)
{
    assert(pphead);
    SLTNode *newnode= BuyLTNode(x);
    //是否为空链表
    if(*pphead==NULL) {
        *pphead = newnode;//改变结构的指针plist
        return;
    }
    else
    {
        SLTNode *tail=*pphead;
        while(tail->next!=NULL)//找到链表最后一位,当tail->为空时,就把新开辟的链表节点接上去
            tail=tail->next;
        tail->next=newnode;//改变结构体尾结点
        //就是把newnode存放的新结点地址给tail->next,然后在存放在之前最后一个结点的struct SListNode* next;中,这样next指向的地址不是NULL,而是新加的结点的位置
        //不能用tail=newnode,因为tail和newnode是局部变量,当这函数结束后就释放了
    }
}

//头删
void SLPopFront(SLTNode** pphead)
{
    //空链表
    assert(*pphead);

//    //一个结点
//    if((*pphead)->next==NULL)
//    {
//        free(*pphead);
//        *pphead=NULL;
//    }
//    //多个结点
//    else
//    {
//        SLTNode *del=*pphead;
//        //*pphead=del->nest;
//        *pphead=(*pphead)->next;
//        free(del);
//    }

    SLTNode* del = *pphead;
    *pphead = (*pphead)->next;
    free(del);

}

// 删除pos位置的值
void SLErase(SLTNode** pphead, SLTNode* pos)
{
    assert(pphead);
    assert(pos);

    //如果只有一个结点
    if(pos==*pphead)
        SLPopFront(pphead);
    else
    {
        SLTNode *p1=*pphead;
        while(p1->next!=pos)
            p1=p1->next;
        p1->next=pos->next;
        free(pos);
    }
}

//单链表销毁
void SListDesTroy(SLTNode** pphead)
{
    assert(pphead && *pphead );

    SLTNode *pcur=*pphead;
    while(pcur)
    {
        SLTNode *next=pcur->next;
        free(pcur);
        pcur=next;
    }
    *pphead=NULL;

}

3. Contact.h

#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 100

//定义联系人数据 结构
//姓名 性别 年龄 电话 地址
typedef struct personInfo
{
    char name[NAME_MAX];
    char gender[GENDER_MAX];
    int age;
    char tel[TEL_MAX];
    char addr[ADDR_MAX];
}PeoInfo;

//要用到顺序表相关的方法,对通讯录的操作实际就是对链表进行操作
//给链表改个名字,叫做通讯录
typedef struct SListNode contact;

//初始化通讯录
void InitContact(contact** con);
//添加通讯录数据
void AddContact(contact** con);
//删除通讯录数据
void DelContact(contact** con);
//展⽰通讯录数据
void ShowContact(contact* con);
//查找通讯录数据
void FindContact(contact* con);
//修改通讯录数据
void ModifyContact(contact* con);
//销毁通讯录数据
void DestroyContact(contact** con);

4.Contact.c

#include "Contact.h"
#include "SList.h"
#include <string.h>

void AddContact(contact** con) {
    SLTDataType info;
    printf("请输⼊姓名:\n");
    scanf("%s", &info.name);
    printf("请输⼊性别:\n");
    scanf("%s", &info.gender);
    printf("请输⼊年龄:\n");
    scanf("%d", &info.age);
    printf("请输⼊联系电话:\n");
    scanf("%s", &info.tel);
    printf("请输⼊地址:\n");
    scanf("%s", &info.addr);
    SLPushBack(con, info);
    printf("插⼊成功!\n");
}
contact* FindByName(contact* con, char name[]) {
    contact* cur = con;
    while (cur)
    {
        if (strcmp(cur->a.name, name) == 0) {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}
void DelContact(contact** con) {
    char name[NAME_MAX];
    printf("请输⼊要删除的⽤⼾姓名:\n");
    scanf("%s", name);
    contact* pos = FindByName(*con, name);
    if (pos == NULL) {
        printf("要删除的⽤⼾不存在,删除失败!\n");
        return;
    }
    SLErase(con, pos);
    printf("删除成功!\n");
}
void ShowContact(contact* con) {
    printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "联系电话","地址");
           contact* cur = con;
    while (cur)
    {
        printf("%s %s  %d %s %s\n",
               cur->a.name,
               cur->a.gender,
               cur->a.age,
               cur->a.tel,
               cur->a.addr);
        cur = cur->next;
    }
}
void FindContact(contact* con) {
    char name[NAME_MAX];
    printf("请输⼊要查找的⽤⼾姓名:\n");
    scanf("%s", name);
    contact* pos = FindByName(con, name);
    if (pos == NULL) {
        printf("要查找的⽤⼾不存在,查找失败!\n");
        return;
    }
    printf("查找成功!\n");
    printf("%-10s %-4s %-4d %15s %-20s\n",
           pos->a.name,
           pos->a.gender,
           pos->a.age,
           pos->a.tel,
           pos->a.addr);
}
void ModifyContact(contact* con) {
    char name[NAME_MAX];
    printf("请输⼊要修改的⽤⼾名称:\n");
    scanf("%s", name);
    contact* pos = FindByName(con, name);
    if (pos == NULL) {
        printf("要查找的⽤⼾不存在,修改失败!\n");
        return;
    }
    printf("请输⼊要修改的姓名:\n");
    scanf("%s", pos->a.name);
    printf("请输⼊要修改的性别:\n");
    scanf("%s", pos->a.gender);
    printf("请输⼊要修改的年龄:\n");
    scanf("%d", &pos->a.age);
    printf("请输⼊要修改的联系电话:\n");
    scanf("%s", pos->a.tel);
    printf("请输⼊要修改的地址:\n");
    scanf("%s", pos->a.addr);
    printf("修改成功!\n");
}

void DestroyContact(contact** con) {
    SListDesTroy(con);
}

5. Text.c

#include "SList.h"

void menu()
{
    printf("**************通讯录*****************\n");
    printf("******1.增加联系人  2.删除联系人******\n");
    printf("******3.修改联系人  4.查找联系人******\n");
    printf("******5.展示联系人  0.   退出  ******\n");
    printf("************************************\n");
}

int main()
{
    int select=0;
    contact *con=NULL;


    do{
        menu();
        printf("请选择您的操作:\n");
        scanf("%d",&select);

        switch (select) {
            case 1:
                AddContact(&con);
                break;
            case 2:
                DelContact(&con);
                break;
            case 3:
                ModifyContact(con);
                break;
            case 4:
                FindContact(con);
                break;
            case 5:
                ShowContact(con);
                break;
            case 0:
                printf("退出通讯录\n");
                break;
            default:
                printf("输入错误,请重新选择您的操作!\n");
                break;

        }

    }while(select!=0);

    DestroyContact(&con);
    return 0;
}

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 好的,下面是一个简单的单链表通讯录数据结构: ``` struct Contact { char name[50]; char phone[20]; char email[50]; struct Contact* next; }; typedef struct Contact* ContactPtr; ``` 上面的结构体定义了一个通讯录中联系人的信息,包括姓名、电话和电子邮件地址。每个联系人都有一个指向下一个联系人的指针。使用这个结构体,我们可以定义一个单链表通讯录。 下面是一个简单的实现示例,包括添加联系人、查找联系人和删除联系人等基本操作: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> struct Contact { char name[50]; char phone[20]; char email[50]; struct Contact* next; }; typedef struct Contact* ContactPtr; // 初始化通讯录 ContactPtr initContact() { ContactPtr head = (ContactPtr)malloc(sizeof(struct Contact)); head->next = NULL; return head; } // 添加联系人 void addContact(ContactPtr head, char name[], char phone[], char email[]) { ContactPtr newContact = (ContactPtr)malloc(sizeof(struct Contact)); strcpy(newContact->name, name); strcpy(newContact->phone, phone); strcpy(newContact->email, email); newContact->next = NULL; ContactPtr current = head; while (current->next != NULL) { current = current->next; } current->next = newContact; printf("联系人 %s 添加成功!\n", name); } // 查找联系人 void findContact(ContactPtr head, char name[]) { ContactPtr current = head->next; while (current != NULL) { if (strcmp(current->name, name) == 0) { printf("%s 的电话号码是:%s,电子邮件地址是:%s\n", current->name, current->phone, current->email); return; } current = current->next; } printf("未找到联系人 %s!\n", name); } // 删除联系人 void deleteContact(ContactPtr head, char name[]) { ContactPtr current = head; while (current->next != NULL) { if (strcmp(current->next->name, name) == 0) { ContactPtr temp = current->next; current->next = temp->next; free(temp); printf("联系人 %s 删除成功!\n", name); return; } current = current->next; } printf("未找到联系人 %s!\n", name); } // 打印所有联系人 void printContacts(ContactPtr head) { if (head->next == NULL) { printf("通讯录为空!\n"); return; } ContactPtr current = head->next; while (current != NULL) { printf("%s 的电话号码是:%s,电子邮件地址是:%s\n", current->name, current->phone, current->email); current = current->next; } } int main() { ContactPtr head = initContact(); addContact(head, "张三", "123456789", "[email protected]"); addContact(head, "李四", "987654321", "[email protected]"); addContact(head, "王五", "234567890", "[email protected]"); printContacts(head); findContact(head, "张三"); findContact(head, "赵六"); deleteContact(head, "李四"); printContacts(head); return 0; } ``` 上面的代码实现了一个简单的单链表通讯录,包括添加联系人、查找联系人和删除联系人等基本操作。 ### 回答2: 单链表通讯录是一种基于数据结构通讯录实现方式。通讯录中的每个联系人都被封装为一个节点,节点内包含联系人的信息和一个指向下一个节点的指针。该链表的头节点指向第一个联系人,最后一个联系人的节点指针为空。 单链表通讯录的优点是插入和删除联系人的操作高效。当需要插入一个新的联系人时,只需要修改指针的指向即可,无需移动其他节点。同样,删除联系人时也只需修改指针指向,不需要进行大量的数据迁移。这样可以大大提高操作的效率。 然而,单链表通讯录的缺点是查找联系人的效率相对较低。由于只能按顺序查找,当查找的联系人位于链表的末尾时,需要遍历整个链表寻找,时间复杂度较高。为了解决这个问题,可以使用更高效的数据结构,如哈希表来实现通讯录。 除了基本的插入、删除和查找操作,单链表通讯录还可以进行其他一些常见的操作,如修改联系人信息、排序联系人。修改联系人信息时,可以根据给定的姓名或其他关键字,遍历链表找到指定联系人并修改其信息。排序联系人时,可以使用冒泡排序等算法进行排序,将链表中的联系人按照一定的规则排序。 总的来说,单链表通讯录是一种简单而高效的通讯录实现方式。它具有插入、删除操作高效的优点,但查找效率相对较低。可以根据实际需求选择合适的数据结构实现通讯录。 ### 回答3: 单链表通讯录是一种常见的数据结构,用于存储和管理联系人信息。通讯录中的每个联系人被表示为一个节点,节点包含姓名、电话号码等信息,并且有一个指向下一个节点的指针。 单链表通讯录的优点是插入、删除和查找操作都很高效。在插入操作时,只需将新的联系人节点插入到链表中,并更新相应的指针,即可完成插入操作。在删除操作时,只需修改相应节点的指针,即可将该联系人节点从链表中删除。在查找操作时,只需从头节点开始,依次遍历每个节点,直到找到目标联系人节点为止。 另一个优点是单链表通讯录能够动态地存储联系人信息。链表的长度可以根据需要进行动态调整,不需要预先分配固定的内存空间。这使得单链表通讯录更加灵活和节省内存空间。 然而,单链表通讯录也有一些缺点。首先,查询某个特定联系人节点的效率较低,需要遍历整个链表,尤其在链表较长时,效率较低。其次,在内存分配上可能存在空间浪费的问题,因为每个节点的指针需要占用额外的内存空间。 综上所述,单链表通讯录是一种高效、灵活的数据结构,适合用于存储和管理通讯录信息。但在应用中需要根据具体需求权衡其优缺点,选择合适的数据结构实现通讯录功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值