C语言单链表的实现

本文详细介绍了单链表的各种操作,包括逆向和正序创建、遍历、取值、插入、删除及查询等核心功能,并提供了完整的C++实现代码。

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

#include <iostream>
#include <stdlib.h>
#include <windows.h>

//定义单链表的结构体存储数据类型
typedef struct LNode{
	int elem;
	struct LNode *next;//指针域
}LNode,*LinkedList;

//定义逆向创建并初始化单链表函数
void reverseCreateList(LinkedList &L,int n){//n为初始化单链表的填充数据个数

	L = (LinkedList)malloc(sizeof(LNode));
	L->next = NULL;//初始化头结点

	for(int i=n;i>0;i--){
		LNode *p = (LNode*)malloc(sizeof(LNode));//生成新结点
		printf("请输入第%d个结点的值:",i);
		scanf("%d",&p->elem);

		p->next = L->next;
		L->next = p;//新结点插入到表头
	}
}

//定义正序创建并初始化单链表函数
void positiveCreateList(LinkedList &L,int n){

	L = (LinkedList)malloc(sizeof(LNode));
	L->next = NULL;

	LNode *rear = L;//定义一个尾指针指向头指针L
	for(int i=0;i<n;i++){
		LNode *p = (LNode*)malloc(sizeof(LNode));//生成新结点
		printf("请输入第%d个结点的值:",i+1);
		scanf("%d",&p->elem);
		p->next = NULL;//指针p的next域置为NULL

		rear->next = p;//rear指针指向当前单链表的末尾结点,此操作修改末尾结点的指针域,使其指向新结点,建立联系
		rear = p;//将新结点加入单链表后,末尾结点则为新结点,改变尾指针指向
	}
}

//定义遍历单链表函数
void traverseList(LinkedList L){
	
	LNode *p = L->next;//指针p指向首元结点
	int i = 0;//i用于表示结点的位置

	printf("==================\n");
	while(p != NULL){
		i++;
		printf("第%d个结点的值:%d\n",i,p->elem);
		p = p->next;//指针p指向下一结点
	}
	printf("==================\n");
	
}

//定义单链表取指定位置数据元素值函数
bool getValue(LinkedList L,int i,int &e){
	LNode *p = L->next;
	int j = 1;//j变量用于计数器

	while(p != NULL && j<i){
		p = p->next;
		j++;
	}

	if(p == NULL ||  j>i){//当i值为0时,出现j>i;当i>单链表表长时出现p为空
		return false;
	}
	e = p->elem;
	return true;
}

//定义单链表插入数据元素函数
bool insertElemList(LinkedList &L,int i,int e){//之所以使用&L,是因为当i为1时,需改变头指针指向
	LNode *p = L;
	int j = 0;

	while(p !=NULL && j<i-1){
		p = p->next;
		j++;
	}//使p指针指向插入位置i的前驱结点

	if(p == NULL || j>i-1){//当i为0时,出现j>i-1;当i>单链表表长+1时,出现p为NULL
		return false;
	}

	LNode *q = (LNode*)malloc(sizeof(LNode));//生成新结点
	q->elem = e;
	q->next = p->next;
	p->next = q;//顺序不可颠倒

	return true;
}

//定义单链表删除数据元素函数
bool deleteElemList(LinkedList &L,int i,int &e){
	LNode *p = L;
	int j = 0;

	while(p->next != NULL && j<i-1){//之所以使用p->next而不是用p,是为了检测将要删除的位置i的结点是否为空,
		//如果此处使用p,则会导致下面q->next语法错误

		p = p->next;
		j++;
	}

	if(p->next == NULL || j>i-1){
		return false;
	}
	LNode *q = p->next;//定义指针q指向将要被删除结点
	p->next = q->next;
	e = q->elem;
	free(q);//释放q所指的内存空间

	return true;
}

//定义单链表查询指定数据所在结点位置函数
int inquireValue(LinkedList L,int e){
	LNode *p = L->next;//p指针指向单链表的首元结点
	int j = 1;//j为计数器

	while(p != NULL){
		if(p->elem == e){
			return j;
		}else{
			p = p->next;
			j++;
		}
	}

	return 0;//返回值0表示没找到e
}

//定义打印单链表功能菜单函数
void functionMenu(void){
	char *menu[] = {
		"1_逆向创建并初始化单链表操作","2_正序创建并初始化单链表操作",
		"3_遍历单链表操作","4_单链表取指定位置数据元素值操作",
		"5_单链表插入数据元素操作","6_单链表删除数据元素操作",
		"7_单链表查询指定数据所在结点位置操作"
	};

	printf("================================\n");
	for(int i=0;i<sizeof(menu)/sizeof(char*);i++){
		printf("%s\n",menu[i]);
	}
	printf("================================\n");

}

//定义单链表操作函数
void operateList(LinkedList &L){

	int funNo = 0;//功能编号
	int n = 0;//创建单链表初始填入的数据个数
	int e = 0;//接收删除数据元素值或查询的数值
	int i = 0;//插入或删除的位置
	bool flag = true;

	while(flag){
		functionMenu( );

		printf("请输入将要执行操作对应的功能编号:");
		scanf("%d",&funNo);

		switch(funNo){
			case 1:
				printf("请输入初始填充的数据个数n:");
				scanf("%d",&n);
				reverseCreateList(L,n);
				break;
			case 2:
				printf("请输入初始填充的数据个数n:");
				scanf("%d",&n);
				positiveCreateList(L,n);
				break;
			case 3:
				traverseList(L);
				break;
			case 4:
				printf("请输入取值位置i:");
				scanf("%d",&i);
				if(getValue(L,i,e)){
					printf("第%d个结点的值:%d\n",i,e);
				}else{
					printf("取值操作失败\n");
				}
				break;
			case 5:
				printf("请输入插入数据元素的位置i:");
				scanf("%d",&i);
				printf("请输入插入的数值e:");
				scanf("%d",&e);
				if(insertElemList(L,i,e)){
					printf("插入数据元素操作成功\n");
				}else{
					printf("插入数据元素操作失败\n");
				}
				break;
			case 6:
				printf("请输入删除数据元素的位置i:");
				scanf("%d",&i);
				if(deleteElemList(L,i,e)){
					printf("删除数据元素%d操作成功\n",e);
				}else{
					printf("删除数据元素操作失败\n");
				}
				break;
			case 7:
				printf("请输入查询的数值e:");
				scanf("%d",&e);
				i= inquireValue(L,e);
				if(i != 0){
					printf("数值e:%d在单链表的第%d个结点处\n",e,i);
				}else{
					printf("没有查询到e\n");
				}
				break;
			default:
				printf("输入的funNo错误\n");
				break;
		}

		printf("是否继续执行其他操作? 1-是  0-否:");
		std::cin>>flag;

		system("cls");//清屏
	}
}

int main(void){

	LinkedList L = NULL;//定义头指针L
	operateList(L);

	system("pause");
	return 0;
}

[注意:函数之间的顺序不可以颠倒,我没有在一些函数中加上其调用函数的声明,如果改变顺序的话,可能会报错]

//如有不足,畅所欲言,谢谢点评

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值