用链表和指针编写通讯录v1.0

/* 知识点总结:
指针部分:
    1、定义使用一个指针:
        ①声明   char * p;
        ②申请内存  p = (char *)malloc(sizeof(char)*n);malloc申请下来的内存空间用来存放*p的值;
        ③给指针p赋值  p = NULL;
        ④free(p)
    2、无法把指针变量本身传递给一个函数。解决方法:①用return②用二级指针
链表部分:
    1、生成
    LinkList L;
    L = (LinkList)malloc(sizeof(Node));
    L->next = NULL;
    注意:这里的参数是&L而非L。这样传递过去的是L的地址,在函数内部,用钥匙(“*”)来开锁:*(&L),其值就是L,
    所以malloc分配的内存地址是真正的赋值给了L本身
    2、插入
        ①头插
        p = (LinkList)malloc(sizeof(Node));  //生成新节点
        p->next = (*L)->next;
        (*L)->next = p;                      //插入到表头
        ②尾插
        r = *L;
        p = (LinkList)malloc(sizeof(Node));
        r->next  = p;
        r = p;
        r->next = NULL;
注意:L与r的关系,L是指整个单链表,而r是指向尾结点的指针变量,r会随着循环不断地变化节点,而L则是随着循环增长为多一个节点的链表
    3、删除
     q = p->next;
     p->next = q->next;
     free(q);
    4、遍历
     while(p && (strcmp(name_t,p->data.name) != 0))  //遍历链表来寻找name_t
    {
        p = p->next;
    }
*/



#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define OK 1
#define ERROR 0

struct PersonInfo
{
    char name[20];
    char phone[12];
};
typedef struct PersonInfo ElemType;

struct Node
{
    ElemType data;
    struct Node * next;
};
typedef struct Node * LinkList;


int GetElem(LinkList L,char name_t[]);
int ListInsert(LinkList * L,char * name_t,char * phone_t);
int ListDelete(LinkList * L,char * name_t);
void ShowList(LinkList L);
int ClearList(LinkList * L);

int main()
{
    int n;
    bool bHomeFlag = false;
    char *name_t = NULL;
    name_t = (char *)malloc(sizeof(char)*20);

    char *phone_t = NULL;
    phone_t = (char *)malloc(sizeof(char)*12);

    LinkList L;
    L = (LinkList)malloc(sizeof(Node));
    L->next = NULL;
    /*注意:这里的参数是&L而非L。这样传递过去的是L的地址,在函数内部,用钥匙(“*”)来开锁:*(&L),其值就是L,
    所以malloc分配的内存地址是真正的赋值给了L本身*/

    while(1)
    {
        printf("\n***************************************\n\
           ***1***: 寻找联系人\n\
           ***2***: 添加联系人\n\
           ***3***: 删除联系人\n\
           ***4***:显示所有联系人\n\
           ***5***: 格式化联系人\n\
           ***6***: 退出\n\
           请输入您要进行的操作序号:\
           \n***************************************\n");
        scanf("%d",&n);
        switch(n)
        {
            case 1:
            {
                printf("请输入您要查找的联系人姓名:");
                scanf("%s",name_t);
                GetElem(L,name_t);
                break;
            }
            case 2:
            {
                printf("请输入您要添加的联系人姓名:");
                scanf("%s",name_t);
                getchar();
                printf("请输入您要添加的联系人电话:");
                scanf("%s",phone_t);
                ListInsert(&L,name_t,phone_t);
                break;
            }
            case 3:
            {
                printf("请输入您要删除的联系人姓名:");
                scanf("%s",name_t);
                ListDelete(&L,name_t);
                break;
            }
            case 4:
            {
                ShowList(L);
                break;
            }
            case 5:
            {
                ClearList(&L);
                break;
            }
            case 6:
            {
                bHomeFlag = 1;
                break;
            }
            default:
                break;
        }
        if(bHomeFlag)
            break;
    }

    free(name_t);
    free(phone_t);
    free(L);

    return 0;
}


/* 遍历查找name_t联系人的信息并输出*/
int GetElem(LinkList L,char * name_t)
{
    LinkList p;
    p = L->next;
    while(p && (strcmp(name_t,p->data.name) != 0))  //遍历链表来寻找name_t
    {
        p = p->next;
    }
    if(!p)
    {
       printf("通讯录中查无此人\n");
       return ERROR;
    }

    printf("姓名:%s    手机号:%s\n",p->data.name,p->data.phone);

    return OK;
}


/*单个元素的插入,在L中第i个位置之前插入新的数据元素e*/
int ListInsert(LinkList * L,char * name_t,char * phone_t)
{
    LinkList p,s;
    p = * L;
    while((p->next) && (strcmp(name_t,p->next->data.name) != 1))  //遍历链表来寻找name_t应该插入的位置,按姓名字母顺序排列
    {
        p = p->next;
    }

    s = (LinkList)malloc(sizeof(Node));
    strcpy(s->data.name,name_t);
    strcpy(s->data.phone,phone_t);

    /*插入核心代码*/
    /*尾插法*/
    s->next = p->next;
    p->next = s;

    return OK;
}

/*删除单个元素:删除L中姓名为name_t数据元素,并输出name_t的信息已删除*/
int ListDelete(LinkList * L,char * name_t)
{
    char flag;
    LinkList p,q;
    p = *L;
    while(p->next && (strcmp(name_t,p->next->data.name) != 0))
    {
        p = p->next;
    }
    if(!(p->next))
    {
        printf("通讯录中查无此人!\n");
        return ERROR;
    }
    printf("是否确认删除%s?y/n\n",name_t);
    getchar();
    scanf("%c",&flag);
    if('y' == flag)
    {
        /*delete 的核心代码*/
        q = p->next;
        p->next = q->next;
        free(q);
        printf("%s已经被删除\n",name_t);
    }

    return OK;
}

/*显示所有联系人:遍历链表,然后输出每个节点的data*/
void ShowList(LinkList L)
{
   LinkList p;
   p = L;
   if(NULL == p->next)
   {
       printf("联系人为空!\n");
   }
   else
   {
       while(p->next)
       {
           p = p->next;
           printf("姓名:%s    手机号:%s\n",p->data.name,p->data.phone);
       }
   }
}

/*格式化:链表的整表删除*/
int ClearList(LinkList * L)
{
    LinkList p,q;
    p = (*L)->next;
    while(p)
    {
        q = p->next;
        free(p);
        p = q;
    }
    (*L)->next = NULL;
    return OK;
}



/*头插法创建链表*/
/*
void CreateLinkHead(LinkList * L,int n)
{
    LinkList p;                              //建立一个节点用于存储要往链表里插入的中间者
    int i;
    srand(time(0));                          //初始化随机数种子
    *L = (LinkList)malloc(sizeof(Node));
    (*L)->next = NULL;                       //先建立一个带头节点的单链表
    for(i=0; i<n; i++)
    {
        p = (LinkList)malloc(sizeof(Node));  //生成新节点
        p->data = rand()%100+1;
        p->next = (*L)->next;
        (*L)->next = p;                      //插入到表头
    }
}
*/

/*尾插法创建链表*/
/*
void CreateLinkTail(LinkList * L,int n)
{
    LinkList p,r;
    int i;
    srand(time(0));
    *L = (LinkList)malloc(sizeof(Node));
    r = *L;
    for(i=0; i<n; i++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = rand()%100 + 1;
        r->next  = p;
        r = p;
    }
    r->next = NULL;
}
*/
/*注意:L与r的关系,L是指整个单链表,而r是指向尾结点的指针变量,r会随着循环不断地变化节点,而L则是随着循环增长为多一个节点的链表*/

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值