自己写了一个小程序,进行链表的一些基本操作。简单起见,链表的节点仅包含一个范围在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");
}
}