[考研系列之数据结构]线性表之链表

1.链表分类

通过线性表概述,我们知道了链表这样一种数据结构,它又分成三类,分别是

  • 单向链表
  • 循环链表
  • 双向链表

单向链表

单向链表的指针域只有一个指向下一个节点的指针,需要注意几点:

1.头指针——指向第一个节点

2.最后一个结点的指针指向NULL

3.头结点——在链表的第一个结点之前附设一个结点,它的数据域为空

所以,我们看到:

 单向链表为空的<=>链表有且只有一个头结点<=>头结点的指针指向NULL

循环链表

循环链表和单向链表最大的不同就是:最后一个结点的指针不再指向NULL而是指向第一个结点。那么:

 循环链表为空的<=>链表有且只有一个头结点<=>头结点的指针指向自己

双向链表

双向链表的指针域有两个,分别为:prior和next:

prior指向前一个结点,next指向后一个结点。

对于双向链表:

双向链表为空的<=>链表有且只有一个头结点<=>头结点的prior和next指针都指向自己

2.关于链表操作

对所有数据结构的操作最基本的都是增删改查,让我们对单向链表的增删改查进行一些分析:

在单向链表中insert一个结点,我们分为两种情况

insert的结点在表尾

insert的结点不在表尾

如果insert的结点在表尾的话,我们要进行的操作就是:

遍历链表到表尾,找到最后一个结点 O(n)
将最后一个结点的指针从NULL改成指向需要insert的结点 O(1)

所以很明显,整个操作的算法复杂度是O(n)

如果insert的结点是在第i个结点之后,而且i<n,整体操作如下:

遍历链表,找到第i个结点 O(n)
让需要插入结点的指针指向第i+1个结点 O(1)
将第i个结点的指针指向需要插入的结点 O(1)

整个算法复杂度也是O(n)

删除操作也分两种情况

delete的结点是最后一个

delete的结点不是最后一个

对于delete的结点是最后一个的情况,操作:

遍历找到最后一个结点和它的前一个结点 O(n)
将它的前一个结点的指针指向NULL O(1)
[如果结点是存储在堆上,可以使用free释放此结点空间] O(1)

而如果delete的结点是第i个,而且i<n,相应的操作

遍历找到第i个结点和它的前一个结点i-1 O(n)
将i-1结点的指针指向第i+1个结点[即将i的指针的值赋给i-1的指针] O(1)
将第i个结点的指针指向NULL O(1)
[如果结点是存储在堆上,可以使用free释放此结点空间] O(1)

对于结点数据域的改操作是建立在查操作之上的,只要找到了这个结点,那么对于数据域的修改就只是赋值那么简单了。

单向链表由于只能从头结点开始向后遍历,所以找到第i个结点也肯定会遍历前面的i-1个结点,关于遍历的算法复杂度:

(数学公式不好机打只好手写了)

扩展

1.两个链表的归并

有两个链表La和Lb,它们同递增或同递减,求一个新的链表Lc,它是La和Lb的元素合并,且Lc也具有相同的递增递减性质

首先,我们明确Lc的长度是

Lc.length=La.length+Lb.length

我们先定义三个指针Pa、Pb和Pc,

初始状态:

Pa指向La的头结点,Pb指向Lb的头结点,Pc指向Lc的头结点

结束状态:

Pa=Pb=Pc=NULL(他们都分别遍历了三个链表)

中间过程:

从初始状态开始,三个指针分别指向三个链表的头,下面用一段伪代码去描述算法(递减):

while(Pa!=NULL&Pb!=NULL)

{

if(Pa->next->data>=Pb->next->data)

{

Pc->next->data=Pa->next->data;

Pa=Pa->next;

}

else

{

Pc->next->data=Pb->next->data;

Pb=Pb->next;

}

Pc=Pc-next;

}

算法的核心就是:每次将Pa和Pc指向的数据比较,如果Da(Data Of La)>=Db(Data Of Lb),则Dc=Da,Da指向下一个结点的数据,这样下次循环就是下一个Da和上一次的Db比较了,每次循环Lc长度都会增加1,增加的数据是Pa和Pb指向元素中较大的。

2.多项式的表示和相加

见严书P39

最后,链表更多的是提供一种数据的表示方法,以后的树和图也会使用链式表示的方法,但是单独作为链表还是会有很多小的知识点和技巧的,更多的可以看我以前的一篇博客:

http://blog.csdn.net/acidsweet/article/details/8642689

[考研系列之数据结构]线性表之链表,布布扣,bubuko.com

时间: 2024-08-05 18:43:58

[考研系列之数据结构]线性表之链表的相关文章

[考研系列之数据结构]线性表概述

