编程实现单向链表的基本操作

该程序实现了单向链表的五种基本操作:插入元素、删除元素、获取第i个元素、判断元素是否存在以及获取某个元素的下一个元素。通过结构体存储数据,动态内存分配创建节点,并提供了相应的操作函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

编程实现单向链表的基本操作的实现包含1.插入元素2.删除元素3.获取第i个结点的数据元素4.判断元素是否存在5.获取某个元素的下一个元素


1.编程实现单向链表的基本操作

代码如下(示例):

//Author:北硝   Date:2023.3.29
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>

//本程序主要功能说明:
// 单链表(带头结点)基本操作实现 
// 1.插入结点  2.删除结点  3.获取i元素  4.判断元素是否存在 5.获取某个元素的下一个元素


//程序返回结构 定义 1成功 0失败
#define Status int
#define OK  1
#define ERROR  0 
#define OVERFLOW -2 //申请不到内存时 用-2表示


//自定义的数据元素,
typedef struct {
	char name[10]; //假设暂时只用姓名和手机号
	char phone[20]; //假设暂时只用姓名和手机号
} ElemType;

//单链表 结点定义
typedef struct LNode {
	ElemType data;
	struct LNode* next;
}LNode, * LinkList;


//基本操作1:插入结点
Status ListInsert_L(LinkList L, int i, ElemType e) {

	LNode *p = L;//先把头指针复制出来 
	int j = 0;
	while (p && j < i - 1) {
		p = p->next;
		++j;
	} //寻找到要插入位置的前一个结点

	if (!p || j > i - 1) {
		return ERROR;
	}

	//开辟新结点
	LNode* s = (LinkList)malloc(sizeof(LNode));
	if (s == NULL) {
		exit(OVERFLOW);
	}
	s->data = e;
	s->next = p->next;
	p->next = s; //注意这两句的顺序;
	return OK;
}


//基本操作2:删除结点
Status ListDelete_L(LinkList L, int i) {
	LNode* p = L;
	int j = 0;
	while (p->next && j < i - 1) {
		p = p->next;
		++j;
	}//p指向要删除位置的前一个结点

	//如果最后一个结点都不是你要找的结点的前一个结点

	if (!(p->next) || j > i - 1) {
		return ERROR;
	}

	LNode* q = p->next;//q此时指向要删除的结点
	p->next = q->next;
	free(q); //最后释放掉该结点的内存
	return OK;
}

//基本操作3:获取第i个结点
Status GetElem_L(LinkList L, int i, ElemType* e) {

	LNode* p = L->next;//指向了第一个数据元素
	int j = 1;
	while (p && j < i) {
		p = p->next;
		++j;
	}

	//p为NULL 表示是 把结点遍历完了
	//j=i 表示到了要获取的位置
	//此时p也指向了第i个元素
	if (!p || j > i) {
		return ERROR; //遍历完不存在第i个元素
	}

	*e = p->data;
	return OK;
}


int ElemIsEqual(ElemType e1, ElemType e2);
//基本操作4:单向链表 判断元素e是否存在 
// 存在时,返回下标位置
// 不存在时,返回0
int LocateElem_L(LinkList L, ElemType e) {

	ElemType temp_e;//接收遍历时候的元素
	LNode* p = L->next;//指向了第一个数据元素
	int j = 1; //表示当前处理的序号

	//遍历一遍L,依次比较
	while (p) {
		temp_e = p->data;
		if (ElemIsEqual(temp_e, e)) {
			return j; //直接返回序号
		}
		p = p->next;
		j++;
	}
	
	//遍历完还没有找到就返回 0
	return 0;
}
//基本操作5:获取某个元素的下一个元素
Status NextElem(LinkList L, int cur_e, ElemType* next_e) {

	LNode* p = L->next;//指向了第一个数据元素
	int j = 1;
	while (p && j < cur_e + 1) {
		p = p->next;
		++j;
	}

	//p为NULL 表示是 把结点遍历完了
	//j=i 表示到了要获取的位置
	//此时p也指向了第i个元素
	if (!p || j > cur_e + 1) {
		return ERROR; //遍历完不存在第i个元素
	}

	*next_e = p->data;
	return OK;
}




//
// 以下几个函数是自定义的, 用于打印数据元素和界面的,不属于线性表的基本操作

//功能:打印某个数据元素
void pintElem(ElemType e) {
	printf("{%s, %s}\r\n", e.name, e.phone);
}

//功能:遍历打印一下当前的单向链表:
void printList(LinkList L) {
	
	LNode* p = L->next;//p先指向第一个数据结点
	if (L->next == NULL) {
		return;//为空时可以不用展示
	}
	printf("当前单向链表所有元素为:\r\n");

	while (p) {
		//打印每一个数据元素
		pintElem(p->data);
		p = p->next;
	}
	printf("\r\n\n");//打印完 跟后面内容最好分隔开
}

//功能:打印主界面菜单
void printMenu(void) {
	printf("\t\t*****单向链表的基本操作语句实现*****\r\n");
	printf("\t\t*********** 1. 插入元素e ***********\r\n");
	printf("\t\t*********** 2. 删除第i个元素 ***********\r\n");
	printf("\t\t*********** 3. 获取第i个元素 ***********\r\n");
	printf("\t\t*********** 4. 判断元素e是否存在 ***********\r\n");
	printf("\t\t*********** 5. 获取某个元素的下一个元素 ***********\r\n");

}

