链表的基本操作

自己写了一个小程序,进行链表的一些基本操作。简单起见,链表的节点仅包含一个范围在1~99的随机整数。

程序提供了一个菜单,该菜单会循环出现,直到用户按下q退出为止,如下图所示。



下面对菜单中的各项功能进行说明。

a、创建新链表

需要输入链表的长度,如果链表已经存在,会要求先删除当前链表,再创建新链表,如下图所示,创建了一个10个节点的链表。



b、显示当前链表,不解释。

c、获取链表长度,不解释。

d、按位置查询

根据输入的位置来查询该节点的值,程序会根据链表长度提示输入的范围。以刚才创建的链表为例,会提示输入1到10之间的数。第3个节点是51,查询一下看看是不是。



e、按值查询

与d选项相反,这里需要输入想查找的值,程序会检索出等于该值的所有节点,或者提示不存在。仍以之前的链表为例,13出现在第8个节点,查查看。



f、插入一个节点

需要输入一个整数,表示想插入到哪个节点之后,范围是0~当前链表长度,0表示插入表头。我们在第2个节点后面插入一个1。



g、修改节点的值

先输入要修改的节点的位置,再输入修改之后的值。我们把第3个节点的1修改为99。



h、删除某个节点

只需要输入节点的位置就行了。我们把第1个节点给删除了。



i、删除整个链表,不解释

q、退出,也不解释


此外,为了达到友好的人机交互效果,每次需要用户输入的地方,都编写了输入检查功能,对于非法输入会提示重新输入,并且会及时清理输入缓冲区。

全部代码如下:

#include <STDIO.H>
#include <STDLIB.H>
#include <TIME.H>
#include <CONIO.H>

#define NUM_MAX 99 //随机数范围[1, NUM_MAX]

struct node{
	int num;
	struct node *next;
};

struct list{
	int length;
	struct node *head;
};

typedef struct node Node;
typedef struct list List;

void ShowMenu(void);
void ClearBuffer(void);
void CreateList(List *);
void ShowList(const List *);
void ShowLength(const List *);
void ShowValue(const List *);
int GetNodeValue(const List *, int);
void ShowPosition(const List *);
void Insert(List *);
void InsertNode(List *, int, int);
void Modify(List *);
void ModifyNode(List *, int, int);
void Delete(List *);
void DeleteNode(List *, int);
void DeleteList(List *);

int main(void)
{
	List linkList;
	List *pList;
	char response;

	srand((unsigned int)time(0));
	linkList.head = NULL;
	linkList.length = 0;
	pList = &linkList;
	ShowMenu();

	while ((scanf("%c", &response) != 1) || response != 'q')
	{
		if (response == '\r' || response == '\n')
		{
			printf("输入有误。\n");
		}
		else if (response < 'a' || response > 'i')
		{
			printf("输入有误。\n");
			ClearBuffer();
		} 
		else
		{
			ClearBuffer();
			switch (response)
			{
			case 'a':
				CreateList(pList);
				break;
			case 'b':
				ShowList(pList);
				break;
			case 'c':
				ShowLength(pList);
				break;
			case 'd':
				ShowValue(pList);
				break;
			case  'e':
				ShowPosition(pList);
				break;
			case 'f':
				Insert(pList);
				break;
			case 'g':
				Modify(pList);
				break;
			case 'h':
				Delete(pList);
				break;
			case 'i':
				DeleteList(pList);
				break;
			}
		}
		printf("\n按任意键继续...\n");
		getch();
		printf("\n");
		ShowMenu();
	}

	return 0;
}

//显示菜单
void ShowMenu(void)
{
	printf("请选择:\n");
	printf("%-20s%-20s%-20s\n", "a. 创建新链表", "b. 显示当前链表", "c. 获取链表长度");
	printf("%-20s%-20s%-20s\n", "d. 按位置查询", "e. 按值查询", "f. 插入一个节点");
	printf("%-20s%-20s%-20s%s\n", "g. 修改节点的值", "h. 删除某个节点", "i. 删除整个链表", "q. 退出");
}

//清理输入缓冲区
void ClearBuffer(void)
{
	while (getchar() != '\n')
		continue;
}

//创建新链表
void CreateList(List *pList)
{

	if (pList->head)
	{
		printf("链表已存在,请先删除当前链表,再创建新链表。\n");
	} 
	else
	{
		int m_length = 0;
		printf("输入链表长度:");
		while ((scanf("%d", &m_length) != 1) || m_length < 1)
		{
			printf("输入无效! 请重新输入链表长度:");
			ClearBuffer();
		}
		ClearBuffer();
		if (m_length == 1)
		{
			pList->head = (Node *)malloc(sizeof(Node));
			pList->head->num = rand() % NUM_MAX + 1;
			pList->head->next = NULL;
			pList->length = 1;
		} 
		else
		{
			Node *p, *q;
			int k;

			p = (Node *)malloc(sizeof(Node));
			p->num = rand() % NUM_MAX + 1;
			q = p;
			pList->head = p;
			pList->length = m_length;
			k = 2;
			while (k <= m_length)
			{
				p = (Node *)malloc(sizeof(Node));
				p->num = rand() % NUM_MAX + 1;
				q->next = p;
				q = p;
				k++;
			}
			p->next = NULL;
		}
		printf("链表创建完毕。");
	}
	ShowList(pList);
}

//显示链表
void ShowList(const List *pList)
{
	if (pList->head)
	{
		Node *p = pList->head;
		printf("当前链表为:\n");
		while(p->next)
		{
			printf("%d->", p->num);
			p = p->next;
		}
		printf("%d\n", p->num);
	} 
	else
	{
		printf("当前链表为空。\n");
	}
}

//显示链表长度
void ShowLength(const List *pList)
{
	printf("当前链表长度为%d。\n", pList->length);
}

