严蔚敏数据结构C语言版 P34 2.17
静态链表的删除操作的思想实践(删除静态链表第i个结点)
/*
严蔚敏数据结构C语言版 P34 2.17
静态链表的删除操作的思想实践(删除静态链表第i个结点)
*/
//头文件
#include<stdio.h>
#include<stdlib.h>
//宏区
#define SIZEMAX 10 //定义最大静态链表结点数
//结构
typedef struct //静态链表的结构
{
int data; //数据域
int cur; //游标
}Sqlink_list, Plink_list[SIZEMAX];
//函数声明
void Link_list_initialize(Plink_list); //初始化静态链表(将所有结点挂在备用头结点上)
int Link_list_allot(Plink_list); //分配空闲结点
void Link_list_build(Plink_list); //建立静态链表
void Link_list_printf(Plink_list); //输出静态链表
void Link_list_delect(Plink_list); //静态链表的删除
//函数区
void Link_list_initialize(Plink_list link_list) //初始化静态链表(将所有结点挂在备用头结点上)
{
int i;
for (i = 0;i < SIZEMAX;i++) //SIZEMAX - 1个元素依次挂在备用头结点上
{
link_list[i].cur = i + 1; //指向下一个结点
}
link_list[SIZEMAX - 1].cur = NULL; //将尾结点挂起
}
int Link_list_allot(Plink_list link_list) //分配空闲结点
{
int i = 1;
if (i) //如果有空闲结点
{
i = link_list[0].cur; //分配一个空闲结点给i
link_list[0].cur = link_list[i].cur; //将备用头结点指向被分配的空闲结点的下一个结点
}
if(NULL == i) //如果没有可分配的备用结点
{
printf("没有可分配的空闲结点了,请重新检查程序!\n"); //提醒用户
exit(0); //正常终止程序
}
return i; //返回当前被分配的空闲结点
}
void Link_list_build(Plink_list link_list) //建立静态链表
{
int len, i, k, c, val;
printf("输入要建立静态链表结点的个数(0 - 8):"); //显示提醒用户输入个数
scanf_s("%d", &len); //记录个数
while ((SIZEMAX - 2) < len || len <= 0) //判断输入长度值是否合法(因为有两个是头结点所以只能开辟八个)
{
printf("个数非法,重新输入结点个数(10 >= x > 0):"); //提示用户
scanf_s("%d", &len); //用户输入个数
}
i = Link_list_allot(link_list); //开辟有效结点的头结点
c = i; //该游标永远指向尾结点
for (k = 1;k <= len;k++) //依次开辟用户定义的结点数
{
printf("输入第%d个静态结点的值:", k); //显示提醒用户输入值
scanf_s("%d", &val); //记录值
i = Link_list_allot(link_list); //开辟新结点
link_list[i].data = val; //将数值发送给新结点的数据域
link_list[c].cur = i; //将新结点的前一个结点的游标指向新结点
c = i; //c操作游标指向尾结点
}
link_list[len + 1].cur = NULL; //将有效结点的尾结点挂起
}
void Link_list_printf(Plink_list link_list) //输出静态链表
{
int i = 1;
i = link_list[i].cur;
printf("当前静态链表的数值为:"); //显示数值
while (i) //如果不为尾结点
{
printf("%d ", link_list[i].data); //输出数据值
i = link_list[i].cur; //指向下一个结点
}
printf("\n");
}
void Link_list_delect(Plink_list link_list) //静态链表的删除(删除静态链表第i个结点)
{
int whe, i = 1, j, k;
printf("输入需要删除静态链表第几个结点:"); //显示提醒用户输入信息
scanf_s("%d", &whe); //记录信息
while (SIZEMAX < whe || whe <= 0) //判断输入长度值是否合法
{
printf("个数非法,重新输入删除的结点位置(10 >= x > 0):");//提示用户
scanf_s("%d", &whe); //用户输入位置
}
for (j = 1;j < whe;j++) //找到需要删除的结点的前一个结点
{
i = link_list[i].cur; //没找到就后移
}
k = link_list[i].cur; //将需要被删除的结点用k指向
link_list[i].cur = link_list[k].cur; //将需要被删除的结点的前一个结点指向需要被删除的结点的后一个结点
link_list[k].cur = link_list[0].cur; //将需要被删除的结点指向备用头结点的第一个结点
link_list[0].cur = k; //将备用头结点指向需要被删除的结点
printf("\n"); //换行
}
//主函数
int main(void)
{
Plink_list link_list;
int i;
Link_list_initialize(link_list); //初始化静态链表(将所有结点挂在备用头结点上)
Link_list_build(link_list); //静态链表的建立
Link_list_printf(link_list); //静态链表的输出
Link_list_delect(link_list); //静态链表的删除(删除静态链表第i个结点)
Link_list_printf(link_list); //静态链表的输出
return 0;
}
模块一:
初始化静态链表(将所有结点挂在备用头结点上)
void Link_list_initialize(Plink_list link_list) //初始化静态链表(将所有结点挂在备用头结点上)
{
int i;
for (i = 0;i < SIZEMAX;i++) //SIZEMAX - 1个元素依次挂在备用头结点上
{
link_list[i].cur = i + 1; //指向下一个结点
}
link_list[SIZEMAX - 1].cur = NULL; //将尾结点挂起
}
模块二:
分配空闲结点
int Link_list_allot(Plink_list link_list) //分配空闲结点
{
int i = 1;
if (i) //如果有空闲结点
{
i = link_list[0].cur; //分配一个空闲结点给i
link_list[0].cur = link_list[i].cur; //将备用头结点指向被分配的空闲结点的下一个结点
}
if(NULL == i) //如果没有可分配的备用结点
{
printf("没有可分配的空闲结点了,请重新检查程序!\n"); //提醒用户
exit(0); //正常终止程序
}
return i; //返回当前被分配的空闲结点
}
模块三:
建立静态链表
void Link_list_build(Plink_list link_list) //建立静态链表
{
int len, i, k, c, val;
printf("输入要建立静态链表结点的个数(0 - 8):"); //显示提醒用户输入个数
scanf_s("%d", &len); //记录个数
while ((SIZEMAX - 2) < len || len <= 0) //判断输入长度值是否合法(因为有两个是头结点所以只能开辟八个)
{
printf("个数非法,重新输入结点个数(10 >= x > 0):"); //提示用户
scanf_s("%d", &len); //用户输入个数
}
i = Link_list_allot(link_list); //开辟有效结点的头结点
c = i; //该游标永远指向尾结点
for (k = 1;k <= len;k++) //依次开辟用户定义的结点数
{
printf("输入第%d个静态结点的值:", k); //显示提醒用户输入值
scanf_s("%d", &val); //记录值
i = Link_list_allot(link_list); //开辟新结点
link_list[i].data = val; //将数值发送给新结点的数据域
link_list[c].cur = i; //将新结点的前一个结点的游标指向新结点
c = i; //c操作游标指向尾结点
}
link_list[len + 1].cur = NULL; //将有效结点的尾结点挂起
}
模块四:
输出静态链表
void Link_list_printf(Plink_list link_list) //输出静态链表
{
int i = 1;
i = link_list[i].cur;
printf("当前静态链表的数值为:"); //显示数值
while (i) //如果不为尾结点
{
printf("%d ", link_list[i].data); //输出数据值
i = link_list[i].cur; //指向下一个结点
}
printf("\n");
}
模块五:
静态链表的删除(删除静态链表第i个结点)
void Link_list_delect(Plink_list link_list) //静态链表的删除(删除静态链表第i个结点)
{
int whe, i = 1, j, k;
printf("输入需要删除静态链表第几个结点:"); //显示提醒用户输入信息
scanf_s("%d", &whe); //记录信息
while (SIZEMAX < whe || whe <= 0) //判断输入长度值是否合法
{
printf("个数非法,重新输入删除的结点位置(10 >= x > 0):");//提示用户
scanf_s("%d", &whe); //用户输入位置
}
for (j = 1;j < whe;j++) //找到需要删除的结点的前一个结点
{
i = link_list[i].cur; //没找到就后移
}
k = link_list[i].cur; //将需要被删除的结点用k指向
link_list[i].cur = link_list[k].cur; //将需要被删除的结点的前一个结点指向需要被删除的结点的后一个结点
link_list[k].cur = link_list[0].cur; //将需要被删除的结点指向备用头结点的第一个结点
link_list[0].cur = k; //将备用头结点指向需要被删除的结点
printf("\n"); //换行
}
主函数:
//主函数
int main(void)
{
Plink_list link_list;
int i;
Link_list_initialize(link_list); //初始化静态链表(将所有结点挂在备用头结点上)
Link_list_build(link_list); //静态链表的建立
Link_list_printf(link_list); //静态链表的输出
Link_list_delect(link_list); //静态链表的删除(删除静态链表第i个结点)
Link_list_printf(link_list); //静态链表的输出
return 0;
}
认真分析每一步细节,将会有大大的收获qwq吧,不足的地方欢迎指出~
错误总结与分析:
分析:在本程序编写的过程中,没有发现分配结点模块的错误,导致下标溢出且未知,其原因是因为在那个模块中i被默认定义为1,所以会一直执行if判断语句,然后在if里i = NULL,但是后面的判断原先加的是else,因为if执行了,else就始终无法正确运行功能,后面改为对i的判断是否为NULL才正确运行;
总结:因为总容量为10,但是其中有2个是头结点,所以最多用户可以开辟8个结点,而不是10个!
感谢观看
再次感谢~