数据结构考研一练习day2-c语言单链表

简介:采用c语言,但是在此代码中函数返回类型中采用了bool,如果需要以c文件运行,将bool类型改为int即可

作者备战考研,以此督学,希望大家多多指教呢

目录

单链表的结构体定义为

1.初始化一个表,构造一个空的线性表

头插法,输入9999停止

尾插法,输入9999停止

2.求表长。返回线性表的长度,即数据元素的个数

3.按值查找操作

4.按位查找操作

5.插入操作

6.删除操作

7.输出操作

8.判空操作

实例全部

总结


单链表的结构体定义为

其中Lnode为节点名字,Linklist代表的是链表的称呼,用两个来区分节点和整个链表(个人认为命名及其重要,毕竟以后大部分的人都是面向项目,有效的名字,可以便于工作高效进行)

typedef struct Lnode{
	elemtype data;
	struct Lnode *next;
}Lnode,*Linklist; 

1.初始化一个表,构造一个空的线性表

头插法,输入9999停止

只要在主函数中引用整个函数,就可以输入数字进行创建单链表,创建的单链表可以返回给主函数中链表指针用,也可以在主函数中传入链表的指针的地址后修改链表指针指向

头插法就是输入后,链表里面储存的顺序和输入顺序相反

比如:你输入1,2,3,4,5,6,然后打印单链表就是6,5,4,3,2,1

ps:需要深刻理解一下Linklist*的具体含义:我们对于一个LinkList需要使其指向一个node大的空间时,传参就需要使用Linklist,否则我么我们使用的la就无法为主函数中的指针修改指向,通俗化说;就是我们需要修改指针,就要用指针的指针

//这个使用头插法建立单链表,这个用c语言不是很好理解 
Linklist List_headinsert(Linklist *la){
	Lnode *s ;//lnode 代表s是指向一个节点的指针 
	int x; 
	*la=(Linklist)malloc(sizeof(Lnode));//为什么要使用*号呢,因为我们改变的是LinkList,所以要用 LinkList *, *la代表已经获得了这个指针的地区名字 
	(*la)->next=NULL;
	scanf("%d",&x);
	while(x!=9999){
		s=(Lnode *)malloc(sizeof(Lnode));
		s->data=x;
		s->next=(*la)->next;
		(*la)->next=s;
		scanf("%d",&x);
	}
	return *la;
} 

尾插法,输入9999停止

同上面,尾插法就是输入后,链表里面储存的顺序和输入顺序相同

比如:你输入1,2,3,4,5,6,然后打印单链表就是1,2,3,4,5,6

//采用尾插法建立单链表
Linklist List_TailInsert(Linklist *la) {
	int x;
	(*la)=(Linklist)malloc(sizeof(Lnode));
	Lnode *s,*r=*la;//r是表尾巴指针
	scanf("%d",&x);
	while(x!=9999){
		s=(Lnode*)malloc(sizeof(Lnode));
		s->data=x;
		s->next=NULL;//这个可别少了 
		r->next=s;
		r=s;
		scanf("%d",&x);
	} 
	return *la;
}

2.求表长。返回线性表的长度,即数据元素的个数

前提条件:这个线性表存在

结果:返回这个单链表的长度

//求单链表长度 
int Length(Linklist la){
	int count=0;
	while(la->next!=NULL){
		count++;
		la=la->next;
	}
	return count; 
}

3.按值查找操作

在表中查找具有给定关键词的节点,如果有多个返回第一个符合的节点指针

//求单链表中元素为e的节点 返回这个节点的指针 
Lnode * LocateElem(Linklist la,int e){
	la=la->next;
	while(la!=NULL){
		if(la->data==e)return la;
		la=la->next;
	}
	return NULL;//没有找到	
}

4.按位查找操作

在表中查找第i个元素的值,找到返回这个节点指针

//求单链表中第i个元素,  返回这个节点的指针 
Lnode *Getelem(Linklist la,int i){  
	if(i<1)return NULL;//不合法返回;
	int count=0; 
	while(la!=NULL&&count<i){
		la=la->next;
		count++;
	}
	if(count==i)return la;
	else return NULL;//还没有找到这个位置,链表就没了 
} 

5.插入操作

在表中第i个位置插入节点temp

//插入节点操作,在第i个位置插入temp节点 
bool  ListInsert(Linklist l,int i,Lnode *temp){
	Lnode *a=Getelem(l,i-1);
	if(a!=NULL){
		temp->next=a->next;
		a->next=temp;
		return 1;
	}else return 0;
}

6.删除操作

删除表中第i个元素,用e返回删除元素之值

//删除节点操作,用e返回被删除元素的值 
bool ListDel(Linklist l,int i,int *e){
	Lnode *a=Getelem(l,i-1);
	Lnode *q;
	if(a->next!=NULL){
		 *e=a->next->data;
		 q=a->next;
		 a->next=a->next->next;
		 free(q);
		 return 1;
	}
	return 0;
}

7.输出操作

依次打印链表中所有节点

