//带表头结点的链表
//链表实现通讯录,具备查询、删除、修改、添加、显示、排序等功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAL_OK 1
#define MAL_ERR 0
struct node
{
char name[20];
int num;
struct node * next;
};
typedef struct node Node;
typedef struct node * Link;
void creat_link(Link * head);
void creat_node(Link * new_node, int i);
int judge_node(Link new_node);
void insert_node_head(Link new_node, Link head);
void insert_node_tail(Link new_node, Link head);
void insert_node_mid(Link new_node, Link head, int num_loc);
void delete_node(Link head, int num_del);
void display(Link head);
void release_link(Link * head);
void makempty_link(Link * head);
void address_initial(Link * head, Link new_node); //初始化通讯录
void address_inquire(Link head); //查询联系人
void address_delete(Link head); //删除联系人
void address_modify(Link head); //修改联系人
void address_add(Link head); //添加联系人
void user_interface(Link head);
int namecmp(char * p,char * q);
void address_sort(Link head); //联系人排序
void swap(Link p, Link min);
int main()
{
Link head = NULL;
Link new_node = NULL;
char n;
address_initial(&head,new_node);
while(1)
{
user_interface(head);
printf("请输入操作代号\n");
scanf("%c",&n);
getchar();
if (n == 'G')
break;
switch(n)
{
case 'A': address_inquire(head);break;
case 'B': address_delete(head);break;
case 'C': address_modify(head);break;
case 'D': address_add(head);break;
case 'E': display(head);break;
case 'F': address_sort(head);break;
default :printf("error\n");
}
printf("\n\n\n\n\n\n");
}
release_link(&head);
printf("链表通讯录关闭\n");
display(head);
return 0;
}
void user_interface(Link head)
{
printf("**********************************************Adress System************************************************\n");
printf("*** A.查询联系人 B.删除联系人 C.修改联系人 D.添加联系人 E.显示所有联系人 F.通讯录排序 G.退出 ***\n");
printf("*** ***\n");
printf("***********************************************************************************************************\n");
}
void address_initial(Link * head, Link new_node)
{
int i;
creat_link(head); //创建链表,此处为带表头结点的空链表
for (i = 0;i < 5;i++)
{
creat_node(&new_node,i);
insert_node_tail(new_node,*head);
}
}
void address_inquire(Link head)
{
printf("------------------------------------------------------------\n");
char * s, a;
s = (char *)malloc(20*sizeof(char)); //给字符型指针赋初值
Link p = head->next;
printf("是否记得其全名?A.是 B.否\n");
scanf("%c",&a);
getchar();
if (a == 'A')
{
printf("请输入待查询人全名(中间以空格分开):\n");
gets(s);
//getchar(); //清空键盘输入缓存
while (strcmp(p->name,s) != 0 && (p->next != NULL))
p = p->next;
if (p->next == NULL && strcmp(p->name,s) != 0)
printf("查无此人\n");
else
{
printf("该联系人的信息如下:\n");
printf("姓名:%s\n",p->name);
printf("电话号码:%d\n",p->num);
}
}
else
{
printf("请输入待查询人的名或姓\n");
scanf("%s",s);
getchar();
while (namecmp(p->name,s) != 0 && (p->next != NULL))
p = p->next;
if (p->next == NULL && namecmp(p->name,s) != 0)
printf("查无此人\n");
else
{
printf("该联系人的信息如下:\n");
printf("姓名:%s\n",p->name);
printf("电话号码:%d\n",p->num);
}
}
printf("------------------------------------------------------------\n");
}
void address_delete(Link head)
{
printf("------------------------------------------------------------\n");
char * s, a;
s = (char *)malloc(10*sizeof(char));
Link p, q;
p = head->next;
q = head;
printf("是否记得其全名?A.是 B.否\n");
scanf("%c",&a);
getchar();
if (a == 'A')
{
printf("请输入待删除人的全名(中间以空格分开):\n");
gets(s);
while (strcmp(p->name,s) != 0 && (p->next != NULL))
{
q = p;
p = p->next;
}
if (p->next == NULL && strcmp(p->name,s) != 0)
printf("查无此人\n");
else
{
q->next = p->next;
free(p);
printf("修改后的通讯录如下:\n");
display(head);
}
}
else
{
printf("请输入待删除人的名或姓\n");
scanf("%s",s);
getchar();
while (namecmp(p->name,s) != 0 && (p->next != NULL))
{
q = p;
p = p->next;
}
if (p->next == NULL && namecmp(p->name,s) != 0)
printf("查无此人\n");
else
{
q->next = p->next;
free(p);
printf("修改后的通讯录如下:\n");
display(head);
}
}
printf("------------------------------------------------------------\n");
}
void address_modify(Link head)
{
printf("------------------------------------------------------------\n");
long int i;
char * s, a;
s = (char *)malloc(10*sizeof(char));
Link p, q;
p = q = head->next;
printf("是否记得其全名?A.是 B.否\n");
scanf("%c",&a);
getchar();
if (a == 'A')
{
printf("请输入待修改人的名字(中间以空格分开):\n");
gets(s);
while (strcmp(p->name,s) != 0 && (p->next != NULL))
{
q = p;
p = p->next;
}
if (p->next == NULL && strcmp(p->name,s) != 0)
printf("查无此人!\n");
else
{
printf("输入修改后的号码:\n");
scanf("%d",&i);
getchar();
p->num = i;
printf("修改后的通讯录如下:\n");
display(head);
}
}
else
{
printf("请输入待删除人的名或姓\n");
scanf("%s",s);
getchar();
while (namecmp(p->name,s) != 0 && (p->next != NULL))
{
q = p;
p = p->next;
}
if (p->next == NULL && namecmp(p->name,s) != 0)
printf("查无此人\n");
else
{
printf("输入修改后的号码:\n");
scanf("%d",&i);
getchar();
p->num = i;
printf("修改后的通讯录如下:\n");
display(head);
}
}
printf("------------------------------------------------------------\n");
}
void address_add(Link head)
{
printf("------------------------------------------------------------\n");
Link new_node;
int i;
char * s;
s = (char *)malloc(10*sizeof(char));
printf("输入待添加联系人的名字(注意:姓和名之间用空格隔开):\n");
gets(s);
printf("输入待联系人的电话号码:\n");
scanf("%d",&i);
getchar();
new_node = (Link)malloc(sizeof(Node));
new_node->num = i;
strcpy(new_node->name, s);
insert_node_tail(new_node, head);
printf("添加后的通讯录如下:\n");
display(head);
printf("------------------------------------------------------------\n");
}
void address_sort(Link head)
{
Link p = head->next;
Link min = p;
Link q = head->next;
while(p->next)
{
q = p->next;
min = p;
while(q)
{
if(strcmp(q->name,min->name) < 0)
{
min = q;
}
q = q->next;
}
swap(p, min); //这里很关键,如何交换两个节点的值,而不改变节点的指针指向?
p = p->next;
}
printf("整理后的通讯录为:\n");
display(head);
}
void swap(Link p, Link q)
{
Node temp = *p;
temp.next = q->next;
q->next = p->next;
*p = *q; //注意注意
*q = temp; //注意注意
}
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
int namecmp(char * p,char * q)
{
int i,j,flag = 1; //flag = 表示名字不匹配
for (i = 0;i < strlen(p);i++)
{
if (*(p+i) == *(q) && *(p+i+1) == *(q+1))
{
for(j = 0;j < strlen(q);i++,j++)
{
if (*(p+i) != *(q+j))
{
flag = 1;
break;
}
}
if (j == strlen(q))
flag = 0;
}
}
return flag;
}
void creat_link(Link * head) //二级指针适用于希望修改指针变量内容的场合
{
Link new_node;
new_node = (Link)malloc(sizeof(Node));
new_node->num = 2018;
strcpy(new_node->name,"node_head");
*head = new_node;
new_node->next = NULL;
}
int judge_node(Link new_node) //一级指针适用于只读指针内容的场合
{
if (new_node == NULL)
return MAL_ERR;
else
return MAL_OK;
}
void creat_node(Link * new_node, int i) //创建结点包括申请内存分配和给num赋值
{
char * name[5] = {"Tom Cruise","Lebron James","Kobe Byrant","Fat Chou","Hao Yu"};
int num[5] = {85850660,85417863,85416756,85573153,85159648};
do
{
*new_node = (Link)malloc(sizeof(Node));
}while(judge_node(*new_node) == MAL_ERR);
strcpy((*new_node)->name,name[i]);
(*new_node)->num = num[i];
}
void insert_node_head(Link new_node, Link head) //头插结点,把新结点的指针域指向头指针
{
new_node->next = head->next; //新结点的指针域指向头指针
head->next = new_node; //头指针指向新结点
}
void insert_node_tail(Link new_node, Link head) //尾插结点
{
Link p; //定义一个struct node型的指针
p = head;
while(p->next != NULL) //链表只能用顺序访问的方法
p = p->next;
p->next = new_node; //如果p的指针域指向NULL,那么p就是末尾结点,在该结点后插入
new_node->next = NULL;
}
void insert_node_mid(Link new_node, Link head, int num_loc)//中插(前插)
{
Link p,q;
p = q =head;
while(p->num != num_loc && p->next != NULL)
{
q = p;
p = p->next;
}
if(p->next == NULL && p->num != num_loc )
{
p->next = new_node;
new_node->next = NULL;
}
else
{
q->next = new_node;
new_node->next = p;
}
}
void delete_node(Link head, int num_del) //删除结点
{
Link p,q;
p = q = head;
while(p->num != num_del && p->next != NULL)
{
q = p;
p = p->next;
}
if(p->next == NULL && p->num != num_del)
printf("ERROR\n");
else
{
q->next = p->next;
free(p);
}
}
void display(Link head)
{
Link p;
int i = 0;
p = head;
if (p == NULL)
printf("链表已被释放\n");
else if(p->next == NULL)
printf("链表已被清空\n");
else
{
p = p->next;
while(p != NULL)
{
i++;
if (p != NULL)
{
printf("第%d个联系人:\n",i);
printf("//姓名:%s\n",p->name);
printf("//电话号码:%d\n",p->num);
}
p = p->next;
}
}
}
void makempty_link(Link *head)
{
Link p, q;
p = (*head)->next;
if (*head == NULL)
printf("Link is null!!!!!!!\n");
else
{
while(p != NULL)
{
q = p;
free(p);
p = q->next;
}
(*head)->next = NULL;
}
}
void release_link(Link *head)
{
Link p, q;
p = *head;
if (*head == NULL)
printf("Link is empty!!!!!!!\n");
else
{
while(p != NULL)
{
free(p);
p = p->next;
}
}
*head = NULL;
}