麻烦给看一下怎么看数据结构的根节点题,尾指针指向最后一个节点,为什么选项B需要遍历链表,而选项D不需要遍历呢?

单链表的操作算法是笔试面试中較为常见的题目本文将着重介绍平时面试中常见的关于链表的应用题目。

本文大概 一万五千字 建议阅读时间为一个小时,请先收藏再閱读平时也可以拿出来多看几遍。

2 输出单链表倒数第 K 个节点

题目:输入一个单链表输出此链表中的倒数第 K 个节点。(去除头结点节點计数从 1 开始)。

(1)遍历单链表遍历同时得出链表长度 N 。 (2)再次从头遍历访问至第 N - K 个节点为所求节点。

/*查找第k个节点的值*/

采用这種遍历方式需要两次遍历链表时间复杂度为O(n※2)。可见这种方式最为简单,也较好理解但是效率低下。

(1)定义num = k (2)使用递归方式遍历至鏈表末尾 (3)由末尾开始返回,每返回一次 num 减 1 (4)当 num 为 0 时即可找到目标节点

使用递归的方式实现仍然需要两次遍历链表,时间复杂度為O(n※2)

(1)定义两个指针 p1 和 p2 分别指向链表头节点。 (2)p1 前进 K 个节点则 p1 与 p2 相距 K 个节点。 (3)p1p2 同时前进,每次前进 1 个节点 (4)当 p1 指向到達链表末尾,由于 p1 与 p2 相距 K 个节点则 p2 指向目标节点。

//p1p2均指向头节点 //p1先出发,前进K个节点 if (p1)//防止k大于链表节点的个数

可以看出使用双指针法呮需遍历链表一次这种方法更为高效时间复杂度为O(n),通常笔试题目中要考的也是这种方法

3.1 判断链表是否有环

单链表中的环是指链表末尾的节点的 next 指针不为 NULL ,而是指向了链表中的某个节点导致链表中出现了环形结构。

链表的末尾节点 8 指向了链表中的节点 3导致链表中出現了环形结构。 对于链表是否是由有环的判断方法有哪些呢

(1)遍历链表,记录已访问的节点 (2)将当前节点与之前以及访问过的节點比较,若有相同节点则有环 否则,不存在环

这种穷举比较思想简单,但是效率过于低下尤其是当链表节点数目较多,在进行比较時花费大量时间时间复杂度大致在 O(n^2)。这种方法自然不是出题人的理想答案如果笔试面试中使用这种方法,估计就要跪了忘了这种方法吧

既然在穷举遍历时元素比较过程花费大量时间,那么有什么办法可以提高比较速度呢

(1)首先创建一个以节点 ID 为键的 HashSe t集合,用來存储曾经遍历过的节点 (2)从头节点开始,依次遍历单链表的每一个节点 (3)每遍历到一个新节点,就用新节点和 HashSet 集合当中存储的節点作比较如果发现 HashSet 当中存在相同节点 ID,则说明链表有环如果 HashSet 当中不存在相同的节点 ID,就把这个新节点 ID 存入 HashSet 之后进入下一节点,继續重复刚才的操作

假设从链表头节点到入环点的距离是 a ,链表的环长是 r 而每一次 HashSet 查找元素的时间复杂度是 O(1), 所以总体的时间复杂度是 1 * ( a + r ) = a + r,鈳以简单理解为 O(n) 而算法的空间复杂度还是 a + r - 1,可以简单地理解成 O(n)

(1)定义两个指针分别为 slow,fast并且将指针均指向链表头节点。 (2)规定slow 指针每次前进 1 个节点,fast 指针每次前进两个节点 (3)当 slow 与 fast 相等,且二者均不为空则链表存在环。

通过图解过程可以看出若表中不存茬环形,fast 与 slow 指针只能在链表末尾相遇

图解过程可以看出,若链表中存在环则快慢指针必然能在环中相遇。这就好比在环形跑道中进行龜兔赛跑由于兔子速度大于乌龟速度,则必然会出现兔子与乌龟再次相遇情况因此,当出现快慢指针相等时且二者不为NULL,则表明链表存在环

//当没有到达链表结尾,则继续前进 //到达末尾仍然没有相遇则不存在环

在 3.1 节中,已经实现了链表中是否有环的判断方法那么,当链表中存在环如何确定环的入口节点呢?

n * r; 意味着slow指针走过的长度为环的长度整数倍

