单链表实现简易通讯录(内附源码)

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include<assert.h>
#include<stdbool.h>

#define NAME_MAX 100
#define SEX_MAX 10
#define TEL_MAX 15
#define ADDR_MAX 100

typedef struct PersonInfo
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}PeoInfo;

typedef struct PersonInfo SLDataType;


typedef struct SListNode
{
	SLDataType data;
	struct SListNode* next;
}SLNode;

typedef SLNode contact;


void InitList(SLNode** phead)//初始化节点
{
	*phead = NULL;
}

void SLPrint(SLNode* phead)//打印函数
{
	//备份phead,临时变量存储
	SLNode* pcur = phead;//pcur是node1的地址
	while (pcur)
	{
		printf("%d -> ", pcur->data);
		pcur = pcur->next;//pcur->next是下一个地址
	}
	printf("NULL\n");
}

SLNode* SLBuyNode(SLDataType x)//创建新节点
{
	SLNode* node = (SLNode*)malloc(sizeof(SLNode));
	if (node == NULL)
		return;
	node->data = x;//结构体能直接传值
	node->next = NULL;
	return node;
}

void SLPushBack(SLNode** pphead, SLDataType x)//尾插
//SLPushBack(&plist, 1)  传入的是地址的地址,采用二级指针来接收
{
	assert(pphead);
	SLNode* node = SLBuyNode(x);
	if (*pphead == NULL)//链表为空,则创建新节点
	{
		*pphead = node;
		return;//跳过以下部分
	}

	SLNode* pcur = *pphead;//备份
	//此时 pcur 指向第头节点
	while (pcur->next)
	{
		pcur = pcur->next;
		//找到倒数第二个节点
	}
	pcur->next = node;
}


void SLPushFront(SLNode** pphead, SLDataType x)//头插
{
	assert(pphead);
	SLNode* node = SLBuyNode(x);

	//若头结点为空,以下代码也可以进行头插操作
	node->next = *pphead;//*pphead 是第一个结点的地址
	*pphead = node;//node成为新的头节点
}



void SLPopBack(SLNode** pphead)//尾删
{
	assert(pphead);
	assert(*pphead);//第一个节点不能为空

	//只有一个结点的情况
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}

	SLNode* ptail = *pphead;//ptail指向最后一个节点
	SLNode* prev = NULL;//倒数第二个节点

	//找到尾节点和尾节点前一个结点
	while (ptail->next != NULL)
	{
		prev = ptail;
		ptail = ptail->next;
	}

	prev->next = NULL;
	free(ptail);
	ptail = NULL;

}



void SLFrontBack(SLNode** pphead)//头删
{
	assert(pphead);
	assert(*pphead);//第一个节点不能为空

	SLNode* del = *pphead;//备份头节点
	*pphead = (*pphead)->next;//指向新的头结点

	free(del);
	del = NULL;
}


/*
//找到按照x查找节点
SLNode* SLFind(SLNode** pphead, SLDataType x)
{
	SLNode* pcur = *pphead;
	while (pcur)
	{
		if (pcur->data == x)
			return pcur;
		pcur = pcur->next;
	}
	return NULL;
}
*/

//在指定位置之前插入数据
void SLInsert(SLNode** pphead, SLNode* pos, SLDataType x)
{
	assert(pphead);//链表非空
	assert(*pphead);//第一个节点非空

	assert(pos);//位置非空

	SLNode* node = SLBuyNode(x);

	//只有一个结点的情况 ( pos指向第一个节点 )
	if (pos == *pphead)
	{
		node->next = *pphead;
		*pphead = node;
		return;
	}

	//先找到pos前一个结点
	SLNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}

	// prev node pos
	node->next = pos;
	prev->next = node;

}


//在指定位置之后插入数据
void SLInsertAfter(SLNode* pos, SLDataType x)
{
	assert(pos);//位置非空

	SLNode* node = SLBuyNode(x);

	node->next = pos->next;
	pos->next = node;
	//此时有 pos 的地址但没有 pos->next ,不能颠倒

}


//删除指定pos节点
void SLErase(SLNode** pphead, SLNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);

	//要删除头结点
	if (pos == *pphead)
	{
		*pphead = (*pphead)->next;
		free(pos);
		return;
	}

	//找 pos 前的节点
	SLNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}

	prev->next = pos->next;
	free(pos);
	pos = NULL;

}


//删除指定pos节点之后的节点
void SLEraseAfter(SLNode* pos)
{
	// pos 及 pos->next 非空
	assert(pos && pos->next);

	SLNode* del = pos->next;//先保存 pos->next
	pos->next = del->next;

	free(del);
}


//销毁链表
void SLDestroy(SLNode** pphead)
{
	assert(pphead);
	SLNode* pcur = *pphead;

	//销毁结点之前,先保存下一个结点的地址
	while (pcur)
	{
		SLNode* del = pcur->next;//存储下一个节点
		free(pcur);
		pcur = del;
	}

	*pphead = NULL;
}






 SL *s 等价于 contact * con
void InitContact(contact** con)//通讯录初始化
{
	InitList(con);
}


