C/C++两个版本实现单链表

本文详细介绍了一个全面的链表操作集合,包括链表的创建、排序、逆转、删除重复元素及特定值、插入节点等核心功能,并提供了C和C++两个版本的实现代码,适合初学者和开发者快速掌握链表的基本操作。

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

前言

写的时候注意一下C++和C的区别,C++里面new 和重载等在C中是没有的。基本上我能想到的函数都实现了

c语言中不能重载函数的原因

代码功能

功能一览

1.头插法建表
1.1直接读输入建表
1.2从文件中读路径建表
2.尾插法建表 同上
3.链表逆转,提供两种实现方法
4.链表排序,使用插入排序思想
4.1递增
4.2递减
5.输出
5.1正序
5.2逆序
6.删除链表中值为X的结点
7.删除值重复结点
8.删除最值
8.1最大值
8.2最小值
9.插入结点
9.1头插
9.2尾插

c++版

读入路径需要自己输入路径读入数据,写入路径直接初始化默认路径了。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*功能一览
1.头插法建表
	1.1直接读输入建表
	1.2从文件中读路径建表 
2.尾插法建表 
	同上
3.链表逆转,提供两种实现方法 
4.链表排序,使用插入排序思想
	4.1递增
	4.2递减 
5.输出
	5.1正序
	5.2逆序
6.删除链表中值为X的结点
7.删除值重复结点
8.删除最值
	8.1最大值
	8.2最小值
9.插入结点
	9.1头插 
	9.2尾插 
*/
typedef struct node
{
	int val;
	node* next;
}Node,*List;

//文件路径 用于读取 
//G:\\CppCode\\Data Structure\\experiment\\Readtest.txt 
char road[100]="G:\\CppCode\\Data Structure\\experiment\\Readtets2.txt";
FILE* fp;
FILE* wp=fopen("G:\\CppCode\\Data Structure\\experiment\\outPut.txt","w"); 
//尾插法建表 直接读取 
List endCreat()
{
	List H=(Node*)malloc(sizeof(Node));
	Node* q=H;
	Node* t;
	while(1)
	{
		char i=getchar();
		if(i=='\n')break;
		t=(List)malloc(sizeof(Node));
		t->next=NULL;
		t->val=i-'0';
		q->next=t;
		q=t;
	}
	return H;
}
//传路径读取 
List endCreat(FILE *fp)
{
	List H=(Node*)malloc(sizeof(Node));
	Node* q=H;
	Node* t;
	while(1)
	{
		char i=fgetc(fp);
		if(i==EOF)break;
		t=(List)malloc(sizeof(Node));
		t->next=NULL;
		t->val=i-'0';
		q->next=t;
		q=t;
	}
	return H;
}
//从路径里面读文件,这里要传入fp的引用 否则读取不了 
void readRoad(FILE*& fp)
{
	gets(road);
	fp=fopen(road,"r");

}
//往路径里面写文件 
void writeRoad(List& H,FILE*& wp)
{
	Node* p=H->next;
	while(p)
	{
		fputc(p->val+'0',wp);
		p=p->next;
	}
}
//头插法建表 
List frontCreat()
{
	List L=(Node*)malloc(sizeof(Node));
	L->next=NULL;
	Node *t;
	while(1)
	{
		char i=getchar();
		if(i=='\n')break;
		t=(Node*)malloc(sizeof(Node));
		t->val=i-'0';
		t->next=L->next;
		L->next=t;
	}
	return L;
}
//在尾端插入 
void insertEnd(List& H,int x)
{
	Node* p=H;
	while(p->next)
	{
		p=p->next;
	}
	Node* t=(Node*)malloc(sizeof(Node));
	t->val=x;
	t->next=NULL;
	p->next=t;
}
//头结点插入 
void insertStart(List& H,int x)
{
	Node* t=(Node*)malloc(sizeof(Node));
	t->val=x;
	t->next=H->next;
	H->next=t;
}