从头结点出发,前进 a 步当 p1 与 p2 相遇时,此时 p1 与 p2 均指向入口节点

//找到环中的相遇节点
 //当没有到达链表结尾,则继续前进
 //到达末尾仍然没有相遇则不存在环
 while (p1 != p2) // p1和p2以相同的速度向前移动,當p2指向环的入口节点时p1已经围绕着环走了n圈又回到了入口节点。
 

 
 
在3.1中找到了 slow 与 fast 的相遇节点令 solw 与 fast 指针从相遇节点出发,按照之前的前进規则当 slow 与fast 再次相遇时,slow 走过的长度正好为环的长度
 

 //当slow与fast再次相遇,得到环长度
 

4 使用链表实现大数加法

 

 
两个用链表代表的整数其中每個节点包含一个数字。数字存储按照在原来整数中相反的顺序使得第一个数字位于链表的开头。写出一个函数将两个整数相加用链表形式返回和。
 

 //保留计算结果的个位
 //若l1到达末尾说明l1长度小于l2
 //l1指针指向l2节点当前位置
 //最高位计算有进位,则新建一个节点保留最高位
 

 

 
题目:将两个有序链表合并为一个新的有序链表并返回新链表是通过拼接给定的两个链表的所有节点组成的。
 

 
 

(1)对空链表存在的情况进行處理假如 pHead1 为空则返回 pHead2 ,pHead2 为空则返回 pHead1(两个都为空此情况在pHead1为空已经被拦截) (2)在两个链表无空链表的情况下确定第一个结点,比较鏈表1和链表2的第一个结点的值将值小的结点保存下来为合并后的第一个结点。并且把第一个结点为最小的链表向后移动一个元素 (3)繼续在剩下的元素中选择小的值,连接到第一个结点后面并不断next将值小的结点连接到第一个结点后面,直到某一个链表为空 (4)当两個链表长度不一致时,也就是比较完成后其中一个链表为空此时需要把另外一个链表剩下的元素都连接到第一个结点的后面。

 
 

 
 

(1)对空鏈表存在的情况进行处理假如 pHead1 为空则返回 pHead2 ,pHead2 为空则返回 pHead1 (2)比较两个链表第一个结点的大小,确定头结点的位置 (3)头结点确定后繼续在剩下的结点中选出下一个结点去链接到第二步选出的结点后面,然后在继续重复(2 )(3) 步直到有链表为空。

 
 

6 删除链表中节点偠求时间复杂度为O(1)

 

 
给定一个单链表中的表头和一个等待被删除的节点。请在 O(1) 时间复杂度删除该链表节点并在删除该节点后,返回表头

 
茬之前介绍的单链表删除节点中,最普通的方法就是遍历链表复杂度为O(n)。 如果我们把删除节点的下一个结点的值赋值给要删除的结点嘫后删除这个结点,这相当于删除了需要删除的那个结点因为我们很容易获取到删除节点的下一个节点,所以复杂度只需要O(1)
 
如果删除嘚节点的是头节点,把头结点指向 NULL 如果删除的节点的是尾节点,那只能从头遍历到头节点的上一个结点

 

 //下一个节点值赋给待删除节点
 //待删除节点指针指后面第二个节点
 //删除待删除节点的下一个节点
 

 

 
输入一个链表,按链表值从尾到头的顺序返回一个 ArrayList

 
初看题目意思就是输絀的时候链表尾部的元素放在前面,链表头部的元素放在后面这不就是 先进后出,后进先出
什么怎么看数据结构的根节点符合这个偠求?

 

 
第二种方法也比较容易想到通过链表的构造,如果将末尾的节点存储之后剩余的链表处理方式还是不变,所以可以使用递归的形式进行处理

 

 

 


进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题

 
  • (1)每次查看cur节点是否为NULL,如果是则结束循环,获嘚结果
  • (2)如果cur节点不是为NULL则先设置临时变量nextcur的下一个节点
  • (3)让cur的下一个节点变成指向pre,而后pre移动curcur移动到next
  • (4)重复(1)(2)(3)
 

 

 
 
8.4.2 遞归的方式处理
 

 
本文由小吴和他的小伙伴 进击的Hello_World 共同整理完成~

通过本文的学习,以后遇到有关链表的面试问题我们有哪些思路去解决

是具有相同数据类型的数据元素嘚一个有限序列通常表示为:(a1,a2… ai,ai+1… an)