void  Linkprint(Linklist a){
	a=a->next;
	while(a!=NULL){
		printf("%d ",a->data);
		a=a->next;
	}
	printf("\n");
}

8.判空操作

含有头结点的链表直接判断头结点后面是否有元素

bool  empty(Linklist l){
	if(l->next!=NULL)return 0;
	return 1;
}

实例全部

//胡宇考研单链表实操代码
#include<stdio.h>
#include<malloc.h>
#define elemtype int 
typedef struct Lnode{
	elemtype data;
	struct Lnode *next;
}Lnode,*Linklist; 

//以下操作是带头节点的链表,c语言不便于理解 
void InitList(Linklist *la){
	//我是为了创建一个带头结点的单链表,所以首先这个LInklist指针要先有一个空间,然后这个空间要指向首元节点 
	*la=(Linklist)malloc(sizeof(Lnode));//
	(*la)->next=NULL; 
} 

//这个使用头插法建立单链表,这个用c语言不是很好理解 
Linklist List_headinsert(Linklist *la){
	Lnode *s ;//lnode 代表s是指向一个节点的指针 
	int x; 
	*la=(Linklist)malloc(sizeof(Lnode));//为什么要使用*号呢,因为我们改变的是LinkList,所以要用 LinkList *, *la代表已经获得了这个指针的地区名字 
	(*la)->next=NULL;
	scanf("%d",&x);
	while(x!=9999){
		s=(Lnode *)malloc(sizeof(Lnode));
		s->data=x;
		s->next=(*la)->next;
		(*la)->next=s;
		scanf("%d",&x);
	}
	return *la;
} 

//采用尾插法建立单链表
Linklist List_TailInsert(Linklist *la) {
	int x;
	(*la)=(Linklist)malloc(sizeof(Lnode));
	Lnode *s,*r=*la;//r是表尾巴指针
	scanf("%d",&x);
	while(x!=9999){
		s=(Lnode*)malloc(sizeof(Lnode));
		s->data=x;
		s->next=NULL;//这个可别少了 
		r->next=s;
		r=s;
		scanf("%d",&x);
	} 
	return *la;
}


//求单链表长度 
int Length(Linklist la){
	int count=0;
	while(la->next!=NULL){
		count++;
		la=la->next;
	}
	return count; 
}
//求单链表中元素为e的节点 返回这个节点的指针 
Lnode * LocateElem(Linklist la,int e){
	la=la->next;
	while(la!=NULL){
		if(la->data==e)return la;
		la=la->next;
	}
	return NULL;//没有找到	
}
//求单链表中第i个元素,  返回这个节点的指针 
Lnode *Getelem(Linklist la,int i){  
	if(i<1)return NULL;//不合法返回;
	int count=0; 
	while(la!=NULL&&count<i){
		la=la->next;
		count++;
	}
	if(count==i)return la;
	else return NULL;//还没有找到这个位置,链表就没了 
} 
//插入节点操作,在第i个位置插入temp节点 
bool  ListInsert(Linklist l,int i,Lnode *temp){
	Lnode *a=Getelem(l,i-1);
	if(a!=NULL){
		temp->next=a->next;
		a->next=temp;
		return 1;
	}else return 0;
}
//删除节点操作,用e返回被删除元素的值 
bool ListDel(Linklist l,int i,int *e){
	Lnode *a=Getelem(l,i-1);
	Lnode *q;
	if(a->next!=NULL){
		 *e=a->next->data;
		 q=a->next;
		 a->next=a->next->next;
		 free(q);
		 return 1;
	}
	return 0;
}
void  Linkprint(Linklist a){
	a=a->next;
	while(a!=NULL){
		printf("%d ",a->data);
		a=a->next;
	}
	printf("\n");
}
bool  empty(Linklist l){
	if(l->next!=NULL)return 0;
	return 1;
}
int main(){
	//首先我先创建一个指向头节点的指针,也就是头指针
	Linklist la;
	List_TailInsert(&la);
	printf("为你打印一下顺序表:"); 
	Linkprint(la);
	printf("顺序表的长度为:%d\n",Length(la)); 
	printf("在第3个位置插入一个节点\n");
	Lnode *temp=(Lnode *)malloc(sizeof(Lnode));
	temp->data=666;
	temp->next=NULL;
	ListInsert(la,3,temp);
	printf("为你打印一下顺序表:"); 
	Linkprint(la);
	temp=Getelem(la,3);
	printf("打印一下第三个节点的值"); 
	printf("%d\n",temp->data);
	printf("删除第三个节点\n");
	int e;
	ListDel(la,3,&e);
	temp=Getelem(la,3);
	printf("打印一下第三个节点的值:"); 
	printf("%d",temp->data); 
	return 0;//讲究人 
}

总结

函数实参和形参的区别,这里不再赘述

便于大家理解文章中的头插法和尾插法,需要深刻理解一下Linklist*的具体含义:我们对于一个LinkList需要使其指向一个node大的空间时,传参就需要使用Linklist,否则我么我们使用的la就无法为主函数中的指针修改指向,通俗化说;就是我们需要修改指针,就要用指针的指针

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值