IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 单链表详解(学习笔记) -> 正文阅读

[数据结构与算法]单链表详解(学习笔记)

tips:

目录

tips:

一.链表的概念和定义

二.链表的建立

三.链表元素的读取

四.链表结点的删除

五.链表结点的插入


#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define Error 0
typedef int Status

Status是函数类型。

链表是一种链式储存结构,在C语言中有着重要的作用。

而在如同我一样的初学者的学习过程中,链表的操作很有难度,故而有必要用博客记录学习过程,分享给大家的同时也自我巩固。

一.链表的概念和定义

相对于线性表,链表有许多优点,例如在线性表中,删除或插入元素的操作很复杂,需要将插入或删除位置的前/后元素不停地移动,倘若涉及到频繁地插入或者删除的操作,链表的优点就凸显出来了。

链表作为一种链式存储结构,其的存储内容除了要存的数据元素信息之外,还储存着后继元素的存储地址。为了表示链表中每一个存储元素a(i)与其直接后继元素a(i+1)的关系,需要存储一个代表该后继元素信息的存储内容,即该元素的地址。

我们把存储当前元素信息的域称为数据域,把存储后继元素信息的域称为指针域。这两部分组合而成的一个存储单元称为节点(Node)。

?上图即为一个节点的图示,图示中,data是数据域,next就是指针域。顾名思义,next作为指针域,其存储的就是指针类型的数据,即是一个地址。

对于链表来说,需要有头有尾,因此我们通常定义一个头节点head(自行命名),head的数据域一般不存储信息,其指针与存储着第一个节点的地址。有了头节点,尾巴也不例外。作为链表的尾端,尾节点的指针域当然为空,一般用“NULL”表示。

上图为链表的结构图解,转载自其他博主的博客。

二.链表的建立

要完成一个链表的建立,与线性表相同,链表的存储形式也是结构体。

typedef struct Node {
	int data;
	struct Node* next;
	
}Node;
typedef struct Node* Linklist;//定义Linklist

下面进行完整链表的建立的代码进程

创建单链表的过程就是一个动态生成链表的过程,即从头开始,依次建立结点,并插入链表。

思路如下:

1.声明结点p,以及计数所用数字i。

2.将数字赋值给p->data。

3.将p插入链表。

另外有必要说明的是,链表的创建有头插法和尾插法两种方式,下面我会分别提出。

(1)头插法

顾名思义头插法就是将新结点插入到下一结点的前方。代码如下:

void creat(Linklist head,int n)
{
	Linklist p;
	int i;
	//这里假设head已经被建立且其指针域为NULL
	for (i; i < n; i++)
	{
		p = (Linklist)malloc(sizeof(Node));//生成新结点
		scanf("%d", p->data);
		p->next = head->next;
		head->next = p;//插入到下一个头节点的后面一个结点
	}
}

(2)尾插法

与头插法相反,尾插法的插入方式是将新节点插入到目前链表末尾结点的后方。代码如下:

void creat(Linklist head,int n)
{
	Linklist p;
	int i;
	//这里假设head已经被建立且其指针域为NULL
	for (i; i < n; i++)
	{
		p = (Linklist)malloc(sizeof(Node));//生成新结点
		scanf("%d", p->data);
		head->next = p;
		head = p;//插入到尾部
	}
}

三.链表元素的读取

思路如下:

1.给出一个结点的位置

2.由于链表的链式存储结构,需要遍历链表至该位置

3.输出该位置的数据信息

代码如下:

void creat(Linklist head,int n)//n代表要读取的结点的位置
{
	Linklist t;
	t = head;//定义一个移动结点t指向head
	for (int i = 1; i <= n&&t!=NULL; i++)
	{
		t = t->next;
	}
	if (t != NULL)
	{
		printf("%d", t->data);
	}
	else {
		printf("结点不存在!");
	}
}

四.链表结点的删除

在实际应用内,有建立则必然少不了删除的操作。

与链表的读取相似,删除之前需要将链表先进行遍历。

但是值得思考的是,链表每一个结点都存储着数据域和指针域,那么如何才能完成链表的删除操作呢?

我用图解来讲述这个问题:

?一目了然,我们直接将p的指针域指向p->next->next,即可完成一半的删除操作,这时候链表依然是完整的。那我们不禁会想到,q的指针域仍然存在,其指向仍然是q->next,只是结点q已经被排除在链表之外了。这时候我们就需要用到free(q)这个操作来完成对q所占内存空间的释放了。

代码如下:

void creat(Linklist head,int n)//n代表要删除的结点的位置
{
	Linklist t;
	t = head;//定义一个移动结点t指向head
	for (int i = 1; i < n&&t!=NULL; i++)
	{
		t = t->next;
	}
	if (t != NULL&&t->next!=NULL)
	{
		Linklist q = t->next;
		t = t->next->next;
		free(q);
	}
	else {
		printf("结点不存在!");
	}
}

五.链表结点的插入

与删除类似,删除的操作是使链表跳过要删除的结点,而插入是将一个新节点插入到该插入的位置

?但是在插入操作时要注意操作顺序。

即先将新节点s的指针域指向a1,再将原本a1之前的结点的指针域指向s。代码我在此就不再赘述。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-19 18:27:38  更:2021-12-19 18:28:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:28:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码