单链表插入删除元素

单链表,实验内容

(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;  
}
相关推荐
莹莹学编程—成长记1 小时前
string的模拟实现
服务器·c++·算法
ShiinaMashirol6 小时前
代码随想录打卡|Day27(合并区间、单调递增的数字、监控二叉树)
java·算法
程序设计实验室7 小时前
一次小而美的重构:使用 C# 在 Avalonia 中生成真正好看的词云
c#
梁下轻语的秋缘7 小时前
每日c/c++题 备战蓝桥杯(P1049 [NOIP 2001 普及组] 装箱问题)
c语言·c++·学习·蓝桥杯
加点油。。。。7 小时前
C语言高频面试题——指针函数和函数指针的区别
c语言·面试
电商api接口开发8 小时前
ASP.NET MVC 入门指南二
前端·c#·html·mvc
wuqingshun3141598 小时前
蓝桥杯 5. 交换瓶子
数据结构·c++·算法·职场和发展·蓝桥杯
Demons_kirit8 小时前
Leetcode 2845 题解
算法·leetcode·职场和发展
adam_life8 小时前
http://noi.openjudge.cn/——2.5基本算法之搜索——200:Solitaire
算法·宽搜·布局唯一码
我想进大厂9 小时前
图论---朴素Prim(稠密图)
数据结构·c++·算法·图论