单链表插入删除元素

单链表,实验内容

(1)分别建立4个元素的线性表L={2,3,4,5}

(2)在L={2,3,4,5}的元素4与5之间插入一个元素9,实现表插入的基本操作,

(3)在L={2,3,4,9,5}中删除指定位置(i=3)上的元素,实现表删除的操作。

常见错误:

  1. 类型定义错误 :应该使用 LinkList 类型,它是链表定义的类型。

  2. 变量未声明 :在 ListInsert_LListDelete_L 函数中,使用 js 变量要声明。

  3. 函数参数类型不匹配ListPrint 函数的参数应该是 LinkList 而不是 LinkList &,因为不需要修改传入的链表头指针。

  4. 引用传递问题 :在 main 函数中,应该首先创建一个链表的头节点,并将其 next 指针设置为 NULL

  5. ElemType 传递方式 :在 GetElem_L 函数中,不能使用 ElemType &e,这在 C 语言中是不合法的。C 语言不支持引用传递,应该使用指针。

  6. 代码风格 :在 C 语言中,通常不使用 & 符号来引用结构体成员,除非是在定义结构体指针。

调试遇到的问题及分析解决方法

  1. 问题 :在 GetElem_L 函数中,循环条件 while(p&&j<1) 永远不会执行,因为 j 初始化为 1,而条件是 j<1
    • 解决方法 :将循环条件改为 while(p && j < i),确保在找到第 i 个元素之前循环继续执行。
  2. 问题 :在 ListInsert_L 函数中,当 i 等于链表长度加 1 时,应该能够成功插入新元素到链表末尾,但原代码中的 if(!p||j>i-1) 阻止了这种情况。
    • 解决方法 :将条件改为 if(!p || j != i-1),这样当 p 为空或 j 不等于 i-1 时才返回错误。
  3. 问题 :在 ListDelete_L 函数中,当 i 等于链表长度时,应该返回错误,因为不存在第 i 个元素。但原代码中的条件 if(!(p->next)||j>i-1) 允许 i 等于链表长度时执行删除操作(尽管实际上不会删除任何元素,因为 p->next 为空)。
    • 解决方法 :虽然这个特定情况可能不会导致错误(因为 p->next 为空时不会执行删除操作),但为了代码的清晰性和一致性,可以保留这个条件检查,或者更明确地处理这种情况。
  4. 问题 :在 main 函数中,插入元素时索引从 1 开始,但链表长度是 0(因为只有一个头结点且其 next 为空),所以第一个元素应该插入到位置 1 而不是 0。
    • 解决方法 :这个问题实际上在代码中已经正确处理了,因为插入函数 ListInsert_L 的索引是从 1 开始的。
  5. 代码风格 :使用 ElemType &e 作为函数参数时,需要注意在函数内部直接通过 e 赋值,而在调用时不需要额外的 & 符号(除非是在需要指针的场景下)。
    • 解决方法 :在 ListDelete_LGetElem_L 函数中,使用 ElemType &e 是正确的,因为这样可以避免不必要的内存分配和复制操作。在调用这些函数时,直接传递变量名即可。
cs 复制代码
#define ERROR 0
#define OK 1
#define OVERFLOW -2

#include <stdio.h>   
#include <stdlib.h> //引入stdlib.h以使用malloc和realloc 

typedef int ElemType;  //定义ElemType为数据元素类型 
typedef int Status; //Status是变量的类型,其值是函数结果状态代码 

typedef struct LNode{
	ElemType data; //结点值 
	struct LNode *next; //连接下一个结点的地址 
}LNode,*LinkList; //数据域,指针域 

Status GetElem_L(LinkList L,int i,ElemType &e){
//这里用ElemType &e则下面用 e=p->data;若为*e则下面也要*e 
	//L为带头结点的单链表的头指针 
	//当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR 
	LNode *p=L->next; 
	int j=1; //初始化,p指向第一个结点,j为计数器 
	while(p&&j<i){ //顺时针向后查找,直到p指向第i个元素或p为空 
		p=p->next; 
		++j;
	}
	if(!p||j>1)return ERROR; //第i个元素不存在 
    e=p->data; //取第i个元素 
    return OK;
}//GetElem_L

