数据结构与算法之美(三)线性表数据结构:数组、链表、栈、队列

线性表上的数据最多只有前和后两个方向。

数组

数组用一组连续的内存空间,来存储一组具有相同类型的数据

1. 优缺点

  • 优点:支持随机访问,根据下标随机访问的时间复杂度为O(1)
  • 缺点:插入、删除低效,平均时间复杂度为O(n)

2. 使用注意点

  • 警惕访问越界
  • 业务开发中可以使用容器代替数组,如果是底层开发有性能优化需要可以用数组

链表

链表通过指针将一组零散的内存块串联起来使用。

1. 链表分类

链表按结构可以分为:单链表、双向链表、循环列表等。

(1)单链表

在这里插入图片描述
链表的组成单元是head指针、结点,每个结点有数据值data后继指针next,其中第一个结点叫作头结点,最后一个结点叫作尾结点,尾结点的指针指向空地址NULL。当head = NULL即为空链表。

  • 优点:插入、删除高效,时间复杂度是O(1)
  • 缺点:随机访问低效,时间复杂度是O(n)

(2)双向链表

在这里插入图片描述
每个结点不只有后继指针next,还有前驱指针prev,支持双向遍历,适合处理需要知道前驱结点的问题。

(3)循环列表

在这里插入图片描述
尾结点指针指向链表的头结点,适合处理具有环形结构的数据,例如“丢手绢”约瑟夫问题

2. 链表代码注意点

(1)将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针:

  • p->next=q表示p结点的next指针存储了q结点的内存地址;
  • p->next=p->next->next表示p结点的next指针存储了p结点的下下一个结点的内存地址。

(2)警惕指针丢失和内存泄露

  • 插入结点(new_node->next=p->next, p->next=new_node)时,注意先将被插入的结点指向下一个结点,再把当前结点指向被插入的结点,如下图和代码所示;
  • 删除结点(p->next=p->next->next)时,注意手动释放内存空间。

在这里插入图片描述

// 在结点a和b之间插入结点x的写法(假设当前指针p指向结点a),如果颠倒过来就会发生指针丢失
x->next = p->next; // 第一步
p->next = x; // 第二步

(3)带头链表:引入哨兵结点(无数据、只有一个next指针),head指针会一直指向这个哨兵结点,就可以简化边界处理,对于插入第一个结点、删除最后一个结点的特殊情况无需特殊处理。

先入后出,只能在一端插入和删除数据。

栈既可以用数组来实现、也可以用链表来实现,分别叫作顺序栈链式栈

栈的基本操作:入栈push出栈pop,时间复杂度都是O(1),空间复杂度也是O(1)。

1. 栈的应用

函数调用栈

单调栈

从名字上就听的出来,单调栈中存放的数据应该是有序的,所以单调栈也分为:

  • 单调递增栈:单调递增栈就是从栈底到栈顶数据是从大到小;
  • 单调递减栈:单调递减栈就是从栈底到栈顶数据是从小到大。

单栈

  • 检查表达式括号匹配:用栈来保存未匹配的左括号,从左到右依次扫描字符串,当扫描到左括号时压入栈,当扫描到右括号时,从栈顶取出一个左括号,如果能够匹配,则继续扫描剩下的字符串,如果遇到不能配对的右括号或栈中没有数据则为不匹配

双栈

  • 表达式求值:双栈(操作数栈、操作符栈)。遇到数字就入数字栈;遇到操作符与操作符栈顶元素比较优先级,如果比栈顶元素优先级高,就将入操作符栈,如果优先级小于等于栈顶元素,就取数字栈栈顶的2个操作数和运算符栈栈顶的操作符进行计算,计算结果入数字栈。在这里插入图片描述
  • 浏览器的前进、后退:双栈X和Y,将顺序浏览的页面压入X,点后退时从X栈顶取网页压入Y,前进时再从Y栈顶取页面压入X

队列

队列先入先出,只支持两个基本操作:入队enqueue出队dequeue

队列既可以用数组来实现、也可以用链表来实现,分别叫作顺序队列链式队列,另外还有循环队列

1. 队列分类

(1)顺序队列

顺序队列是用数组来实现的队列。

  • 需要双指针:head指向队头,tail指向队尾
  • 为了避免没有空间了,入队时可以检测下tail是否指向数组尾,如果是的话进行整体的数据搬移,入队、出队的时间复杂度是O(1)

(2)链式队列

链式队列是用链表来实现的队列。

  • 需要双指针:head指向第一个结点,tail指向最后一个结点

(3)循环队列

循环队列能够避免数据搬移。

  • 判断队空和队满:队空head==tail,队满(tail+1)%n=head

2. 队列的业务应用

在资源有限的场景下,可以通过“队列”这种数据结构来实现请求排队。

(1)阻塞队列

在队空时,出队会被阻塞;
在队满时,入队会被阻塞。

(2)并发队列

线程安全的队列叫作并发队列,支持多个线程同时操作队列。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值