线性表的顺序存储是指用一组地址连续的存储单元依次存放线性表的数据元素这种存储形式的线性表称为顺序表。它的特点是线性表中相邻的元素在内存中的存储位置也是相邻的由于线性表中的所有数据元素属于同一类型,所以每个元素在存储中所占的空间大小相同

优点:顺序存储结构内存的存储密度高,可以节约存储空间并可以随机或顺序地存取结點,但是插入和删除操作时往往需要移动大量的数据元素并且要预先分配空间,并要按最大空间分配因此存储空间得不到充分的利用,从而影响了运行效率

线性表的链式存储结构,它能有效地克服顺序存储方式的不足同时也能有效地实现线性表的扩充。

单链表和循環链表(循环链表是单链表的变形)

线性表的链式存储结构是用一组地址任意的存储单元存放线性表中的数据元素除了存储其本身的值の外,还必须有一个指示该元素直接后继存储位置的信息即指出后继元素的存储位置。这两部分信息组成数据元素ai的存储映像称为结點(node)。每个结点包括两个域:一个域存储数据元素信息称为数据域;另一个存储直接后继存储位置的域称为指针域。

指针域中存储的信息称做指针或链N个结点链结成一个链表,由于此链表的每一个结点中包含一个指针域故又称线性链表或单链表

循环链表最后一个結点的next指针不为空而是指向了表的前端。为简化操作在循环链表中往往加入表头结点。

循环链表的特点是:只要知道表中某一结点的哋址就可搜寻到所有其他结点的地址。

双向链表是指在前驱和后继方向都能游历(遍历)的线性链表

在双向链表结构中,每一个结点除了數据域外还包括两个指针域,一个指针指向该结点的后继结点另一个指针指向它的前趋结点。通常采用带表头结点的循环链表形式

鼡数组实现表时,利用了数组单元在物理位置上的邻接关系表示表元素之间的逻辑关系

无须为表示表元素之间的逻辑关系增加额外的存儲空间。

可以方便地随机存取表中任一位置的元素

插入和删除运算不方便,除表尾位置外在表的其他位置上进行插入或删除操作都须迻动大量元素,效率较低

由于数组要求占用连续的存储空间,因此在分配数组空间时只能预先估计表的大小再进行存储分配。当表长變化较大时难以确定数组的合适的大小

顺序表的存储空间可以是静态分配的,也可以是动态分配的链表的存储空间是动态分配的。

顺序表可以随机或顺序存取链表只能顺序存取。

顺序表进行插入/删除操作平均需要移动近一半元素链表则修改指针不需要移动元素。

若插入/删除仅发生在表的两端宜采用带尾指针的循环链表。

存储密度=结点数据本身所占的存储量/结点结构所占的存储总量

顺序表的存储密度= 1,链表的存储密度< 1

总结:顺序表是用数组实现的,链表是用指针实现的用指针来实现的链表,结点空间是动态分配的链表又按鏈接形式的不同,区分为单链表、双链表和循环链表


是限定仅在表尾进行插入或删除操作的线性表。栈是一种后进先出(Last In First Out)/先进后出的线性表简称为LIFO表

用指针实现栈—链(式)栈链式栈

无栈满问题,空间可扩充

插入与删除仅在栈顶处执行

1)为待进栈元素x申请一个新结点并把x赋給 该结点的值域。

2)将x结点的指针域指向栈顶结点

3)栈顶指针指向x结点,即使x结点成为新的栈顶结点

1)检查栈是否为空,若为空进荇错误处理。

2)取栈顶指针的值并将栈顶指针暂存。

是只允许在表的一端进行插入而在另一端进行删除的运算受限的线性表。其所有嘚插入均限定在表的一端进行该端称为队尾(Rear);所有的删除则限定在表的另一端进行,该端则称为队头(Front)如果元素按照a1,a2a3....an的顺序进入队列,则出队列的顺序不变也是a1,a2a3....an。所以队列具有先进先出(First In First Out简称FIFO)/后进后出特性。如车站排队买票排在队头的处理完走掉,后来的则必须排在队尾等待在程序设计中,比较典型的例子就是操作系统的作业排队

队列的顺序存储结构称为顺序队列,顺序队列实际上是运算受限的顺序表和顺序表一样,顺序队列也是必须用一个数组来存放当前队列中的元素由于队列的队头和队尾的位置是變化的,因而要设两个指针分别指示队头和队尾元素在队列中的位置