void DestoryContact(contact** con)//通讯录销毁
{
	SLDestroy(con);
}


void ShowContact(contact* con)//打印通讯录
{
	printf("\n%-15s %-15s %-15s %-15s %-15s\n", "姓名", "性别", "年龄", "电话", "地址");
	contact* cur = con;
	while (cur)
	{
		printf("%-15s %-15s %-15d %-15s %-15s\n",
			cur->data.name,
			cur->data.sex,
			cur->data.age,
			cur->data.tel,
			cur->data.addr);
		cur = cur->next;
	}
	printf("\n");
}


void AddContact(contact** con)//添加联系人
{
	PeoInfo info;

	printf("请输入要添加联系人的信息:\n");
	printf("请输入联系人姓名:\n");
	scanf("%s", info.name);

	printf("请输入联系人性别:\n");
	scanf("%s", info.sex);

	printf("请输入联系人年龄:\n");
	scanf("%d", &(info.age));

	printf("请输入联系人电话:\n");
	scanf("%s", info.tel);

	printf("请输入联系人地址:\n");
	scanf("%s", info.addr);

	//数据存储在info中
	//往通讯录(顺序表)中插入数据
	SLPushBack(con, info);
	printf("\n");
}


contact* FindByName(contact* con, char name[])//查找下标
{
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}


void FindContact(contact* con)//查找联系人
{
	printf("请输入要查找联系人姓名: ");
	char name[NAME_MAX];
	scanf("%s", name);
	contact* pos = FindByName(con, name);
	if (pos == NULL)
	{
		printf("要查找的人不存在!\n");
		return;
	}
	printf("\n%s的信息如下:\n", name);
	printf("%-15s %-15s %-15s %-15s %-15s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%-15s %-15s %-15d %-15s %-15s\n",
		pos->data.name,
		pos->data.sex,
		pos->data.age,
		pos->data.tel,
		pos->data.addr);
}


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 ModifyContact(contact** con)//修改联系人
{
	printf("\n请输入要修改联系人姓名: ");
	char name[NAME_MAX];
	scanf("%s", name);
	contact* pos = FindByName(*con, name);
	if (pos == NULL)
	{
		printf("要查找的人不存在!\n");
		return;
	}
	printf("\n请输入要修改联系人的信息:\n");

	printf("请输入要修改联系人姓名:\n");
	scanf("%s", pos->data.name);

	printf("请输入要修改联系人性别:\n");
	scanf("%s", pos->data.sex);

	printf("请输入要修改联系人年龄:\n");
	scanf("%d", &(pos->data.age));

	printf("请输入要修改联系人电话:\n");
	scanf("%s", pos->data.tel);

	printf("请输入要修改联系人地址:\n");
	scanf("%s", pos->data.addr);


	printf("\n");
}



void DestroyContactFile(contact** con)//销毁通讯录
{
	SLDestroy(con);
}





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


int main()
{
	//slttrst();
	//slttrst1();

	contact* con;//  SeqList con
	InitContact(&con);

	int op = -1;
	do {
		menu();
		printf("请进行你的选择: \n");
		scanf("%d", &op);

		switch (op)
		{
		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 (op != 0);

	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
链表可以用来实现员工通讯录管理系统。下面是一种可能的实现方式: 定义员工结构体: ``` typedef struct Employee { int id; // 员工编号 char name[20]; // 员工姓名 char phone[20]; // 员工电话 struct Employee *next; // 指向下一个员工的指针 } Employee; ``` 定义链表结构体: ``` typedef struct EmployeeList { Employee *head; // 链表头指针 int length; // 链表长度 } EmployeeList; ``` 初始化链表: ``` EmployeeList initEmployeeList() { EmployeeList list; list.head = NULL; list.length = 0; return list; } ``` 添加员工: ``` void addEmployee(EmployeeList *list, Employee employee) { Employee *newEmployee = (Employee*)malloc(sizeof(Employee)); *newEmployee = employee; newEmployee->next = NULL; if(list->head == NULL) { list->head = newEmployee; } else { Employee *p = list->head; while(p->next != NULL) { p = p->next; } p->next = newEmployee; } list->length++; } ``` 删除员工: ``` void deleteEmployee(EmployeeList *list, int id) { if(list->head == NULL) { return; } if(list->head->id == id) { Employee *temp = list->head; list->head = list->head->next; free(temp); list->length--; return; } Employee *p = list->head; while(p->next != NULL) { if(p->next->id == id) { Employee *temp = p->next; p->next = p->next->next; free(temp); list->length--; return; } p = p->next; } } ``` 查找员工: ``` Employee* findEmployee(EmployeeList *list, int id) { Employee *p = list->head; while(p != NULL) { if(p->id == id) { return p; } p = p->next; } return NULL; } ``` 遍历链表: ``` void traverse(EmployeeList *list) { Employee *p = list->head; while(p != NULL) { printf("id:%d name:%s phone:%s\n", p->id, p->name, p->phone); p = p->next; } } ``` 这样,我们就可以使用链表实现员工通讯录管理系统了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值