//传引用修改链表
//口->1->2->3->2->4 
//口->1->3->4
//从头分析 当传入头结点时它不等于任何值,所以传入H->next到下一层递归
//在下一层递归如果等于X,那么修改链表H->next=H->next->next; 
void delX(List& H,int X)
{
	Node* p;
	if(!H)return ;
	if(H->val==X)
	{
		p=H;
		H=H->next;
		free(p);
		delX(H,X);
	}
	else delX(H->next,X);
}
//链表逆转 摘下头结点然后再用前插法建表 
void Reverse(List H)
{
	Node* p=H->next;
	H->next=NULL;
	Node* q=p->next;
	while(p)
	{
		q=p->next;
		p->next=H->next;
		H->next=p;
		p=q;
	}
}
//链表逆转2 新建空节点
//不断取头结点的下一个结点指向新节点
void Reverse2(List& H)
{
	Node* t=NULL;
	Node* p=H->next;
	Node* q=p->next;
	while(p)
	{
		q=p->next;
		p->next=t;
		t=p;
		p=q;
	}
	H->next=t;
} 
void Print(List H)
{
	List p=H->next;
	int i=0;
	while(p)
	{
		printf("%s%d",i==0?"":"->",p->val);
		i=1;
		p=p->next;
	}
	printf("\n");
}
//递归逆序输出链表的值 
void Print_d(List H)
{
	if(H->next)
	{
		Print_d(H->next);
	}
	printf("%d",H->val);
	return;
} 
//按值递增排序链表
void sortListAsc(List& H)
{
	Node* p=H->next;
	Node* t=p->next;
	p->next=NULL;
	p=t;
	Node* r;
	while(p)
	{
		t=p->next;
		r=H;
		while(r->next)
		{
			if(r->next->val>p->val)break;
			r=r->next;
		}
		p->next=r->next;
		r->next=p;
		p=t;
	}
}
//升序排列链表 
void sortListDec(List& H)
{
	Node* p=H->next;
	Node* t=p->next;
	p->next=NULL;
	p=t;
	Node* r;
	while(p)
	{
		t=p->next;
		r=H;
		while(r->next)
		{
			if(r->next->val<p->val)break;
			r=r->next;
		}
		p->next=r->next;
		r->next=p;
		p=t;
	}
}
//删除重复 
void delRepe(List &H)
{
	if(!H->next)return ;
	const int len=1000;
	int book[len];
	memset(book,0,sizeof(int)*len);
	Node* p=H;
	Node* q;
	while(p->next)
	{
		if(book[p->next->val]==0)
		{
			book[p->next->val]=1;
			p=p->next;
		}
		else
		{
			q=p->next;
			p->next=p->next->next;
			free(q);
		}
	}
}
bool delMin(List H)
{
	if(!H->next)return 0;
	Node* p=H;
	Node* q=H;
	int min=H->next->val;
	while(p->next)
	{
		if(p->next->val<min)
		{
			min=p->next->val;
			q=p;
		}
		p=p->next;
	}
	p=q->next;
	q->next=q->next->next;
	free(p);
	return 1;	
}
bool delMax(List H)
{
	if(!H->next)return 0;
	Node* p=H;
	Node* q=H;
	int Max=H->next->val;
	while(p->next)
	{
		if(p->next->val>Max)
		{
			Max=p->next->val;
			q=p;
		}
		p=p->next;
	}
	p=q->next;
	q->next=q->next->next;
	free(p);
	return 1;	
}

int main()
{
	List Head;
	int i=0;
	//G:\\CppCode\\Data Structure\\experiment\\Readtets2.txt 
	printf("请先建表,1输入路径读取,2直接读取:");
	scanf("%d",&i);
	switch(i)
	{
		case 1:
			getchar();
			readRoad(fp);
			Head=endCreat(fp);
			break;
		case 2:
			getchar();
			Head=endCreat();
			break;
	}
	int ch=0;
	int t=0;
	bool end=false;
	while(1)
	{
		if(end)break;
		printf("------menu------\n");
		printf("1.printf\n");
		printf("2.reverse\n");
		printf("3.delX\n");
		printf("4.delMin\n");
		printf("5.delMax\n");
		printf("6.delRepe\n");
		printf("7.insert at end\n");
		printf("8.sort descend\n");
		printf("9.write road\n");
		printf("-1.end\n");
		scanf("%d",&ch);
		switch(ch)
		{
			case 1:
				Print(Head);
				break;
			case 2:
				Reverse(Head);
				Print(Head); 
				break;
			case 3:
				printf("x:");
				scanf("%d",&t);
				delX(Head,t);
				Print(Head); 
				break;
			case 4:
				delMin(Head);
				Print(Head); 
				break;
			case 5:
				delMax(Head);
				Print(Head); 
				break;
			case 6:
				delRepe(Head);
				Print(Head); 
				break;
			case 7:
				printf("x:");
				scanf("%d",&t);
				insertEnd(Head,t);
				Print(Head); 
				break;
			case 8:
				sortListAsc(Head);
				Print(Head); 
				break;
			case 9:
				writeRoad(Head,wp);
				break;
			case -1:
				end=true;
				break;
		}
		if(!Head->next)printf("链表现在为空\n");
		printf("*****************\n");
	}
	return 0;
}