循环队列是为了克服顺序队列中“假溢出”,通常将一维数组Sq.elem[0]到Sq.elem.[MaxSize-1]看荿是一个首尾相接的圆环即Sq.elem[0]与Sq.elem .[maxsize-1]相接在一起。这种形式的顺序队列称为循环队列

用线性链表表示的队列称为链队列。链表的第一个节点存放队列的队首结点链表的最后一个节点存放队列的队尾首结点,队尾结点的链接指针为空另外还需要两个指针(头指针和尾指针)財能唯一确定,头指针指向队首结点尾指针指向队尾结点

定义:若一个函数部分地包含它自己或用它自己给自己定义,则称这个函数是递歸的;若一个算法直接地或间接地调用自己,则称这个算法是递归的算法。



①结点的度:结点拥有子节点的个数

②树的度:该树中最大的度數

③叶子结点:度为零的结点

④分支结点:度不为零的结点

⑤内部结点:除根结点之外的分支结点

⑥开始结点:根结点又称为开始结点

结點的高度:该结点到各结点的最长路径的长度

森林:m(m≥0)棵互不相交的树的集合将一棵非空树的根结点删去,树就变成一个森林;

反の给m棵独立的树增加一个根结点,并把这m棵树作为该结点的子树森林就变成一棵树。

2.结点的层数和树的深度

①结点的层数:根结点嘚层数为1其余结点的层数等于其双亲结点的层数加1。

②堂兄弟:双亲在同一层的结点互为堂兄弟

③树的深度:树中结点的最大层数称為树的深度。

注意:要弄清结点的度、树的度和树的深度的区别

树中结点之间的逻辑关系是“一对多”的关系,树是一种非线性的结构

先序遍历:访问根结点——先序遍历根的左子树——先序遍历根的右子数

中序遍历:中序遍历左子树——访问根结点——中序遍历右子树

後序遍历:后序遍历左子树——后序遍历右子树——访问根结点

最优二叉树(哈夫曼树):最小两结点数相加的值再与次小结点数合并

巳知一棵二叉树的前根序序列和中根序序列,构造该二叉树的过程如下:

1. 根据前根序序列的第一个元素建立根结点;

2. 在中根序序列中找到該元素确定根结点的左右子树的中根序序列;

3. 在前根序序列中确定左右子树的前根序序列;

4. 由左子树的前根序序列和中根序序列建立左孓树;

5. 由右子树的前根序序列和中根序序列建立右子树。

-已知一棵二叉树的后根序序列和中根序序列构造该二叉树的过程如下:

1. 根据后根序序列的最后一个元素建立根结点;

2. 在中根序序列中找到该元素,确定根结点的左右子树的中根序序列;

3. 在后根序序列中确定左右子树嘚后根序序列;

4. 由左子树的后根序序列和中根序序列建立左子树;

5. 由右子树的后根序序列和中根序序列建立右子树

翻书问题或者走台阶問题:

共有n个台阶,每次只能上1个台阶或者2个台阶共有多少种方法爬完台阶。 
共有n页书每次只能翻1页或者2页书,共有多少种方法翻完铨书

# f(n)为翻完全书的方法
# 迭代写法,或者叫循环写法
 



查找比如16在不在矩阵中
 
 

链表中最简单的一种是单向链表,它包含两个域一个信息域和一个指针域。这个链接指向列表中的下一个节点而最后一个节点则指向一个空值。
# 链表中的节点的怎么看数据结构的根节点
# 这样┅条链表就形成了。
 









 



 






# root就是一颗二叉树
 
中序遍历(先遍历左子树再遍历根节点,再遍历右子树)
 
前序遍历(先遍历根节点再遍历左子树,再遍曆右子树)
 
后序遍历(先遍历左子树再遍历右子树,再遍历根节点)
 
 
已知一颗二叉树的先序遍历序列为ABCDEFG中序遍历为CDBAEGF,能否唯一确定一颗二叉樹如果可以,请画出这颗二叉树

  
 
使用程序根据二叉树的先序遍历和中序遍历来恢复二叉树。
 


 

 
 
 
 
 
假设快速排序的时间复杂度为f(N)
 



在数组元素數量为n的数组里面寻找第k大的数


并不是都是错题带 * 号的为感兴趣的题。

设栈S和队列Q的初始状态为空元素E1、E2、E3、E4、E5和E6依次通过栈S,一个元素出栈后即进入队列Q若6個元素出列的顺序为E2、E4、E3、E6、E5和E1,则栈S的容量至少应该是( )

真不知道为什么会做错,那就辛苦自己改一遍吧你活该。

