链表基础知识详解

news2025/2/27 23:17:27

链表基础知识详解

  • 一、链表是什么?
    • 1.链表的定义
    • 2.链表的组成
    • 3.链表的优缺点
    • 4.链表的特点
  • 二、链表的基本操作
    • 1.链表的建立
    • 2.链表的删除
    • 3.链表的查找
    • 4.链表函数

链表基础知识详解

一、链表是什么?

1.链表的定义


链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

2.链表的组成


链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

3.链表的优缺点


使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。

4.链表的特点

线性表的链式存储表示的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素 与其直接后继数据元素 之间的逻辑关系,对数据元素 来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。由这两部分信息组成一个"结点"(如概述旁的图所示),表示线性表中一个数据元素。线性表的链式存储表示,有一个缺点就是要找一个数,必须要从头开始找起,十分麻烦。
根据情况,也可以自己设计链表的其它扩展。但是一般不会在边上附加数据,因为链表的点和边基本上是一一对应的(除了第一个或者最后一个节点,但是也不会产生特殊情况)。不过有一个特例是如果链表支持在链表的一段中把前和后指针反向,反向标记加在边上可能会更方便。
对于非线性的链表,可以参见相关的其他数据结构,例如树、图。另外有一种基于多个线性链表的数据结构:跳表,插入、删除和查找等基本操作的速度可以达到O(平衡二叉树一样。
其中存储数据元素信息的域称作数据域(设域名为data),存储直接后继存储位置的域称为指针域(设域名为next)。指针域中存储的信息又称做指针或链。
由分别表示,,…,的N 个结点依次相链构成的链表,称为线性表的链式存储表示,由于此类链表的每个结点中只包含一个指针域,故又称单链表或线性链表。

二、链表的基本操作

1.链表的建立

第一行读入n,表示n个数
第二行包括n个数
以链表的形式存储输出这些数

program project1;
type
    point=^node;
    node=record
        data:longint;
        next:point;
    end;
var
    i,n,e:longint;
    p,q,head,last:point;

begin
    write('Input the number count:');
    readln(n);
    i:=1;
    new(head);
    read(e);
    head^.data:=e;
    head^.next:=nil;
    last:=head;
    q:=head;
    while i<n do
        begin
            inc(i);
            read(e);
            new(p);
            q^.next:=p;
            p^.data:=e;
            p^.next:=nil;
            last:=p;
            q:=last
        end;
    //建立链表
    q:=head;
    while q^.next<>nil do
        begin
            write(q^.data,'');
            q:=q^.next;
        end;
    write(q^.data);
    //输出
    readln;
    readln
    end.

2.链表的删除

在以z为头的链表中搜索第一个n,如果找到则删去,返回值为1,否则返回0

function delete(n:longint;var z:point):longint;
    var
        t,s:point;

    begin
        t:=z;
        while(t^.next<>nil)and(t^.data<>n)do
            begin
                s:=t;
                t:=t^.next;
            end;
        if t^.data<> nthen exit(0);
        s^.next:=t^.next;
        dispose(t);
        exit⑴
    end;

3.链表的查找

类似于删除,只需要找到不删即可
插入
插入,在以zz为头的链表第w个的前面插入nn元素,函数返回值正常是0,如果w超过了链表的长度,函数返回链表的长度

function insert(w,nn:longint;var zz:point):longint;
var d:longint;v,vp,vs:point;

begin
    v:=zz;
    for d:=1 to w do
    if v^.next=nil
        then exit(d)
    else
        begin
            vp:=v;
            v:=v^.next;
        end;

    new(vs);
    vs^.data:=nn;
    vp^.next:=vs;
    vs^.next:=v;
    exit(0)
end;

4.链表函数

#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>

usingnamespacestd;

structNode
{
intdata;//数据域
structNode*next;//指针域
};

/*
Create
*函数功能:创建链表.
*输入:各节点的data
*返回值:指针head
*/
Node*Create()
{
intn=0;
Node*head,*p1,*p2;
p1=p2=newNode;
cin>>p1->data;
head=NULL;
while(p1->data!=0)
{
if(n==0)
{
head=p1;
}
else
p2->next=p1;
p2=p1;
p1=newNode;
cin>>p1->data;
n++;
}
p2->next=NULL;
returnhead;
}

/*
insert
*函数功能:在链表中插入元素.
*输入:head链表头指针,p新元素插入位置,x新元素中的数据域内容
*返回值:无
*/
voidinsert(Node*head,intp,intx)
{
Node*tmp=head;//for循环是为了防止插入位置超出了链表长度
for(inti=0;i<p;i++)
{
if(tmp==NULL)
return;
if(i<p-1)
tmp=tmp->next;
}
Node*tmp2=newNode;
tmp2->data=x;
tmp2->next=tmp->next;
tmp->next=tmp2;
}

/*
del
*函数功能:删除链表中的元素
*输入:head链表头指针,p被删除元素位置
*返回值:被删除元素中的数据域.如果删除失败返回-1
*/
intdel(Node*head,intp)
{
Node*tmp=head;
for(inti=0;i<p;i++)
{
if(tmp==NULL)
return-1;
if(i<p-1)
tmp=tmp->next;
}
intret=tmp->next->data;
tmp->next=tmp->next->next;
returnret;
}

voidprint(Node*head)
{
for(Node*tmp=head;tmp!=NULL;tmp=tmp->next)
printf("%d",tmp->data);
printf("\n");
}

intmain()
{
Node*head;
head=newNode;
head->data=-1;
head->next=NULL;
return0;
}
例子
#include<iostream>
#defineNULL0
structstudent
{
longnum;
structstudent*next;
};
intmain()
{
inti,n;
student*p=(structstudent*)malloc(sizeof(structstudent));
student*q=p;
printf("输入几个值");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&(q->num));
q->next=(structstudent*)malloc(sizeof(structstudent));
q=q->next;
}
printf("值第几个");
intrank;
scanf("%d%d",&(q->num),&rank);
student*w=p;
for(i=1;i<rank-1;i++)
{
w=w->next;
}
q->next=w->next;
w->next=q;
for(i=1;i<=n+1;i++)
{
printf("%d",p->num);
p=p->next;
}
return0;
}//指针后移麻烦链表形式循环链表