1.脑图 2.表示方法 按照数据结构概述所说,线性表有两种表示方法分别是顺序表示和链式表示,链表就是链式表示的典型. 我们知道链式表示是分配了n块内存空间,可以认为彼此不连续,所以不能用偏移量去定位每个元素. 下面就先说最简单的单向链表: 如果每个数据元素能有一个指针指向下一个元素的话,那么只需要知道第一个数据元素就能一个一个的遍历整个链表了,这就是单向链表. 对于每个链表元素我们称之为节点,每个节点都有两个域:数据域&指针域 数据域就是数据元素所在的区域,而指针域则是存储指向另一个节点的指针的

[考研系列之数据结构]线性表之队列

基本概念 队列的定义 队列是一种只能在表的一头插入,另一头删除的线性表,简而言之具有FIFO的特性 组成 队头 队尾 扩展 双端队列 只能在两端进行删除插入操作的线性表 实现 链队列 顺序队列 循环队列 循环队列 循环队列是将顺序队列臆造成一个环,如图 循环队列有以下参数 front 指向队头的指针 rear 指向队尾的指针 SIZE 循环最大队列长度 对于循环队列,初始状态的时候 front=rear=0; 每次insert的时候 Insert((front++)%SIZE); 那么,当循环队

[考研系列之数据结构]线性表之栈

?基本概念 栈的定义 限定仅在表尾进行插入或删除的线性表 组成 栈顶 栈底 基本操作 入栈(PUSH) 往栈中插入一个元素 弹栈(POP) 从栈顶删除一个元素 栈的表示 顺序栈 链栈 对于顺序栈,有两个指针base和top base指向栈底 top指向栈顶 对于栈的一些基本情况: 栈不存在时候 base=NULL 栈为空时  top=base 栈的长度 top-base 链栈略过. 栈的应用 1 数制转换 数制转换我们使用一种称之为"辗转相除法"的算法.此算法的基本原理基于: N=(N

[考研系列之数据结构]线性表之字符串

基本概念 串(字符串)  由0个或多个字符组成的有限序列,例如s="hello world" 串名  上例中的s 子串  某串任意连续字符组成的子序列,称为此字符串的子串 空串  0个字符的串,s="" 空格串  由一个或多个字符组成的串 模式匹配算法 作用 定位某子串T在字符串S中的位置 主串 S 模式串  T 针对模式匹配算法从简到难我们需要了解两种算法: [1] 朴素的模式匹配算法 [2] KMP匹配算法 朴素的模式匹配算法: 所谓朴素就是简单,这是一种简单的

C语言 严蔚敏数据结构 线性表之链表实现

博主最近在考成都大学皇家计算机科学与技术专业,复习专业课数据结构,正好学习到线性结构中的线性表用链表这种存储结构来实现. 首先,数据结构包括1.数据的操作2.逻辑结构3.存储结构(数据结构三要素. 直接上代码,现阶段代码实现功能有:链表初始化.遍历.增.删.返回链表长度,后续功能陆续发布.其中肯定有很多问题,希望各位码哥留言. Linklist* InitList(int i)//i为链表大小 { Linklist *head; head = (Linklist*)malloc(sizeof(L

再回首,数据结构——线性表、链表上的常见算法

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. //1.编写算法实现线性表就地逆置的操作 void InverseList (SeqList l) { for (i = 0; i <= (l.length-1)/2; i++) { l.elem[i] <-> l.elem[l.length-1-i]; } } //2.从顺序表中删除自第i个元素开始的k个元素 void DeleteList(SeqList l, int

数据结构-线性表-静态链表

对于线性链表,也可用一维数组来进行描述.这种描述方法便于在没有指针类型的高级程序设计语言中使用链表结构. 静态链表是利用数组来实现,只是改变了实现方式,实际上链式存储说的存储的方式,数组只是实现的方式,不能将静态链表看做是顺序存储. 数组的元素都是由两个数据域组成,data和cur.也就是说,数组的每一个下标都对应一个data和一个cur. 数据域data用来存放数据元素,也就是通常我们要处理的数据:而游标cur相当于单链表中的next指针, 存放该元素的后继在数组中的下标.我们把这种用数组描述

Java数据结构-线性表之链表应用-检测链表是否有环

??如何检测一个链表是否有环?这个是一个出现频率较高的面试题. ??如下是一个含有环的链表. (图片来自http://www.nowamagic.net/librarys/veda/detail/2245 一个有很多关于数据结构的文章的网站,还有其他的资料,可以看看) 我这里解题的方法有三种: 快慢指针方法:两个速度不一样的指针遍历总会相遇: 利用环的顶点数和边相等的关系: 两个指针遍历判断步数是否相等. ??为了实现检查链表是否含有环的情况,我们需要先构建出一个含有环的链表. ??于是乎我在之

(源代码见大话数据结构)线性表—静态链表

#include <stdio.h> #include <stdlib.h> #include <time.h> #define MAXSIZE 1000 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALS 0 typedef int ElemType; typedef int Status; typedef struct { ElemType data; int cur; } Component,Stati