//查询某个节点的值
void ShowValue(const List *pList)
{
	if (pList->head)
	{
		int pos = 0;
		printf("输入查询位置(1到%d之间):", pList->length);
		while ((scanf("%d", &pos) != 1) || pos < 1 || pos > pList->length)
		{
			printf("输入有误,请重新输入查询位置(1到%d之间):", pList->length);
			ClearBuffer();
		}
		ClearBuffer();
		printf("查询成功,第%d个节点的值为%d。\n", pos, GetNodeValue(pList, pos));
	} 
	else
	{
		printf("当前链表为空,无法查询。\n");
	}
}

//得到某个节点的值
int GetNodeValue(const List *pList, int pos)
{
	int k = 1;
	Node *p = pList->head;
	while (k < pos)
	{
		p = p->next;
		k++;
	}
	
	return p->num;
}

//查询某个值在链表中的所有位置
void ShowPosition(const List *pList)
{
	if (pList->head)
	{
		int num;
		printf("输入要查询的值:");
		while (scanf("%d", &num) != 1)
		{
			printf("输入有误,请重新输入要查询的值:");
			ClearBuffer();
		}
		ClearBuffer();
		Node *p = pList->head;
		int k = 1, i = 0;
		printf("查询结果:\n");
		while (k <= pList->length)
		{
			if (p->num == num)
			{
				i++;
				printf("第%d次出现在第%d个节点。\n", i, k);
			}
			k++;
			p = p->next;
		}
		if (i == 0)
		{
			printf("当前链表中不存在该值。\n");
		}
	} 
	else
	{
		printf("当前链表为空,无法查询。\n"); 
	}
}

//插入操作
void Insert(List *pList)
{
	int pos, num;

	if (pList->head)
	{
		printf("插入到第几个节点之后(0到%d,0表示插入到表头):", pList->length);
		while ((scanf("%d", &pos) != 1) || pos < 0 || pos > pList->length)
		{
			printf("输入有误,请重新输入插入位置(0到%d):", pList->length);
			ClearBuffer();
		}
		ClearBuffer();
	} 
	else
	{
		printf("当前链表为空,新节点只能插入到表头。\n");
		pos = 0;
	}
	printf("输入节点的值:");
	while (scanf("%d", &num) != 1)
	{
		printf("输入有误,请重新输入节点的值:");
		ClearBuffer();
	}
	ClearBuffer();
	InsertNode(pList, pos, num);
	ShowList(pList);
}

//在某个节点之后插入一个节点
void InsertNode(List *pList, int pos, int num)
{
	Node *p, *q;

	if (pos == 0)
	{
		q = pList->head;
		p = (Node *)malloc(sizeof(Node));
		p->num = num;
		p->next = q;
		pList->head = p;
		pList->length++;
	}
	else
	{
		int k = 1;
		q = pList->head;
		while (k < pos)
		{
			q = q->next;
			k++;
		}
		p = (Node *)malloc(sizeof(Node));
		p->num = num;
		p->next = q->next;
		q->next = p;
		pList->length++;
	}
	printf("插入完成。");
}

//修改操作
void Modify(List *pList)
{
	if (pList->head)
	{
		int pos = 0;
		int num;
		printf("输入要修改的节点位置(1到%d之间):", pList->length);
		while ((scanf("%d", &pos) != 1) || pos < 1 || pos > pList->length)
		{
			printf("输入有误,请重新输入节点位置(1到%d之间):", pList->length);
			ClearBuffer();
		}
		ClearBuffer();
		printf("该节点当前的值为%d。", GetNodeValue(pList, pos));
		printf("输入修改之后的值:");
		while (scanf("%d", &num) != 1)
		{
			printf("输入有误,请重新输入节点的值:");
			ClearBuffer();
		}
		ClearBuffer();
		ModifyNode(pList, pos, num);
		ShowList(pList);
	} 
	else
	{
		printf("当前链表为空,无法修改。\n");
	}
}

//修改某个节点的值
void ModifyNode(List *pList, int pos, int num)
{
	Node *p = pList->head;
	int k = 1;
	while (k < pos)
	{
		p = p->next;
		k++;
	}
	p->num = num;
	printf("修改完成。");
}

//删除操作
void Delete(List *pList)
{
	if (pList->head)
	{
		int pos = 0;
		printf("输入删除节点的位置(1到%d之间):", pList->length);
		while ((scanf("%d", &pos) != 1) || pos < 1 || pos > pList->length)
		{
			printf("输入有误,请重新输入删除位置(1到%d之间):", pList->length);
			ClearBuffer();
		}
		ClearBuffer();
		DeleteNode(pList, pos);
		ShowList(pList);
	} 
	else
	{
		printf("当前链表为空,无法删除节点。\n");
	}
}

//删除某个节点
void DeleteNode(List *pList, int pos)
{
	Node *p;

	if (pos == 1)
	{
		p = pList->head;
		pList->head = p->next;
		printf("删除完成,已删除第%d个节点,其值为%d。\n", pos, p->num);
		free(p);
		pList->length--;
	}
	else
	{
		Node *q;
		p = pList->head;
		int k = 1;
		while (k < pos)
		{
			q = p;
			p = q->next;
			k++;
		}
		printf("删除完成,已删除第%d个节点,其值为%d。\n", pos, p->num);
		q->next = p->next;
		free(p);
		pList->length--;
	}
}

//删除整个链表
void DeleteList(List *pList)
{
	if (pList->head)
	{
		Node *p;
		while (pList->head)
		{
			p = pList->head;
			pList->head = p->next;
			free(p);
			pList->length--;
		}
		printf("链表已删除。\n");
	} 
	else
	{
		printf("链表已经为空。\n");
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值