Status ListInsert_L(LinkList *L,int i,ElemType e){
    //存疑,这里用 LinkList *L,则下面用LNode *p=*L而非p=L ,同时定义*s 
	//在带头结点的单链线性表L中第i个位置之前插入元素e 
	LNode *p=*L,*s;
	int j=0;
	while(p&&j<i-1){ 
    	p=p->next;
    	++j;	
		} //寻找第i-1个结点 
	if(!p||j>i-1)return ERROR; //i<1或者大于表长+1 
	s=(LinkList)malloc(sizeof(LNode)); //生成新节点 
	s->data=e;
	s->next=p->next; //插入L中 
	p->next=s;
	return OK;
}//ListInsert_L

Status ListDelete_L(LinkList *L,int i,ElemType &e){ //同上 
	//在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 
	LNode *p=*L,*q;
	int j=0;
	while(p->next&&j<i-1){ //寻找第i个结点,并令p指向其前驱 
		p=p->next;++j;
	}
	if(!(p->next)||j>i-1)return ERROR; //删除位置不合理 
	q=p->next; 
	p->next=q->next; //删除并释放结点 
	e=q->data; free(q);
	return OK;
}//ListDelete_L

void ListPrint(LinkList L){
	LNode *temp=L->next; //从头结点的下一个结点开始打印 
	while(temp!=NULL){
		printf("%d ",temp->data);
		temp=temp->next;
	} 
    printf("\n");
}

int main() {  
    LinkList L=(LinkList)malloc(sizeof(LNode)); //创建头结点
	if(!L) return -1; //内存分配失败
	L->next=NULL; //初始化头结点的next指针 
	
    ElemType e;  
  
    // 插入元素建立线性表L={2,3,4,5}  
    for (int i = 1; i <= 4; i++) {  
        ListInsert_L(&L, i, i + 1);  
    }  
  
    // 打印线性表L  
    printf("线性表L={");  
    ListPrint(L);  
  
    // 在L={2,3,4,5}的元素4与5之间插入一个元素9  
    ListInsert_L(&L, 4, 9);  
  
    // 打印插入后的线性表L  
    printf("插入9后,线性表L={");  
    ListPrint(L);  
  
    // 在L={2,3,4,9,5}中删除指定位置(i=3)上的元素  
    if (ListDelete_L(&L, 3, e)) { 
    //ListDelete_Sq里用ElemType *e时这里要用&e,若用ElemType &e时这里用e 
        printf("删除位置i=3的元素,其值为%d\n", e);  //删除位置i从1,2,3数起 
    } else {  
        printf("删除失败\n");  
    }  
  
    // 打印删除后的线性表L  
    printf("删除后,线性表L={");  
    ListPrint(L);  
  
    return 0;  
}
相关推荐
指针满天飞4 分钟前
Collections.synchronizedList是如何将List变为线程安全的
java·数据结构·list
CoovallyAIHub13 分钟前
方案 | 动车底部零部件检测实时流水线检测算法改进
深度学习·算法·计算机视觉
CoovallyAIHub15 分钟前
方案 | 光伏清洁机器人系统详细技术实施方案
深度学习·算法·计算机视觉
Dm_dotnet17 分钟前
Stylet启动机制详解:从Bootstrap到View显示
c#
lxmyzzs19 分钟前
【图像算法 - 14】精准识别路面墙体裂缝:基于YOLO12与OpenCV的实例分割智能检测实战(附完整代码)
人工智能·opencv·算法·计算机视觉·裂缝检测·yolo12
洋曼巴-young21 分钟前
240. 搜索二维矩阵 II
数据结构·算法·矩阵
丑小鸭是白天鹅35 分钟前
嵌入式C语言学习笔记之枚举、联合体
c语言·笔记·学习
GUET_一路向前1 小时前
【C语言防御性编程】if条件常量在前,变量在后
c语言·开发语言·if-else·防御性编程
楼田莉子2 小时前
C++算法题目分享:二叉搜索树相关的习题
数据结构·c++·学习·算法·leetcode·面试
三千道应用题2 小时前
WPF&C#超市管理系统(6)订单详情、顾客注册、商品销售排行查询和库存提示、LiveChat报表
开发语言·c#·wpf