Java-刷题知识点笔记-P5:链表

1.广义表

广义表即我们通常所说的列表(lists)。它放松了对表元素的原子性限制,允许他们有自身结构。

1.1 广义表示例

  1. E=()
    E是一个空表,其长度为0
  2. L=(a,b)
    L是长度为2的广义表,它的两个元素都是原子,因此它是一个线性表
  3. A=(x,L)=(x,(a,b))
    A是长度为2的广义表,第一个元素是原子x,第二个元素是子表L。
  4. B=(A,y)=((x,(a,b)),y)
    B是长度为2的广义表,第一个元素是子表A,第二个元素是原子y。
  5. C=(A,B)=((x,(a,b)),((x,(a,b)),y))
    C的长度为2,两个元素都是子表。
  6. D=(a,D)=(a,(a,(a,(…))))
    D的长度为2,第一个元素是原子,第二个元素是D自身,展开后它是一个无限的广义表。
  7. 由内到外依次运算:Head广义表的第一个元素(外层的括号去除)Tail取广义表除了第一个元素外的其他元素(注意外层的括号不能去除)

1.2非空广义表

  • 非空广义表的第一个元素称为表头,他可以是一个单元素,也可以是一个子表
  • 除表头元素之外,由其余元素所构成的表称为表尾非空广义表的表尾必定是一个表

1.3广义表长度和深度

广义表的长度: 若广义表不空,则广义表所包含的元素的个数,叫广义表的长度,数第一层括号内的逗号数目。
广义表的深度: 广义表中括号的最大层数叫广义表的深度。
构图为

长度:去掉一层括号剩下的是几部分。
深度:去掉几层括号可以到最后一部分。
比如: 例如E((a,(a,b),((a,b),c)))的长度和深度分别为1和4
在这里插入图片描述

2.线性表

线性表=顺序表+链表

2.1链表特点

  1. 插入、删除不需要移动元素
  2. 不必事先估计存储空间
  3. 所需空间与线性长度成正比
  4. 链表访问元素要从第一个节点开始遍历 ,不可随机访问任一元素
  5. 线性链表中,由于前一个结点包含下一个结点的指针,尾结点指针为空,要插入或删除元素,只需要改变相应位置的结点指针即可头指针和尾指针无法决定链表长度

2.2单向链表

  1. 单链表的基本操作(判空、增、删、查)。
    在这里插入图片描述

  2. 单链表头结点是一个指针指向Node数据类型如果头结点指示的是NULL,则该链表为空

  3. 根据头结点的next指向,可以依次遍历出单链表所有节点的位置(即查找操作,但时间复杂度比较大)。

  4. 单链表的增删只需更改指针的指向,而查找需要从链表头依次对比(单向链表中指向头结点的指针First,可用于定位所有其他结点的位置),所以插入、删除(单向链表允许在非表头进行插入或删除操作)时间复杂度小于查找

  5. 判断空
    不带头结点的单向链表的判空条件是head==null
    带头结点单向链表的判空条件是head.next==null;
    带头结点的单向循环链表的判空条件是head.next==head;

  6. 长度不固定,可以任意增删,插入或删除节点时,只需改变相应节点的指针指向即可,无需大量移动元素,不易于存取

  7. 存储空间不连续,数据元素之间使用指针相连,每个数据元素只能访问周围的一个元素(根据单链表还是双链表有所不同),所以易于扩展

  8. 存储密度小,因为每个数据元素,都需要额外存储一个指向下一元素的指针(双链表则需要两个指针)。

  9. 要访问特定元素,链表必须从链表头开始,依次向后查找,平均需要0(n)的时间存取速度慢

  10. 如果两个单向链表相交,那他们的尾结点一定相同

  11. 快慢指针是判断一个单向链表有没有环的一种方法

  12. 有环的单向链表跟无环的单向链表不可能相交