循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链。

循环链表的运算与单链表的运算基本一致。所不同的有以下几点:
1、在建立一个循环链表时,必须使其最后一个结点的指针指向表头结点,而不是象单链表那样置为NULL。此种情况还使用于在最后一个结点后插入一个新的结点。
2、在判断是否到表尾时,是判断该结点链域的值是否是表头结点,当链域值等于表头指针时,说明已到表尾。而非象单链表那样判断链域值是否为NULL。
双向链表
双向链表其实是单链表的改进。
当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。
在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。
应用举例概述
约瑟夫环问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。例如:n = 9,k = 1,m = 5

参考代码

#include<stdio.h>
#include<malloc.h>
#defineN41
#defineM5
typedefstructnode*link;
structnode
{
intitem;
linknext;
};
linkNODE(intitem,linknext)
{
linkt=malloc(sizeof*t);
t->item=item;
t->next=next;
returnt;
}
intmain(void)
{
inti;
linkt=NODE(1,NULL);
t->next=t;
for(i=2;i<=N;i++)
t=t->next=NODE(i,t->next);
while(t!=t->next)
{
for(i=1;i<M;i++)
t=t->next;
t->next=t->next->next;
}
printf("%d\n",t->item);
return0;
}

如若本文能帮您, 希望您能关注Python老吕的CSDN博客 ;
您可以在本文进行评论,老吕将努力快速回复,和您近距离交流各种问题;
博主ID:Python老吕,希望大家点赞、评论、收藏。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1504526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能|机器学习——K-means系列聚类算法k-means/ k-modes/ k-prototypes/ ......(划分聚类)