//从控制台输入获取某个元素e
void getElemFormConsole(ElemType* e) {
	printf("请输入姓名 手机号(回车表示结束):\r\n");
	scanf_s("%s", e->name, 20);
	scanf_s("%s", e->phone, 20);
}

//判断两个元素是否相等:
//相等返回1  不相等返回0
int ElemIsEqual(ElemType e1, ElemType e2) {
	if (strcmp(e1.name, e2.name) == 0 &&
		strcmp(e1.phone, e2.phone) == 0) {
		return 1;
	}
	return 0;
}


//菜单的功能1:插入:
//就是从控制台接收要插入的位置i 和 元素e  并调用基本功能插入
void FunctionNo1(LinkList L) {
	ElemType e;//用于接收要插入的元素e
	int i;//用于接收要插入的位置

	system("cls");//清屏

	printf("请输入要插入的位置(回车表示结束):\r\n");
	scanf_s("%d", &i, 5);

	getElemFormConsole(&e);

	//调用基本操作语句 插入
	int result = ListInsert_L(L, i, e);
	if (result != OK) {
		printf("插入操作失败!");
		system("pause");
	}
}

//菜单的功能2:删除:
//就是从控制台接收要删除的位置i 并调用基本功能删除
void FunctionNo2(LinkList L) {
	int i;//用于接收要删除的位置

	system("cls");//清屏

	printf("请输入要删除的位置(回车表示结束):\r\n");
	scanf_s("%d", &i, 5);

	//调用基本操作语句 删除
	int result = ListDelete_L(L, i);
	if (result != OK) {
		printf("删除操作失败!");
		system("pause");
	}
}

//菜单的功能3:获取第i个元素
//就是从控制台接收要 查询的序号, 并调用基本功能获取第i元素
void FunctionNo3(LinkList L) {
	int i;//用于接收要查询的序号
	ElemType e;//用于接收查询到的元素

	system("cls");//清屏

	printf("请输入要查询的位置(回车表示结束):\r\n");
	scanf_s("%d", &i, 5);

	//调用基本操作语句 获取第i元素
	int result = GetElem_L(L, i, &e);
	if (result != OK) {
		printf("查询操作失败!");
		system("pause");
		return;
	}

	//查出来打印一下
	printf("\r\n查询出来的第 %d 个元素为:", i);
	pintElem(e);
	system("pause");//暂停一下 让用户能看到查询的结果,再下一步
}



//菜单的功能4:判断元素e是否存在
//就是从控制台接收要 查询的元素,并调用基本功能判断是否存在
void FunctionNo4(LinkList L) {
	ElemType e;//用于接收要查询的元素e

	system("cls");//清屏

	//接收要查询的元素e
	getElemFormConsole(&e);

	//调用基本操作语句 LocateElem_L
	int result = LocateElem_L(L, e);
	if (!result) {
		//不存在
		printf("所找的元素e 不存在!");
	}
	else {
		printf("所找的元素e 存在! 位置是第%d个", result);
	}
	system("pause");
}
//菜单的功能5:获取某个元素的下一个元素
//就是从控制台接收要 查询的序号, 并调用基本功能获取某个元素的下一个元素
void FunctionNo5(LinkList L) {
	int i;//用于接收要查询的序号
	ElemType e;//用于接收查询到的元素

	system("cls");//清屏

	printf("请输入要查询的位置(回车表示结束):\r\n");
	scanf_s("%d", &i, 5);

	//调用基本操作语句 获取第i元素
	int result = NextElem(L, i, &e);
	if (result != OK) {
		printf("查询操作失败!");
		system("pause");
		return;
	}

	//查出来打印一下
	printf("\r\n查询出来的第 %d 个元素为:", i + 1);
	pintElem(e);
	system("pause");//暂停一下 让用户能看到查询的结果,再下一步
}

//自定义几个功能代码
#define FUNCTION01 1
#define FUNCTION02 2
#define FUNCTION03 3
#define FUNCTION04 4
#define FUNCTION05 5

void main() {

	LinkList L; //只是定义了一个头指针
	int selectFun = 0;

	//先创建一个头结点,头结点用户不用感知
	//开辟一个新结点:作为头结点
	LNode* s = (LinkList)malloc(sizeof(LNode));
	if (s == NULL) {
		exit(OVERFLOW);
	}
	s->next = NULL;
	//s->data 不用处理。 不用它
	L = s; //头指针 指向头结点


	while (1) {
		system("cls");//清屏
		printList(L);//先展示一下当前的表内容
		printMenu();//展示一下 主菜单
		printf("请输入你的选择:(回车表示结束)\r\n");
		scanf_s("%d", &selectFun, 5);
		switch (selectFun) {
		case FUNCTION01:
			//选择功能1时
			FunctionNo1(L);
			break;
		case FUNCTION02:
			//选择功能2时
			FunctionNo2(L);
			break;
		case FUNCTION03:
			//选择功能3时
			FunctionNo3(L);
			break;
		case FUNCTION04:
			//选择功能4时
			FunctionNo4(L);
			break;
		case FUNCTION05:
			//选择功能5时
			FunctionNo5(L);
			break;
		default:;
		}
	}
}

总结

编程实现单向链表的五个基本操作的实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北硝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值