2.3顺序表

  • 在顺序表中,只要知道基地址和结点大小,就可在相同时间内求出任一结点的存储地址。
  • 顺序表在计算机内存中以数组的形式保存,插入元素时,插入到的该位置以及后续位置的元素都要移动
  • 存储空间可以离散分布
  • 在结点等长时可以随机存取

2.4 顺序表和链表的区别和联系

顺序表

  • 空间连续,支持随机访问。
  • 中间或前面部分的插入删除时间复杂度O(N)
  • 增容的代价比较大

链表

  • 以节点为单位存储,不支持随机访问
  • 任意位置插入时间复杂度为O(1)
  • 没有增容问题

2.5循环队列

在这里插入图片描述

长度为SIZE的循环队列有对头指针F和队尾指针R

队列属于逻辑结构的概念,它们的物理存储既可以利用数组也可以利用链表完成,所以循环队列属于逻辑上首尾相接的抽象圆环,如上图所示。

  • 空队列头尾指针指向同一个区域(0区域),所以F==R
  • 满队列是随着元素的入队,尾指针逐渐加1,直到从0区域加到SIZE-1区域,这时尾指针指向SIZE-1区域,头指针指向0区域。判断队满的条件是尾指针再加1(由于是循环)所以头尾指针重合在0区域,(R+1)%SIZE==F
  • front=rear 不为空时带链的队列中只有一个元素
  • 在循环队列中,队头指针和队尾指针的动态变化决定队列的长度

循环队列的相关条件和公式:
队尾指针是rear,队头是front,其中QueueSize为循环队列的最大长度
1.队空条件:rear==front
2.队满条件:(rear+1) %QueueSIze==front
3.计算队列长度:(rear-front+QueueSize)%QueueSize
4.入队:(rear+1)%QueueSize
5.出队:(front+1)%QueueSize

2.6栈

  1. 和顺序栈相比,链栈有一个比较明显的优势是:通常不会出现栈满的情况

  2. 前缀表达式的计算机求值特点:
    从右至左扫描表达式,遇到数字时,将数字压入堆栈遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。

  3. 若一序列进栈顺序为e1,e2,e3,e4,e5,问存在多少种可能的出栈序列()
    在这里插入图片描述

  4. 栈的典型应用:表达式求值,括号匹配,递归函数调用,数制转换、高级编程语言的过程调用等

  5. 在栈中,栈底指针保持不变,有元素入栈,栈顶指针增加,有元素出栈,栈顶指针减少

2.7循环双链表

先搭后拆
在循环双链表的 p 所指的结点之前插入 s 所指结点的操作是

s->next = p;s->prior = p->prior;p->prior->next = s;p->prior = s

在这里插入图片描述

2.8 栈 和 堆区别

  1. ==栈区(stack)由编译器自动分配释放 ==,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

  2. 堆区(heap)一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事。

  3. 管理方式:
    对于栈来讲,是由编译器自动管理,无需我们手工控制;
    对于堆来说,释放工作由程序员控制,容易产生内存溢出。

  4. 空间大小:
    一般都是有一定的空间大小
    内存几乎是没有什么限制

  5. 碎片问题:
    对于栈来讲,则不会存在这个问题。
    对于堆来讲,频繁的new/delete会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。

  6. 分配方式:
    栈有2种分配方式:静态分配和动态分配。
    堆都是动态分配的,没有静态分配的堆。

  7. 分配效率:
    栈的效率比较高。
    堆的效率比栈要低得多。

  8. 增长方向:
    堆的增长方向是从程序低地址高地址向上增长
    栈是连续的,生长方向是向下的,即向着内存地址减小的方向增长

3.堆

3.1大顶堆

  • 大顶堆,在n位置上的数要比在2n+1和2n+2位置上的数大

3.2小顶堆

  • i 位置的数,小于 2i 和 2i + 1 位置上的数
  • 创建最小堆,从下往上,从右到左的顺序,从第一个非叶结点开始调整。
  • 筛选法就是开始按现有的顺序从上到下,从左到右放到一个完全二叉树里面。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值