由上图知顺序栈 与 链栈 就像是一个正着走的时候,另一个就倒着走

7. 设front和rear分别表示顺序循环队列的头指针和尾指针,N为存储该循环队列的数組最大容量则判断该循环队列为空的条件为_____;判断该循环队列为满的条件为_______________

解:参考上一题的图队尾插入新元素时,尾指针增1删除队列头元素时,头指针增1

进行后续遍历,所得即为后缀算式

注意:遇到操作符,选取操作数的时候从左到右(或是从栈底到栈顶嘚方向来选),运算有顺序



下面叙述正确的是()。
A. 二叉树是特殊的树
B. 二叉树等价于度为2的树
C. 完全二叉树必为满二叉树
D. 二叉树的左右子樹有次序之分

(Tree)是nn?0个节点的有限集

二叉树(Binary Tree)是另一种树形结构,它的特点是每个节点至多只有二棵子树(即二叉树中不存茬存在度大于2的节点)并且,二叉树的子树有左右之分其次序不能任意颠倒。

 ————摘自《怎么看数据结构的根节点(C语言版)》嚴蔚敏 主编

由上述定义知二叉树 是两种不同的怎么看数据结构的根节点, 排除A,B
满二叉树必为完全二叉树,排除C

*由权值分别为3,8,6,2,5的葉子结点生成一棵哈夫曼树,它的带权路径长度为( )

顺便展示一下哈夫曼树的构建过程。

从树中一个节点到另一个节点之间的分支构荿这两个节点之间的路径路径上的分支数目称作路径长度

树的路径长度是从树根到每一个节点的路径长度之和

n 个叶子节点的二叉树,每个叶子节点带权为wi每个叶子节点的树的路径长度为 li树的带权路径长度为树中所有带权路径长度之和通常记作 其中,树的带权路徑长度最小的二叉树称作最优二叉树或哈夫曼树

 ————摘自《怎么看数据结构的根节点(C语言版)》严蔚敏 主编

注意:不是权值 乘以 層数,而是乘以树的路径长度

任何一棵二叉树的叶子结点在先序、中序和后序遍历序列中的相对次序()。

解:题意理解错误本题是指叶子节点之间的相对次序,只说叶子节点且不是绝对位置,三种遍历方法都是先左后右所以,认真理解题意啊笨蛋

*假设一棵二叉樹的先序序列为EBADCFHGIKJ,中序序列为ABCDEFGHIJK请画出该二叉树并写出该二叉树的后序遍历序列。

通过先序序列找双亲节点通过中序序列将左右子树区汾开,一步一步慢慢来

*下列关于AOE网的叙述中,不正确的是()
A.关键活动不按期完成就会影响整个工程的完成时间
B.任何一个关键活動提前完成,那么整个工程将会提前完成
C.所有的关键活动提前完成那么整个工程将会提前完成
D.某些关键活动提前完成,那么整个工程将会提前完成

分号左边为最早发生时间右边为最迟发生时间。

一个关键活动提前完成只能让这条关键路径变成非关键路径。

当关键蕗径不止一条的时候单单提高一条关键路径上关键活动的速度,是不能缩短整个工程工期的

所以,并不是网中任何一个关键活动提前唍成整个工程都能提前完成。但如果网中任何一个关键活动延期完成整个工程一定延期。

关键是 D 选项这个理解起来比较奇怪,我第┅次没怎么理解出题人的意思是,“存在某些关键活动若它们被完成,那么整个工程将会提前完成”我理解成了,“任意一些关键活动若它们被完成,那么整个工程将会提前完成”,慢慢感觉吧我总觉得这句话说的有歧义,不严谨但 B 一定错就是了。



*怎么看数據结构的根节点中其逻辑结构有 ??? ????????????四种。

答案:集合线性结构,树形结构图状结构或网状结构

*AOV網中,结点表示???,边表示???。AOE网中,结点表示???

答案:活动活动间的关系,事件活动

数组A[5][6]的每个元素占五个字节,将其按行優先次序存储在起始地址为1000的内存单元中则元素A[4][5]的地址是???

解:幼儿难度计算题但我还是做错了。

就是设数组为F[m][n]待求地址为 F[i][j],首哋址为 F, 数组中每一个元素所占字节为 B 所以:

呢因为数组是从0开始数的啊笨蛋,你怎么就忘了呢??


我要回帖

更多关于 怎么看数据结构的根节点 的文章

 

随机推荐