【数据结构】链表

引言

介绍链表之前,先来说一下顺序表,即数组的缺点:

  1. 顺序表在存储数据时,不易插入和删除数据;
  2. 顺序表的存储空间利用率和运行效率都不高;
    为了解决上述缺点,线性表可以采用另一种存储结构—链式存储结构。

单链表

定义

(链表没特殊说明默认为单链表)链表是通过一组地址任意的存储单元来存储数据元素的存储结构;这些存储单元可以连续,也可以不连续。

1.单链表结点结构

在这里插入图片描述

2.头指针

头指针的作用有两个:
1.标识链表,即链表的名字;
2.存储链表中第一个结点的地址;

3.尾指针

尾指针即链表的最后一个结点,没有后继,因此指针域必须置空,即NULL。

单链表的创建

1.头插法创建单链表

创建步骤:
1.建立头节点Head,另其指针域置空;
2.生成新节点p(申请空间失败的话返回Head);
3.读入数据到p的数据域;
4.将结点p插入到Head之后。
5.重复步骤2~4。
图文表示:
在这里插入图片描述
代码实现:
返回值是链表的头节点;

LinkList *CreateLink(){
	//头插法 
	LinkList *head,*p;
	head=(LinkList *)malloc(sizeof(LinkList));//获得的地址转换为 ListLink *类型 
	if(head==NULL)return head;
	head->next=NULL;
	int x;
	cin>>x;
	while(x!=0){
		p=(LinkList *)malloc(sizeof(LinkList));
		p->data=x;
		p->next=head->next;
		head->next=p;
		cin>>x;
	}
	return head;
}
2.尾插法创建单链表

尾插法与头插法类似,只是将p结点连入尾结点之后。
在这里插入图片描述
代码实现:

LinkList *CreateLink2(){
	//尾插法
	LinkList *head,*p,*tail; 
	head=(LinkList *)malloc(sizeof(LinkList));//每次申请空间时,严谨的做法是判断申请是否成功 
	if(head==NULL)return head;
	head->next=NULL;
	tail=head;
	int x;
	cin>>x;
	while(x!=0){
		p=(LinkList *)malloc(sizeof(LinkList));
		p->data=x;
		tail->next=p;
		tail=p;
		tail->next=NULL;
		cin>>x;
	} 
	return head;
}

单链表的基本操作

1.单链表的遍历

链表的遍历就是从头节点开始,依次访问链表中的每一个结点;在遍历过程中也可以设置一个计数器,计算链表的长度。
代码实现:

void Print_Link(LinkList *head){
	LinkList *p=head->next;
	int num=0; //num为计数器,其结果为链表长度 
	while(p!=NULL){
		cout<<p->data<<endl;
		p=p->next; 
		num+=1;
	}
} 
2.单链表的查找

查找方式分为两种,一种是根据序号查找;一种是根据值去查找。
根据值查找:

LinkList *GetByNum(LinkList *head,int num){
	LinkList *p=head->next;
	while(p!=NULL){
		if(p->data==num)return p;//找到返回结点指针 
		p=p->next;
	} 
	return NULL;//找不到返回NULL 
}

根据节点查找:

LinkList *GetById(LinkList *head,int i){
	int j=0;
	if(i<=0)return NULL;//保证序号合法 
	LinkList *p=head;
	while(p->next!=NULL){
		p=p->next;
		j+=1;//以头节点指向的节点为序号1对应的节点 
	} 
	if(i==j)return p;
	return NULL;
}
3.单链表的插入

链表插入方式分为两种,一种是后插;一种是前插。
后插:
示意图
在这里插入图片描述
代码实现

void InsertAfter(LinkList *p,LinkList *s){
	//在p节点之后插入s节点
	s->next=p->next;
	p->next=s; 
}
前插与后插的思想类似:
1.先找出节点p的前驱节点q;
2.对q进行后插;
4.单链表的删除
int Delete_LinkList(LinkList *head,LinkList *p){
	//删除指定节点p
	LinkList *r;
	if(p->next!=NULL){//如果p有后继节点
		p->data=p->next->data;
		r=p->next;
		p->next=r->next;
		free(r); //释放空间
		return 1; 
	} 
	else {//p没有后继节点
		r=head;
		while(r->next!=p)
			r=r->next;
		LinkList *q=r->next;
		r->next=q->next;
		free(q); 
	}
} 

静态链表

与单链表的操作基本一直,只是指针指向下标;用下标作为起到唯一标识作用的“地址”。

struct LinkList{
	int data;
	int next;
};

循环链表和双向链表

循环链表

双向链表

链表的应用

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

高冷小伙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值