严蔚敏C语言版的删除操作
/*
严蔚敏数据结构C语言版 P30 算法2.10
在带头结点的单链线性表L中,删除第i个元素
*/
//头文件
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
//结构
typedef struct LIST //该链表的结构
{
int data; //该单链表的数据域
struct LIST *NEXT; //该链表的指针域
}SQlist, *PList;
//函数声明
PList List_initialize(void); //初始化单链表,并返回头指针
void List_the_assignment(PList); //用户自定义要开辟的结点数并赋予每个结点数据
void List_output(PList); //单链表的输出
void List_drop(PList); //在带头结点的单链线性表L中,删除第i个元素
//函数区
PList List_initialize(void) //初始化单链表
{
PList PHead = NULL; //挂起头指针
PHead = (PList)malloc(sizeof(SQlist)); //开辟头结点,并用头指针指向
if (NULL == PHead) //如果分配失败
{
printf("初始化头结点失败,检查程序!\n"); //显示错误位置,方便检查
exit(1); //非正常终止程序
}
PHead->NEXT = NULL; //挂起头结点的指针域
return PHead; //返回头指针
}
void List_the_assignment(PList PHead) //用户自定义要开辟的结点数并赋予每个结点数据
{
PList PTail = NULL; //用于操作链表的指针
PList PNew = NULL; //用于开辟新结点的指针
int i, len, val;
printf("输入要开辟的结点个数:");
scanf_s("%d", &len); //输入要开辟的个数
PTail = PHead; //将头指针赋给PTail,注意不能写成PTail = PHead->NEXT,因为PHead->NEXT为NULL
for (i = 1;i <= len;i++) //建立链表
{
printf("输入第%d个结点的值:", i);
scanf_s("%d", &val); //依次输入各个结点的值
PNew = (PList)malloc(sizeof(SQlist)); //开辟新结点
if (NULL == PNew) //如果分配失败
{
printf("初始化赋值时,建立新结点失败,检查程序!\n"); //显示错误位置,方便检查
exit(1); //非正常终止程序
}
PNew->data = val; //使新结点的数据域赋值
PNew->NEXT = NULL; //使新结点的指针域挂起
PTail->NEXT = PNew; //将新结点挂在前一个结点
PTail = PNew; //使PTail指向下一个元素
}
}
void List_output(PList PHead) //单链表的输出
{
PList PTail = NULL; //用于操作链表的指针
PTail = PHead->NEXT; //将第一个结点的位置赋给PTail
printf("\n当前链表的值为:");
while (NULL != PTail) //当前结点不为空
{
printf("%d ", PTail->data); //输出当前结点的数据域
PTail = PTail->NEXT; //使PTail指向下一个结点
}
printf("\n");
}
void List_drop(PList PHead) //在带头结点的单链线性表L中,删除第i个元素
{
PList PTail = NULL; //用于操作链表的指针
PList PTail_drop = NULL; //用于操作链表的指针
int i, j = 0;
printf("输入删除第几个元素:");
scanf_s("%d", &i);
PTail = PHead; //将头指针的权限赋给PTail
while (PTail->NEXT && j < i - 1) //只要当前结点不为空与没有到需要删除结点的前一个位置
{
PTail = PTail->NEXT; //指向下一个结点
j++; //记录
}
if (NULL == PTail->NEXT || j > i || i < 0) //如果删除的位置非法
{
printf("输入删除的位置有误,请重新输入!\n"); //显示信息
exit(0); //正常终止程序
}
PTail_drop = PTail->NEXT; //将当前需要删除的结点用PTail_drop指向
PTail->NEXT = PTail_drop->NEXT; //将当前需要删除的结点的下一个结点挂在当前需要删除的结点的前一个结点
free(PTail_drop); //释放当前需要删除的结点
}
//主函数
int main(void)
{
PList PHead = NULL; //使主函数的头指针挂起
PHead = List_initialize(); //初始化单链表,并把返回的头指针给主函数的头指针
List_the_assignment(PHead); //用户自定义要开辟的结点数并赋予每个结点数据
List_output(PHead); //单链表的输出
List_drop(PHead); //在带头结点的单链线性表L中,删除第i个元素
List_output(PHead); //单链表的输出
return 0;
}
总结:在敲本程序时,在建立赋值时,犯了严重的错误,将头结点的指针域为NULL时,将临时操作指针的指针域存放了头结点的指针域的地址,导致临时操作结点的值无法挂在头结点上。
结论:细微的思想建模需要考虑实际的存储和数据,不然代码跟着思想跑容易出错,且不可敲完在调试,完成一项功能要进行假设错误的处理提醒,方便找出错误所在!
感谢观看
非常感谢~