简介:采用c语言,但是在此代码中函数返回类型中采用了bool,如果需要以c文件运行,将bool类型改为int即可
作者备战考研,以此督学,希望大家多多指教呢
目录
单链表的结构体定义为
其中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就无法为主函数中的指针修改指向,通俗化说;就是我们需要修改指针,就要用指针的指针