数据结构-什么是单向链表?

简介

链表是一个线性数据结构,由一系列的结点组成,每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域,节点动态分配,长度可变。

常见类型:单向链表(singly)、双向链表(doubly)、循环链表(circular)。

用途:需要频繁在中间插入/删除的场景很合适。

链表可用于实现数据队列。队列(Queue)是一种抽象数据类型(ADT),遵循 FIFO(先进先出)规则。只在队尾插入(enqueue),只在队头删除(dequeue)。

队列可以用数组(循环缓冲)或链表实现。

一、单向链表的数据定义

单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。

单向链表是一种线性表,实际上是由节点(Node)组成的,一个链表拥有不定数量的节点。其数据在内存中存储是不连续的,它存储的数据分散在内存中,每个结点只能也只有它能知道下一个结点的存储位置。由N各节点(Node)组成单向链表,每一个Node记录本Node的数据及下一个Node。向外暴露的只有一个头节点(Head),我们对链表的所有操作,都是直接或者间接地通过其头节点来进行的。

链表的数据定义,代码如下:

复制代码
//单向链表定义
typedef struct LNode *List;
struct LNode
{
	ElementType Data;
	List Next;
}

二、获取单向链表长度

具体代码实现,如下:

复制代码
//获取单向链表长度
int Length(List Pstart)
{
	List p = Pstart;
	int j = 0;

	while(p)
	{
		p = p->Next;
		j++;
	}

	return j;
}

三、单向链表查找数据

3.1 按序号查找

代码实现如下:

复制代码
//1.按序号查找
int FindK(int K, List Ptrl)
{
	List p = Ptrl;
	int i = 0;
	
	while((p != NULL) && (i < K))
	{
		P = P->Next;
		i++;
	}
	
	if(i == K)
	{
		return p;
	}
	else 
	{
		return NULL;
	}
}

3.2 按值查找

代码实现如下:

复制代码
//2.按值查找
int Find(ElementType Val, List Ptrl)
{
	List p = Ptrl;
	
	while((p != NULL) && (p->Data != Val))
	{
		p = p->Next;
	}
	
	return p;
}

四、单向链表插入

在第i-1(1≤i≤n+1)个结点后插入一个值为X的新结点。

1.先构造一个新结点,用s指向;

2.再找到链表的第i-1个结点,用p指向;

3.然后修改指针,插入结点(p之后插入新结点是s)。

链表插入过程如下图所示:

程序实现,如下:

复制代码
//单向链表插入(在第i-1(1≤i≤n+1)个结点后插入一个值为X的新结点)
List Insert(ElementType X,int i,List Ptrl)
{
	List P,S;
	
	if(i == 1)				//新结点插入在表头
	{
		S = (List)malloc(sizeof(stroct LNode));		//申请、填装结点
		S->Data = X;
		S->Next = Ptrl;
		
		return S;			//返回表头指针
	}
	
	P = Find(i-1,Ptrl);		//查找第i-1个结点
	if(P == NULL)			//第i-1个不存在,不能插入
	{
		printf("参数i错\r\n");
		return NULL;
	}
	else
	{
		S = (List)malloc(sizeof(struct LNode));
		S->Data = X;
		S->Next = P->Next;	//新结点插入在第i-1个结点的后面
		P->Next = S;
		
		return Ptrl;
	}
}

五、删除

删除链表的第i(1≤i≤n)个位置上的结点。

1.先找到链表的第i-1个结点,用p表示;

2.再用指针s指向要删除的结点(p的下一个结点);

3.然后修改指针,删除s所指向的结点;

4.最后释放s所指向结点的内存空间。

链表删除过程如下图所示:

程序实现,如下:

复制代码
//删除(删除链表的第i(1≤i≤n)个位置上的结点)
List Delete(int i,List Ptrl)
{
	List p,s;
	
	if(i == 1)						//若删除的是表的第一个结点
	{
		s = Ptrl;					//s指向第一个结点
		if(Ptrl != NULL)
		{
			Ptrl = Ptrl->Next;		//从链表中删除
		}
		else
		{
			return NULL;
		}
		
		free(s);					//释放被删除的结点
		return Ptrl;
	}
	
	p = Find(i-1,Ptrl);				//查找第i-1个结点
	if(p == NULL)
	{
		printf("第%d个结点不存在",i-1);	
		return NULL;
	}
	else if(p->Next == NULL)
	{
		printf("第%d个结点不存在",i);	
		return NULL;
	}
	else
	{
		s = p->Next;				//s指向第i个结点
		p->Next = s->Next;			//从链表中删除结点s
		free(s);					//释放被删除的结点s
		return Ptrl;
	}
}

六、总结

链表的知识点初学起来感觉很抽象,开始时可以先把链表的定义、查找、插入、删除这些基本操作用代码敲一下,然后,最好是实际应用一下,找一个例程把需要处理的数据通过链表存储起来,数据的查找、更新数据插入、删除旧的数据等这些操作都实践一下,只有用了,才能真正理解链表,只学习概念理论,没什么用。

相关推荐
Bdygsl2 小时前
数据结构 —— 栈
数据结构
编程之路,妙趣横生2 小时前
数据结构(十一) 哈希表
数据结构
客梦2 小时前
数据结构--队列
数据结构·笔记
xiaoxue..2 小时前
二叉搜索树 BST 三板斧:查、插、删的底层逻辑
javascript·数据结构·算法·面试
程序员小白条2 小时前
提前实习的好处有哪些?有坏处吗?
java·开发语言·数据结构·数据库·链表
蒙奇D索大2 小时前
【数据结构】排序算法精讲 | 快速排序全解:分治思想、核心步骤与示例演示
数据结构·笔记·学习·考研·算法·排序算法·改行学it
七夜zippoe2 小时前
Python高级数据结构深度解析:从collections模块到内存优化实战
开发语言·数据结构·python·collections·内存视图
sin_hielo11 小时前
leetcode 2483
数据结构·算法·leetcode
大头流矢12 小时前
归并排序与计数排序详解
数据结构·算法·排序算法