1.k-means聚类 1.1.算法简介 K-Means算法又称K均值算法&#xff0c;属于聚类&#xff08;clustering&#xff09;算法的一种&#xff0c;是应用最广泛的聚类算法之一。所谓聚类&#xff0c;即根据相似性原则&#xff0c;将具有较高相似度的数据对象划分至同一类簇&#xff0c;…

【Docker】golang使用DockerFile正确食用指南

【Docker】golang使用DockerFile正确食用指南 大家好 我是寸铁&#x1f44a; 总结了一篇golang使用DockerFile正确食用指南✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 问题背景 今天寸铁想让编写好的go程序在docker上面跑&#xff0c;要想实现这样的效果&#xff0c;就需要用…

流放者柯南服务器端搭建!

这是一个开放世界生存游戏。在这个游戏里&#xff0c;你可以建造自己的城堡&#xff0c;探索神秘的遗迹&#xff0c;与野兽和敌人战斗&#xff0c;甚至成为一个神。 首先推荐服务器配置&#xff1a; 4核16G 月50 季度200 8核32G 月120 季度350 含安装搭建服务&#xff01…

《剑指 Offer》专项突破版 - 面试题 76 : 数组中第 k 大的数字(C++ 实现)

目录 详解快速排序 面试题 76 : 数组中第 k 大的数字 详解快速排序 快速排序是一种非常高效的算法&#xff0c;从其名字可以看出这种排序算法最大的特点是快。当表现良好时&#xff0c;快速排序的速度比其他主要对手&#xff08;如归并排序&#xff09;快 2 ~ 3 倍。 快速排…

WordPress高端后台美化WP Adminify Pro优化版

后台UI美化WP Adminify Pro修改自定义插件&#xff0c;适合建站公司和个人使用&#xff0c;非常高大上&#xff0c;下载地址&#xff1a;WP Adminify Pro优化版 修复记录&#xff1a; 1、修复已知BUG 2、修复手机版兼容问题 3、修复打开速度&#xff0c;原版打开速度太慢 4…

Git的基本操作(安装Git,创建本地仓库,配置Git,添加、修改、回退、撤销修改、删除文件)

文章目录 一、Git安装二、创建本地仓库三、配置Git四、认识工作区、暂存区、本地库五、添加文件六、修改文件七、版本回退八、撤销修改1.对于⼯作区的代码&#xff0c;还没有add2.已经add&#xff0c;但没有commit3.已经add&#xff0c;并且已经commit 九、删除⽂件 一、Git安装…

解释区块链技术的应用场景、优势及经典案例

目录 1.区块链应用场景 2.区块链优势 3.区块链经典案例 区块链技术是一种分布式账本技术&#xff0c;它通过加密和安全验证机制&#xff0c;允许网络中的多个参与者之间进行可信的、不可篡改的交易和数据的记录与传输。区块链技术的应用场景广泛&#xff0c;其优势也十分显著…

R语言复现:中国Charls数据库一篇现况调查论文的缺失数据填补方法

编者 在临床研究中&#xff0c;数据缺失是不可避免的&#xff0c;甚至没有缺失&#xff0c;数据的真实性都会受到质疑。 那我们该如何应对缺失的数据&#xff1f;放着不管&#xff1f;还是重新开始?不妨试着对缺失值进行填补&#xff0c;简单又高效。毕竟对于统计师来说&#…

【AcWing】蓝桥杯集训每日一题Day1|二分|差分|503.借教室(C++)

503. 借教室 503. 借教室 - AcWing题库难度&#xff1a;简单时/空限制&#xff1a;1s / 128MB总通过数&#xff1a;8052总尝试数&#xff1a;26311来源&#xff1a;NOIP2012提高组算法标签二分差分 题目内容 在大学期间&#xff0c;经常需要租借教室。 大到院系举办活动&…

