《算法导论》学习(十二)----链表(C语言)


前言

文章主要讲解了链表的相关讲解,涉及了单链表,双向链表,循环链表的操作函数,并且用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",&current->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;
}

总结

由于链表数据结构没有逻辑上的复杂性,因此讲解偏少,望大家包涵
文章不妥错误之处请大家包涵和指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SigmaBull

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

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

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

打赏作者

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

抵扣说明:

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

余额充值