一、实验目的:
1、复习C语言程序设计中的知识。
2、掌握线性表的链式存储结构的表示和实现方法。
3、掌握单链表基本操作的算法实现。
二、实验内容:
1.建立单链表。
2.在单链表上实现插入、删除和查找等操作。
三、实验要求:
编写实现单链表的基本算法(初始化、查找、插入、删除等)的函数,并在此基础上设计一个主程序完成如下功能:
⑴初始化整型单链表H;
⑵采用尾插法建立单链表H,如(a,b,c,d,c);
⑶输出单链表H的长度;
⑷输出单链表H的第i个元素,如输出单链表H的第3个元素;
⑸输出给定元素的位置,如输出元素a的位置;
⑹在第i个元素前插入给定元素,如在第4个元素前插入元素f;
⑺删除单链表H的第i个元素,如删除单链表H的第3个元素。
⑻输出单链表
代码如下:(注:需要运行功能a再执行其他功能)
#include<stdio.h>
#include<stdlib.h >
typedef int elemtype; //节点的数据类型,设为整型
typedef struct node //定义单链表节点类型
{
elemtype data; //节点的数据域
struct node *next; //节点的指针域
}LinkList; //单链表的类型名为 LinkList
LinkList *head; //head 是指向单链表类型LinkList的指针变量
//初始化单链表
LinkList *Init_LinkList()
{
LinkList *head; //
head = (LinkList*)malloc(sizeof(LinkList)); //生成头结点指针
if (head == NULL) //如果申请空间失败,返回空指针
{
printf("初始化失败!\n");
return 0;
}
else
{
printf("初始化成功!\n");
return head;
}
}
//尾插法创建带头结点单链表的函数
LinkList *Create_LinkListR(LinkList*head) //尾插法创建带头结点单链表的函数
{
elemtype ix; //
LinkList *p, *tail; //*head,tail分别为头指针和尾指针
head->next = NULL; //置头结点指针域为空
tail = head; //尾指针域指向头结点
printf("请输入数据直到输入0结束:"); //
scanf("%d", &ix); //输入第一个数据
while (ix != 0) //输入数据,0为结束标志
{
p = (LinkList*)malloc(sizeof(LinkList));//生成新结点
if (p == NULL) //如果申请空间失败,返回主调函数
{
printf("新结点申请空间失败,无法继续建立单链表!\n");
return head;
}
p->data = ix; //为新结点数据域赋值
tail->next = p; //修改尾结点指针域
tail = p; //修改尾指针
tail->next = NULL; //将尾结点的指针域置为空
scanf("%d", &ix); //读入下一个数据
}
printf("单链表建立成功!\n");
return head; //返回头结点指针
}
//单链表的遍历
int Print_LinkList(LinkList*head) //单链表的遍历
{
LinkList *p = head->next; //
if (p == NULL) //链表为空,返回值为0
{
printf("单链表为空!\n");
return 0; //
}
while (p != NULL) //当前结点不为空
{
printf("%d\n", p->data); //输出当前结点的数据
p = p->next; //移动指针指向下一个结点
}
return 1;
}
//单链表的长度
void LinkList_Length(LinkList*head) //单链表的长度
{
LinkList*p = head; //p指向头结点
int j = 0; //
while (p->next != NULL) //
{
p = p->next; //p指向的是第j个结点
j++; //
}
printf("单链表长度为:%d\n", j);
}
//单链表查找,按序号查找
LinkList *GetData_LinkList(LinkList *head/*, int i*/) //单链表查找,按序号查找
{
LinkList *p; //
int i;
int j = 0; //
printf("需要查找的元素为第几个?\n");
scanf("%d", &i);
if (i <= 0) //指定的位置非法时返回NULL
{
printf("你所输入的元素位置非法!\n");
return NULL; //
}
p = head; //
while (p->next != NULL&&j < i) //不是目标结点且还有后继结点时继续查找
{
p = p->next; //
j++; //
}
if (i == j) //找到目标结点,返回当前指针
{
printf("查找的元素为:%d\n",p->data);
return p; //
}
else
{
printf("未找到目标结点!\n");
return NULL; //未找到目标结点,返回NULL
}
}
LinkList *GetData_LinkList_A(LinkList *head, int i)
{
LinkList *p; //
int j = 0; //
if (i <= 0) //指定的位置非法时返回NULL
{
printf("你所输入的元素位置非法!\n");
return NULL; //
}
p = head; //
while (p->next != NULL&&j < i) //不是目标结点且还有后继结点时继续查找
{
p = p->next; //
j++; //
}
if (i == j) //找到目标结点,返回当前指针
{
/*printf("查找的元素为:%d\n", p->data);*/
return p; //
}
else
{
printf("未找到目标结点!\n");
return NULL; //未找到目标结点,返回NULL
}
}
//单链表的查找,按值查找
LinkList *Search_LinkList(LinkList *head/*, elemtype key*/)//单链表的查找,按值查找
{
LinkList *p;
elemtype key;
int j = 0,i=1;
printf("请输入所需查找元素的值:");
scanf("%d", &key);
p = head->next; //指针指向首结点
while (p != NULL) //
{
if (p->data != key) //
{
p = p->next; //取下一个结点,继续查找
i++;
}
else
{
printf("所查找的元素位置为:%d\n", i);
j = 1;
break; //找到结点key,退出循环
}
}
if (j == 0)
{
printf("链表中没有该元素。\n");
}
return 0;
/*return p;*/ //返回找到的结点指针域或未找到时的NULL
}
//单链表的插入 后插运算
void InserAfter_LinkList(LinkList *p, LinkList *s) //单链表的插入 后插运算
{
s->next = p->next; //新结点连入链表
p->next = s; //修改前趋结点的指针域
}
//单链表的插入,前插运算
void InserBefore_LinkList(LinkList *head/*, LinkList *p, LinkList *s*/)//单链表的插入,前插运算
{
LinkList *q; //
LinkList *p;
LinkList *s;
q = head; //
printf("在哪个元素前插入元素?\n");
scanf("%d", p->data);
printf("请输入所要插入的元素:%d", s->data);
while (q->next != p) //从头结点开始搜索结点p的前驱结点
{
q = q->next; //
}
s->next = p; //修改相应结点的指针域
q->next = s; //修改相应结点的指针域
printf("插入成功!\n");
}
//单链表的插入,在指定序号前插入运算
int InserNo_LinkList(LinkList *head/*, LinkList *s, int i*/) //单链表的插入,在指定序号前插入运算
{
LinkList *p, *s;
int i;
s = (LinkList*)malloc(sizeof(LinkList));
printf("在第几个元素前插入元素?\n");
scanf("%d", &i);
printf("插入的元素为:");
scanf("%d", &s->data);
if (i <= 0)
{
p = NULL;
}
else if (i == 1)
{
p = head;
}
else
{
p = GetData_LinkList_A(head, i - 1); //搜索第i-1个结点
}
if (p == NULL)
{
printf("你所输入的位置不合法!\n");
return 0; //不存在第i个位置的结点
}
else
{
InserAfter_LinkList(p, s); //调用后插函数
printf("插入成功!\n");
return 1;
}
}
//单链表的删除 删除后继结点
int DeleteAfter_LinkList(LinkList *p) //单链表的删除 删除后继结点 删除p的后继结点,成功返回1,否则返回0
{
LinkList *r;
if (!p)
{
return 0;
}
r = p->next;
if (!r)
{
return 0;
}
p->next = r->next; //将结点r从链表上摘除
free(r); //释放结点占用的内存空间
return 1;
}
//单链表的删除 删除指定结点本身
int DeleteNode_LinkList(LinkList *head, LinkList *p)//单链表的删除 删除指定结点本身
{
LinkList *r;
if (p->next != NULL) //若p有后继结点
{
p->data = p->next->data; //将后继结点的数据写入当前结点的数据域
return (DeleteAfter_LinkList(p)); //删除p的后继结点
}
else
{
r = head;
while (r->next != p) //搜索p的前驱结点
{
r = r->next;
}
return (DeleteAfter_LinkList(r)); //删除p的后继结点
}
}
//单链表的删除 删除指定位置的结点
int DeleteNo_LinkList(LinkList *head/*, int i*/) //单链表的删除 删除指定位置的结点 删除成功返回1,否则返回0
{
LinkList *p, *r;
int i;
printf("删除第几个元素?\n");
scanf("%d", &i);
if (i <= 0)
{
p = NULL;
}
else if (i == 1)
{
p = head;
}
else
{
p = GetData_LinkList_A(head, i - 1); //搜索第i-1个结点
}
if (p == NULL) //不存在第i个结点,删除失败
{
return 0;
}
else //找到第i-1个结点
{
r = p->next;
if (r == NULL) //第i个结点不存在,删除失败
{
return 0;
}
p->next = r->next; //删除指定结点
printf("删除成功!\n");
free(r);
return 1;
}
}
//置空表
LinkList *SetNull_LinkList(LinkList *head) //置空表
{
while (head->next)
{
DeleteAfter_LinkList(head); //依次删除每个结点
}
printf("单链表置空成功!\n");
return head;
}
//菜单界面
void menu()
{
system("cls");
printf("\n");
printf("\t\t---------------欢迎使用单链表的基本操作------------------\n");
printf("\t\t|\t\t a 初始化单链表 \t\t|\n");
printf("\t\t|\t\t b 采用尾插法建立单链表 \t\t|\n");
printf("\t\t|\t\t c 输出单链表的长度 \t\t|\n");
printf("\t\t|\t\t d 输出单链表的第i个元素 \t\t|\n");
printf("\t\t|\t\t e 输出给定的元素的位置 \t\t|\n");
printf("\t\t|\t\t f 在第i个元素前插入给定的元素\t\t|\n");
printf("\t\t|\t\t g 删除单链表的第i个元素 \t\t|\n");
printf("\t\t|\t\t h 输出单链表 \t\t|\n");
printf("\t\t|\t\t i 置空单链表 \t\t|\n");
printf("\t\t|\t\t j 退出系统 \t\t|\n");
printf("\t\t---------------------------------------------------------\n");
printf("\t\t请选择(a-j):");
}
int main()
{
LinkList *head;
int quit=0;
char select;
while (1)
{
menu(); //调用子函数
scanf("%c", &select);
switch (select)
{
case 'a': head =Init_LinkList(); break;//初始化单链表
case 'b': Create_LinkListR(head); break; //采用尾插法建立单链表
case 'c': LinkList_Length(head); break; //输出单链表的长度
case 'd': GetData_LinkList(head); break;//输出单链表的第i个元素 按序号查找
case 'e': Search_LinkList(head); break;//输出给定的元素的位置 按值查找
case 'f': InserNo_LinkList(head); break;//在第i个元素前插入给定的元素
case 'g': DeleteNo_LinkList(head); break;//删除单链表的第i个元素 删除指定位置的结点
case 'h': Print_LinkList(head); break;//输出单链表
case 'i': SetNull_LinkList(head); break;//置空单链表
case 'j': quit = 1; break;
default:printf("请输入a~j之间的数字\n"); break;
}
if (quit == 1)
{
break;
}
printf("按任意键返回主菜单!\n");
getchar(); //提取到缓冲区中的回车键
getchar(); //起到暂停的作用
printf("程序结束!\n");
}
return 0;
}