c版本

重命名了重载函数,稍微修改了下读写函数,还有就是好像不支持传指针引用这种写法,直接把引用都去掉了,测试也没问题

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*功能一览
1.头插法建表
	1.1直接读输入建表
	1.2从文件中读路径建表 
2.尾插法建表 
	同上
3.链表逆转,提供两种实现方法 
4.链表排序,使用插入排序思想
	4.1递增
	4.2递减 
5.输出
	5.1正序
	5.2逆序
6.删除链表中值为X的结点
7.删除值重复结点
8.删除最值
	8.1最大值
	8.2最小值
9.插入结点
	9.1头插 
	9.2尾插 
*/
typedef struct node
{
	int val;
	struct node* next;
}Node,*List;

//文件路径 用于读取 
//G:\\CppCode\\Data Structure\\experiment\\Readtest.txt 
char road[100]="G:\\CppCode\\Data Structure\\experiment\\Readtets2.txt";
FILE* fp;
FILE* wp;
//尾插法建表 直接读取 
List endCreat()
{
	List H=(Node*)malloc(sizeof(Node));
	Node* q=H;
	Node* t;
	while(1)
	{
		char i=getchar();
		if(i=='\n')break;
		t=(List)malloc(sizeof(Node));
		t->next=NULL;
		t->val=i-'0';
		q->next=t;
		q=t;
	}
	return H;
}
//传路径读取 
List endCreatRoad(FILE *fp)
{
	List H=(Node*)malloc(sizeof(Node));
	Node* q=H;
	Node* t;
	while(1)
	{
		char i=fgetc(fp);
//		printf("%c\n",i);
		if(i==EOF)break;
		t=(List)malloc(sizeof(Node));
		t->next=NULL;
		t->val=i-'0';
		q->next=t;
		q=t;
	}
	return H;
}
//从路径里面读文件,这里要传入fp的引用 否则读取不了 
FILE* readRoad(FILE* fp)
{
	gets(road);
	fp=fopen(road,"r");
	return fp;
}
//往路径里面写文件 
void writeRoad(List H,FILE* wp)
{
	Node* p=H->next;
	while(p)
	{
		fputc(p->val+'0',wp);
		p=p->next;
	}
}
//头插法建表 
List frontCreat()
{
	List L=(Node*)malloc(sizeof(Node));
	L->next=NULL;
	Node *t;
	while(1)
	{
		char i=getchar();
		if(i=='\n')break;
		t=(Node*)malloc(sizeof(Node));
		t->val=i-'0';
		t->next=L->next;
		L->next=t;
	}
	return L;
}
//在尾端插入 
void insertEnd(List H,int x)
{
	Node* p=H;
	while(p->next)
	{
		p=p->next;
	}
	Node* t=(Node*)malloc(sizeof(Node));
	t->val=x;
	t->next=NULL;
	p->next=t;
}
//头结点插入 
void insertStart(List H,int x)
{
	Node* t=(Node*)malloc(sizeof(Node));
	t->val=x;
	t->next=H->next;
	H->next=t;
}