Yolov8模型用torch_pruning剪枝

目录 &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及时查看不迷路&#x1f680;&#x1f680;&#x1f680; 原理 遍历所有分组 高级剪枝器 &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及时查看不迷路&#x1f680;&#x1f680…

TYPE C模拟耳机POP音产生缘由

关于耳机插拔的POP音问题&#xff0c;小白在之前的文章中讲述过关于3.5mm耳机的POP音产生原因。其实这类插拔问题的POP音不仅仅存在于3.5mm耳机&#xff0c;就连现在主流的Type C模拟耳机的插拔也存在此问题&#xff0c;今天小白就来讲一讲这类耳机产生POP音的缘由。 耳机左右…

计算机视觉——P2PNet基于点估计的人群计数原理与C++模型推理

简介 人群计数是计算机视觉领域的一个核心任务&#xff0c;旨在估算静止图像或视频帧中的行人数量。在过去几十年中&#xff0c;研究人员在这个领域投入了大量的精力&#xff0c;并在提高现有主流基准数据集性能方面取得了显著进展。然而&#xff0c;训练卷积神经网络需要大规…

书与我

和书深深结缘&#xff0c;始于需求&#xff0c;得益于通勤时间长。 读什么书 一直没有停止过编码&#xff0c;工作性质也要求我必须了解很多的新技术&#xff0c;从踏上工作岗位后&#xff0c;就需要不停的看书。从《JAVA编程思想》、《java与模式》、《TCP/IP详解》、《深入…

131.分割回文串

// 定义一个名为Solution的类 class Solution {// 声明一个成员变量&#xff0c;用于存储所有满足条件的字符串子序列划分结果List<List<String>> lists new ArrayList<>(); // 声明一个成员变量&#xff0c;使用LinkedList实现的双端队列&#xff0c;用于临…

Windows下安装pip

一、下载pip 官网地址&#xff1a;https://pypi.org/project/pip/#files 1.1、pip工具查找方法 单击官网首页“PyPi”选项 在弹出来的搜索框中输入“pip” 选择最新的pip版本&#xff0c;点进去 下载pip安装包包 二、安装pip 解压“pip-24.0.tar.gz”&#xff0c;进…

【深度学习笔记】6_5 RNN的pytorch实现

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 6.5 循环神经网络的简洁实现 本节将使用PyTorch来更简洁地实现基于循环神经网络的语言模型。首先&#xff0c;我们读取周杰伦专辑歌词…

b站小土堆pytorch学习记录—— P23-P24 损失函数、反向传播和优化器

文章目录 一、损失函数1.简要介绍2.代码 二、优化器1.简要介绍2.代码 一、损失函数 1.简要介绍 可参考博客&#xff1a; 常见的损失函数总结 损失函数的全面介绍 pytorch学习之十九种损失函数 损失函数&#xff08;Loss Function&#xff09;是用来衡量模型预测输出与实际…

开发指南002-前后端信息交互规范-概述

前后端之间采用restful接口&#xff0c;服务和服务之间使用feign。信息交互遵循如下平台规范&#xff1a; 前端&#xff1a; 建立api目录&#xff0c;按照业务区分建立不同的.js文件&#xff0c;封装对后台的调用操作。其中qlm*.js为平台预制的接口文件&#xff0c;以qlm_user.…

离线数仓(五)【数据仓库建模】

前言 今天开始正式数据仓库的内容了, 前面我们把生产数据 , 数据上传到 HDFS , Kafka 的通道都已经搭建完毕了, 数据也就正式进入数据仓库了, 解下来的数仓建模是重中之重 , 是将来吃饭的家伙 ! 以及 Hive SQL 必须熟练到像喝水一样 ! 第1章 数据仓库概述 1.1 数据仓库概念 数…

【stm32 外部中断】

中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运行 中断优先级&#xff1a;当有多个中…