线性表的链式实现C语言代码(新手向,大佬别浪费时间看了)

针对数据结构中的链表,用C语言实现所有函数的代码。说实话,我感觉数据结构的教材都是采用伪代码,有的函数连伪代码也没提供,对初学数据结构的小白实在不是很友好。希望这些代码能给初学者带来方便。

#include<stdio.h>
#include<stdlib.h>

//线性表的链式实现中,每一个数据元素都存在结构体节点中,每一个节点结构体需要包含数据域和指针域两个部分
//为了简化,这里数据域为int类型。指针域为指向自身结构体类型的指针变量。 
typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList;//LinkList 就等价于 struct LNode *;所有声明为LinkList类型的变量都是一个指向这个结构体类型的指针变量 

int main(){
	//函数声明部分 
	LinkList InitList();//链表的初始化(带有头结点) 
	int ListInsert(LinkList ,int ,int ); //向链表的合法位置插入指定元素 
	void visit(int );//对数据域的访问方法 
	void ListTraverse(LinkList ,void (*f)(int ));//遍历链表,函数指针指向visit方法 
	int ListDelete(LinkList ,int ,int *);//删除合法位置的结点 
	void DestroyList(LinkList);//销毁链表,释放空间 
	int ListLength(LinkList); //返回链表的长度(即除去头结点以外的结点个数) 
	void GetElem(LinkList ,int ,int *);//获取指定位置的数据 
	int compare(int ,int );//两个结点数据域的比较方法 
	int LocateElem(LinkList ,int ,int (*f)(int ,int ));//根据上面的比较方法查找链表中第一个满足条件的数据,返回它在链表中的位置 
	void PriorElem(LinkList ,int ,int *);//返回指定值的元素的前驱元素 
	void NextElem(LinkList ,int ,int *);//返回指点值的元素的后继元素 
	
	//函数测试部分 
	//链表初始化,并且插入元素 
	LinkList l;
	l=InitList();
	if(ListInsert(l,1,9)){
		printf("ok\n");
	}
	ListInsert(l,2,8);
	ListInsert(l,1,10);
	//测试求表长函数 
	printf("\n现在的表长是:%d\n",ListLength(l));
	//测试遍历函数 
	ListTraverse(l,visit);
	//测试元素删除函数 
	int t,*tp=&t;
	if(ListDelete(l,2,tp)){
		printf("\n成功删除了第%d个元素,被删除元素的值是%d\n",2,t);
	}
	printf("\n现在的表长是:%d\n",ListLength(l));
	ListTraverse(l,visit);
	//测试访问指定位置元素函数 
	int k,*e=&k;
	GetElem(l,2,e);
	printf("\n第二个元素是:%d\n",k);
	//测试按值定位函数 
	int loc=LocateElem(l,10,compare);
	if(loc!=0){
		printf("\n定位10的位置:%d\n",loc);
	}else{
		printf("\n链表中没有这个元素\n");
	}
	//测试求前驱函数 
	int pri,*prip=&pri;
	PriorElem(l,8,prip);
	printf("找到8的前驱元素:%d\n",pri);
	//测试求后继函数 
	int next,*nextp=&next;
	NextElem(l,10,nextp);
	printf("找到10的后继元素:%d\n",next);
	//测试链表销毁函数 
	DestroyList(l);
	l=NULL;//销毁空间的函数free不会把指针置空,这里手动置空 
	return 0;	
}

//初始化函数 
LinkList InitList(){//返回指向结构体类型的指针变量 
	LinkList t=(LinkList)malloc(sizeof(LNode));//申请头结点的空间 
	if(!t){
		exit(1);
	}
	t->next=NULL;//头结点数据域为空,指针域置空 
	return t;//返回申请到的空间首地址 
}

//插入元素函数 
int ListInsert(LinkList l,int i,int e){
	LinkList p=l;
	int j=0;
	while(p&&j<i-1){
		p=p->next;
		j++;
	}
	if(!p||j>i-1){
		return 0;
	}
	LinkList s=(LinkList)malloc(sizeof(LNode));
	s->data=e;
	s->next=p->next;
	p->next=s;
	return 1;
} 

//额,后面的懒得写了,需要注意的后面各个函数中的循环终止条件,不太理解的可以画个例子在纸上试一下
//核心是p和p->next的关系:假如说p指向第i-1个元素,那么p的值就等于第i-2个结点的指针域的值。p->next等价于
//第i-1个结点的指针域的值,那么p->next指向第i的结点。理解这点很重要,因为链表无法随机访问,大多数操作都要从
//头指针出发挨个找的真确的位置。 
void ListTraverse(LinkList l,void (*f)(int )){
	if(!l){
		printf("这是一个空表");
		exit(1);
	}
	LinkList p=l;
	for(p=p->next;p!=NULL;p=p->next){
		f(p->data);
	}
}

void visit(int a){
	printf("%d\t",a);
}

int ListDelete(LinkList l,int i,int *e){
	LinkList p=l;
	int j=0;
	while(p->next&&j<i-1){
		p=p->next;
		++j;
	}
	if(!(p->next)||j>i-1){
		return 0;
	}
	LinkList q=p->next;
	p->next=q->next;
	*e=q->data;
	free(q);
	return 1;
}

void DestroyList(LinkList l){
	LinkList p=l;
	if(p->next!=NULL){
		DestroyList(p->next);
		free(p);
	}else{
		free(p);
	}
}

int ListLength(LinkList l){
	if(!l){
		exit(1);
	}
	int j=0;
	for(LinkList p=l;p->next!=NULL;p=p->next){
		j++;
	}
	return j;
}

void GetElem(LinkList l,int i,int *e){
	if(!l){
		exit(1);
	}
	LinkList p=l;
	for(int j=0;j<i;j++){
		p=p->next;
	}
	*e=p->data;
}

int compare(int a,int b){
	if(a==b){
		return 1;
	}else{
		return 0;
	}
}

int LocateElem(LinkList l,int e,int (*f)(int ,int )){
	LinkList p=l;
	int j=1;
	for(p=p->next;p!=NULL;p=p->next){
		if(f(e,p->data)==1){
			return j;
		}
		j++;
	}
	return 0;
}

void PriorElem(LinkList l,int cur,int *pri){
	int i=LocateElem(l,cur,compare);
	if(i==1||i==0){
		exit(1);
	}
	GetElem(l,i-1,pri);
}

void NextElem(LinkList l,int cur,int *next){
	int i=LocateElem(l,cur,compare);
	if(i==0||i==ListLength(l)){
		exit(1);
	}
	GetElem(l,i+1,next);
}

运行结构:

ok

现在的表长是:3
10      9       8
成功删除了第2个元素,被删除元素的值是9

现在的表长是:2
10      8
第二个元素是:8

定位10的位置:1
找到8的前驱元素:10
找到10的后继元素:8

--------------------------------
Process exited after 2.351 seconds with return value 0
请按任意键继续. . .

码字不易点个赞再走啊~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

KOKO银角大王

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

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

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

打赏作者

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

抵扣说明:

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

余额充值