//传引用修改链表
//口->1->2->3->2->4 
//口->1->3->4
//从头分析 当传入头结点时它不等于任何值,所以传入H->next到下一层递归
//在下一层递归如果等于X,那么修改链表H->next=H->next->next; 
void delX(List H,int X)
{
	Node* p;
	if(!H)return ;
	if(H->val==X)
	{
		p=H;
		H=H->next;
		free(p);
		delX(H,X);
	}
	else delX(H->next,X);
}
//链表逆转 摘下头结点然后再用前插法建表 
void Reverse(List H)
{
	Node* p=H->next;
	H->next=NULL;
	Node* q=p->next;
	while(p)
	{
		q=p->next;
		p->next=H->next;
		H->next=p;
		p=q;
	}
}
//链表逆转2 新建空节点
//不断取头结点的下一个结点指向新节点
void Reverse2(List H)
{
	Node* t=NULL;
	Node* p=H->next;
	Node* q=p->next;
	while(p)
	{
		q=p->next;
		p->next=t;
		t=p;
		p=q;
	}
	H->next=t;
} 
void Print(List H)
{
	List p=H->next;
	int i=0;
	while(p)
	{
		printf("%s%d",i==0?"":"->",p->val);
		i=1;
		p=p->next;
	}
	printf("\n");
}
//递归逆序输出链表的值 
void Print_d(List H)
{
	if(H->next)
	{
		Print_d(H->next);
	}
	printf("%d",H->val);
	return;
} 
//按值递增排序链表
void sortListAsc(List H)
{
	Node* p=H->next;
	Node* t=p->next;
	p->next=NULL;
	p=t;
	Node* r;
	while(p)
	{
		t=p->next;
		r=H;
		while(r->next)
		{
			if(r->next->val>p->val)break;
			r=r->next;
		}
		p->next=r->next;
		r->next=p;
		p=t;
	}
}
//升序排列链表 
void sortListDec(List H)
{
	Node* p=H->next;
	Node* t=p->next;
	p->next=NULL;
	p=t;
	Node* r;
	while(p)
	{
		t=p->next;
		r=H;
		while(r->next)
		{
			if(r->next->val<p->val)break;
			r=r->next;
		}
		p->next=r->next;
		r->next=p;
		p=t;
	}
}
//删除重复 
void delRepe(List H)
{
	if(!H->next)return ;
	const int len=1000;
	int book[len];
	memset(book,0,sizeof(int)*len);
	Node* p=H;
	Node* q;
	while(p->next)
	{
		if(book[p->next->val]==0)
		{
			book[p->next->val]=1;
			p=p->next;
		}
		else
		{
			q=p->next;
			p->next=p->next->next;
			free(q);
		}
	}
}
int delMin(List H)
{
	if(!H->next)return 0;
	Node* p=H;
	Node* q=H;
	int min=H->next->val;
	while(p->next)
	{
		if(p->next->val<min)
		{
			min=p->next->val;
			q=p;
		}
		p=p->next;
	}
	p=q->next;
	q->next=q->next->next;
	free(p);
	return 1;	
}
int delMax(List H)
{
	if(!H->next)return 0;
	Node* p=H;
	Node* q=H;
	int Max=H->next->val;
	while(p->next)
	{
		if(p->next->val>Max)
		{
			Max=p->next->val;
			q=p;
		}
		p=p->next;
	}
	p=q->next;
	q->next=q->next->next;
	free(p);
	return 1;	
}

int main()
{
	wp=fopen("G:\\CppCode\\Data Structure\\experiment\\outPut.txt","w"); 
	List Head;
	int i=0;
	//G:\\CppCode\\Data Structure\\experiment\\Readtets2.txt 
	printf("请先建表,1输入路径读取,2直接读取:");
	scanf("%d",&i);
	switch(i)
	{
		case 1:
			getchar();
			fp=readRoad(fp);
			Head=endCreatRoad(fp);
			break;
		case 2:
			getchar();
			Head=endCreat();
			break;
	}
	int ch=0;
	int t=0;
	int end=0;
	while(1)
	{
		if(end)break;
		printf("------menu------\n");
		printf("1.printf\n");
		printf("2.reverse\n");
		printf("3.delX\n");
		printf("4.delMin\n");
		printf("5.delMax\n");
		printf("6.delRepe\n");
		printf("7.insert at end\n");
		printf("8.sort descend\n");
		printf("9.write road\n");
		printf("-1.end\n");
		scanf("%d",&ch);
		switch(ch)
		{
			case 1:
				Print(Head);
				break;
			case 2:
				Reverse(Head);
				Print(Head); 
				break;
			case 3:
				printf("x:");
				scanf("%d",&t);
				delX(Head,t);
				Print(Head); 
				break;
			case 4:
				delMin(Head);
				Print(Head); 
				break;
			case 5:
				delMax(Head);
				Print(Head); 
				break;
			case 6:
				delRepe(Head);
				Print(Head); 
				break;
			case 7:
				printf("x:");
				scanf("%d",&t);
				insertEnd(Head,t);
				Print(Head); 
				break;
			case 8:
				sortListAsc(Head);
				Print(Head); 
				break;
			case 9:
				writeRoad(Head,wp);
				break;
			case -1:
				end=1;
				break;
		}
		if(!Head->next)printf("链表现在为空\n");
		printf("*****************\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值