前言
文章主要讲解了链表的相关讲解,涉及了单链表,双向链表,循环链表的操作函数,并且用C语言进行了实现
一、链表
1.什么是链表?
要了解链表,我们就要先说到数组。
数组是计算机的顺序存储结构,是贴合计算机的硬件架构的
而链表是链式存储结构,它的存储方式是运用了指针来作为链条,然后结构体空间为结点。用链条将一个个结点串起来
就计算机的底层结构来说,链式结构的任意两个结点之间的地址空间没有任何的联系
2.为什么需要链表?
顺序结构的好处是查找,访问特别的方便,因为它满足计算机最底层的硬件架构
但是数组元素的插入,删除是很不方便的,可以称为牵一发而动全身,在数组中间插入一个数组,如果要保持原来的元素顺序不变的话,那需要将整个数组的元素都进行重新换位;删除也是一样的道理。
这时我们就用到了链表,链表最擅长的工作就是删除和插入元素,因为
它的存储结构是链式的,结点之间的联系是靠链条来维持
因此插入删除元素只需要改动“链条”,并且释放结点的存储空间就可以了
二、单链表
1.数据结构
typedef struct body
{
int value;
struct body *next;
};
2.操作函数
#include<stdio.h>
#include<stdlib.h>
char a[10001];
char b[3];
typedef struct body
{
int value;
struct body *next;
};
body *init()
{
body *first=(body*)malloc(sizeof(body));
first->next=NULL;
first->value=0;
printf("创建成功\n");
return first;
}
void isemp(body *first)
{
if(first->next==NULL||first==NULL)
{
printf("单链表为空\n");
}
else printf("单链表不为空\n");
}
void printlinelist(body *first)
{
if(first->next==NULL)
{
printf("单链表为空表\n");
}
else
{
body* per;
per=first->next;
while(per->next!=NULL)
{
printf("%d ",per->value);
per=per->next;
}
printf("%d\n",per->value);
}
}
int length(body *first)
{
if(first->next==NULL)
{
return 0;
}
else
{
return first->value;
}
}
int getvalue(body *first,int i)
{
if(first->next==NULL)
{
printf("单链表为空表,取值无效\n");
return 0;
}
else if(i<=0)
{
printf("位置信息不合规范\n");
return 0;
}
else if(i>first->value)
{
printf("超过单链表大小\n");
return 0;
}
else
{
int count=1;
body *per;
per=first;
while(count!=i)
{
per=per->next;
count++;
}
return per->next->value;
}
}
int getlocation(body *first,int value1)
{
if(first->next==NULL)
{
printf("单链表为空表\n");
return 0;
}
else
{
int count=0;
body *per;
per=first->next;
while(per->next!=NULL)
{
count++;
if(per->value==value1)
{
return count;
}
per=per->next;
}
if(per->value==value1)
{
return count+1;
}
else
{
printf("没有该值\n");
return 0;
}
}
}
void insert(body* first,int i,int value1)
{
if(i<=0)
{
printf("插入失败\n");
}
else
{
body *per;
per=first;
int count;
count=first->value;
if(i>count+1)
{
printf("插入失败\n");
}
else if(i==count+1)
{
while(per->next!=NULL)
{
per=per->next;
}
body *l1;
l1=(body*)malloc(sizeof(body));
per->next=l1;
l1->next=NULL;
l1->value=value1;
first->value=first->value+1;
printf("插入成功\n");
}
else
{
count=1;
per=first;
while(count!=i)
{
per=per->next;//per是第i个位置的元素
count++;
}
body* temp;
temp=(body*)malloc(sizeof(body));
temp->next=per->next;
per->next=temp;
temp->value=value1;
first->value=first->value+1;
printf("插入成功\n");
}
}
}
void delet(body *first,int i)
{
body* per;
per=first;
int count;
count=first->value;
if(i<0||per->next==NULL)
{
printf("删除失败\n");
}
else if(i==count)
{
per=first;
while(per->next->next!=NULL)
{
per=per->next;
}
free(per->next);
per->next=NULL;
first->value=first->value-1;
printf("删除成功\n");
}
else if(i>count)
{
printf("超过单链表大小\n");
}
else
{
per=first;
count=1;
while(count!=i)
{
per=per->next;
count++;
}
body* temp;
temp=per;
per=per->next;
temp->next=per->next;
free(per);
first->value=first->value-1;
printf("删除成功\n");
}
}
body* creatlinelist(int a[],int i)
{
if(i<=0)
{
printf("创建失败\n");
return NULL;
}
else
{
body *first=NULL;
first=(body*)malloc(sizeof(body));
body *s=NULL;
first->value=i;
body *per;
per=first;
for(int k=0;k<i;k++)
{
s=(body*)malloc(sizeof(body));
s->value=a[k];
per->next=s;
per=per->next;
}
s->next=NULL;
printf("创建成功\n");
return first;
}
}
void destroy(body *first)
{
body* per;
first->value=0;
per=first->next;
for(int i=1;i<=first->value;i++)
{
body* temp;
temp=per;
per=per->next;
free(temp);
}
first->next=NULL;
printf("销毁完成\n");
}
int main()
{
body *l;
l=init();
body *l1;
l1=init();
int num;
scanf("%d",&num);
int number1=0;
int number2=0;
int i=0;
for(int i=0;i<num;i++)
{
scanf("%c",&a[i]);
printf("%c ",a[i]);
if(a[i]==1)
{
number1++;
}
if(a[i]==0)
{
number2++;
}
i++;
}
return 0;
}
三、双向链表
1.数据结构
typedef struct body
{
int value;
struct body *next;
struct body *pre;
};
2.操作函数
#include<stdio.h>
#include<stdlib.h>
typedef struct body
{
int value;
struct body *next;
struct body *pre;
};
body *init()
{
body *first=(body*)malloc(sizeof(body));
first->next=NULL;
first->pre=NULL;
first->value=0;
printf("创建成功\n");
return first;
}
void isemp(body *first)
{
if(first->next==NULL||first==NULL)
{
printf("单链表为空\n");
}
else printf("单链表不为空\n");
}
void nextprintlinelist(body *first)
{
if(first->next==NULL)
{
printf("单链表为空表\n");
}
else
{
body* per;
per=first->next;
while(per->next!=NULL)
{
printf("%d ",per->value);
per=per->next;
}
printf("%d\n",per->value);
}
}
void preprintlinelist(body *first)
{
if(first->next==NULL)
{
printf("单链表为空表\n");
}
else
{
body* per;
per=first;
while(per->next!=NULL)
{
per=per->next;
}
while(per->pre!=NULL)
{
printf("%d ",per->value);
per=per->pre;
}
printf("\n");
}
}
int length(body *first)
{
if(first->next==NULL)
{
return 0;
}
else
{
return first->value;
}
}
int getvalue(body *first,int i)
{
if(first->next==NULL)
{
printf("单链表为空表,取值无效\n");
return 0;
}
else if(i<=0)
{
printf("位置信息不合规范\n");
return 0;
}
else if(i>first->value)
{
printf("超过单链表大小\n");
return 0;
}
else
{
int count=1;
body *per;
per=first;
while(count!=i)
{
per=per->next;
count++;
}
return per->next->value;
}
}
int getlocation(body *first,int value1)
{
if(first->next==NULL)
{
printf("单链表为空表\n");
return 0;
}
else
{
int count=0;
body *per;
per=first->next;
while(per->next!=NULL)
{
count++;
if(per->value==value1)
{
return count;
}
per=per->next;
}
if(per->value==value1)
{
return count+1;
}
else
{
printf("没有该值\n");
return 0;
}
}
}
void insert(body* first,int i,int value1)
{
if(i<=0)
{
printf("插入失败\n");
}
else
{
body *per;
per=first;
int count;
count=first->value;
if(i>count+1)
{
printf("插入失败\n");
}
else if(i==count+1)
{
while(per->next!=NULL)
{
per=per->next;
}
body *l1;
l1=(body*)malloc(sizeof(body));
per->next=l1;
l1->pre=per;
l1->next=NULL;
l1->value=value1;
first->value=first->value+1;
printf("插入成功\n");
}
else
{
count=1;
per=first;
while(count!=i)
{
per=per->next;//per是第i个位置的元素
count++;
}
body* temp;
temp=(body*)malloc(sizeof(body));
temp->next=per->next;
per->next->pre=temp;
temp->pre=per;
per->next=temp;
temp->value=value1;
first->value=first->value+1;
printf("插入成功\n");
}
}
}
void delet(body *first,int i)
{
body* per;
per=first;
int count;
count=first->value;
if(i<0||per->next==NULL)
{
printf("删除失败\n");
}
else if(i==count)
{
per=first;
while(per->next->next!=NULL)
{
per=per->next;
}
free(per->next);
per->next=NULL;
first->value=first->value-1;
printf("删除成功\n");
}
else if(i>count)
{
printf("超过单链表大小\n");
}
else
{
per=first;
count=1;
while(count!=i)
{
per=per->next;
count++;
}
body* temp;
temp=per;
per=per->next;
per->next->pre=temp;
temp->next=per->next;
free(per);
first->value=first->value-1;
printf("删除成功\n");
}
}
body* creatlinelist(int a[],int i)
{
if(i<=0)
{
printf("创建失败\n");
return NULL;
}
else
{
body *first=NULL;
first=(body*)malloc(sizeof(body));
body *s=NULL;
first->value=i;
first->pre=NULL;
body *per;
per=first;
for(int k=0;k<i;k++)
{
s=(body*)malloc(sizeof(body));
s->value=a[k];
per->next=s;
s->pre=per;
per=per->next;
}
s->next=NULL;
printf("创建成功\n");
return first;
}
}
void destroy(body *first)
{
body* per;
first->value=0;
per=first->next;
for(int i=1;i<=first->value;i++)
{
body* temp;
temp=per;
per=per->next;
free(temp);
}
first->next=NULL;
printf("销毁完成\n");
}
int main()
{
int b[7];
for(int i=0;i<7;i++)
{
scanf("%d",&b[i]);
}
body *l;
l=creatlinelist(b,7);
preprintlinelist(l);
nextprintlinelist(l);
insert(l,5,888);
delet(l,1);
preprintlinelist(l);
nextprintlinelist(l);
destroy(l);
return 0;
}
四、循环链表
1.数据结构
typedef struct body
{
int value;
struct body *next;
};
2.操作函数
#include<stdio.h>
#include<stdlib.h>
typedef struct body
{
int value;
struct body *next;
};
body *init()
{
body *first=(body*)malloc(sizeof(body));
first->next=NULL;
first->value=0;
printf("创建成功\n");
return first;
}
void isemp(body *first)
{
if(first->next==NULL||first==NULL)
{
printf("循环链表为空\n");
}
else printf("循环链表不为空\n");
}
void printlinelist(body *first)
{
if(first->next==NULL)
{
printf("循环链表为空表\n");
}
else
{
body* per;
per=first->next;
int n;
n=first->value;
for(int i=0;i<n;i++)
{
printf("%d ",per->value);
per=per->next;
}
printf("\n");
}
}
int length(body *first)
{
if(first->next==NULL)
{
return 0;
}
else
{
return first->value;
}
}
int getvalueonce(body *first,int i)
{
if(first->next==NULL)
{
printf("循环链表为空表,取值无效\n");
return 0;
}
else if(i<=0)
{
printf("位置信息不合规范\n");
return 0;
}
else if(i>first->value)
{
printf("超过循环链表大小\n");
return 0;
}
else
{
int count=1;
body *per;
per=first;
while(count!=i)
{
per=per->next;
count++;
}
return per->next->value;
}
}
int getvalue(body *first,int i)
{
if(first->next==NULL)
{
printf("循环链表为空表\n");
return 0;
}
else if(i<=0)
{
printf("无效位置\n");
return 0;
}
else
{
int n;
n=first->value;
int num;
num=i%n;
body *per;
per=first;
for(int j=0;j<num;j++)
{
per=per->next;
}
printf("取值成功\n");
return per->value;
}
}
int getlocation(body *first,int value1)
{
if(first->next==NULL)
{
printf("循环链表为空表\n");
return 0;
}
else
{
int count=0;
body *per;
per=first->next;
while(per->next!=NULL)
{
count++;
if(per->value==value1)
{
return count;
}
per=per->next;
}
if(per->value==value1)
{
return count+1;
}
else
{
printf("没有该值\n");
return 0;
}
}
}
void insert(body* first,int i,int value1)
{
if(i<=0)
{
printf("插入失败\n");
}
else
{
body *per;
per=first;
int count;
count=first->value;
int num;
num=i%count;
if(num==1)
{
for(int k=0;k<count;k++)
{
per=per->next;
}
body *temp;
temp=(body*)malloc(sizeof(body));
temp->value=value1;
temp->next=first->next;
first->next=temp;
per->next=temp;
printf("插入成功\n");
first->value=first->value+1;
}
else if(num==0)
{
for(int k=1;k<count;k++)
{
per=per->next;
}
body *temp;
temp=(body *)malloc(sizeof(body));
temp->next=per->next;
temp->value=value1;
per->next=temp;
printf("插入成功\n");
first->value=first->value+1;
}
else
{
for(int k=1;k<num;k++)
{
per=per->next;
}
body *temp;
temp=(body *)malloc(sizeof(body));
temp->next=per->next;
temp->value=value1;
per->next=temp;
printf("插入成功\n");
first->value=first->value+1;
}
}
}
void delet(body *first,int i)
{
body* per;
per=first;
int count;
count=first->value;
int num;
num=i%count;
if(i<=0||per->next==NULL)
{
printf("删除失败\n");
}
else if(num==0)
{
per=first;
for(int k=1;k<count;k++)
{
per=per->next;
}
body *s;
s=per->next;
per->next=s->next;
free(s);
first->value=first->value-1;
printf("删除成功\n");
}
else
{
per=first;
for(int k=1;k<num;k++)
{
per=per->next;
}
body *s;
s=per->next;
per->next=s->next;
free(s);
first->value=first->value-1;
printf("删除成功\n");
}
}
body* creatlinelist(int a[],int i)
{
if(i<=0)
{
printf("创建失败\n");
return NULL;
}
else
{
body *first=NULL;
first=(body*)malloc(sizeof(body));
body *s=NULL;
first->value=i;
body *per;
per=first;
for(int k=0;k<i;k++)
{
s=(body*)malloc(sizeof(body));
s->value=a[k];
per->next=s;
per=per->next;
}
s->next=first->next;
printf("创建成功\n");
return first;
}
}
void destroy(body *first)
{
body* per;
first->value=0;
per=first->next;
for(int i=1;i<=first->value;i++)
{
body* temp;
temp=per;
per=per->next;
free(temp);
}
first->next=NULL;
printf("销毁完成\n");
}
void delcha(body *first,int i)
{
body* per;
per=first;
int count;
count=first->value;
int num;
num=i%count;
if(i<=0||per->next==NULL)
{
printf("删除失败\n");
}
else if(num==0)
{
per=first;
for(int k=1;k<count;k++)
{
per=per->next;
}
body *s;
s=per->next;
per->next=s->next;
free(s);
first->next=per->next;
first->value=first->value-1;
printf("删除成功\n");
}
else
{
per=first;
for(int k=1;k<num;k++)
{
per=per->next;
}
body *s;
s=per->next;
per->next=s->next;
free(s);
first->next=per->next;
first->value=first->value-1;
printf("删除成功\n");
}
}
int main()
{
body *l;
int a[20];
for(int i=0;i<20;i++)
{
a[i]=i+1;
}
l=creatlinelist(a,20);
printlinelist(l);
for(int i=0;i<19;i++)
{
delcha(l,3);
}
printlinelist(l);
return 0;
}
三、链表思想的应用
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define TSIZE 45
typedef struct film
{
char title[TSIZE];
int rating;
struct film *next;
};
char *sgets(char *st,int n)
{
char *ret_val;
char *find;
ret_val=fgets(st,n,stdin);
if(ret_val)
{
find=strchr(st,'\n');
if(find)
{
*find='\0';
}
else
{
while (getchar()!='\n')
continue;
}
}
return ret_val;
}
int main()
{
film* head=NULL;
film* prev,*current;
char input[TSIZE];
puts("Enter first movie title:");
while(sgets(input,TSIZE)!=NULL&&input[0]!='\0')
{
current=(film*)malloc(sizeof(film));
if(head==NULL)
{
head=current;
}
else
{
prev->next=current;
}
current->next=NULL;
strcpy(current->title,input);
puts("Enter your rating<0-10>:");
scanf("%d",¤t->rating);
while(getchar()!='\n')
{
continue;
}
puts("Enter next movie title (empty line to stop):");
prev=current;
}
if(head==NULL)
{
printf("No data entered.");
}
else
{
printf("Here is the movie list:\n");
}
current=head;
while(current!=NULL)
{
printf("Movie: %s Rating: %d\n",current->title,current->rating);
current=current->next;
}
current=head;
while(current!=NULL)
{
current=head;
head=current->next;
free(current);
}
printf("Bye!\n");
return 0;
}
总结
由于链表数据结构没有逻辑上的复杂性,因此讲解偏少,望大家包涵
文章不妥错误之处请大家包涵和指正