3.[数据结构和算法分析笔记]栈 Stack

简介:

1.栈 List

定义

栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶。

栈有时又叫做LIFO(后进先出)表,即last-in,first-out

现实中的栈

栈的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public  interface  StackInterface<T> {
     /**
      * 将新元素加到站定
      * @param newEntry 带插入站的对象 */
     public  void  push(T newEntry);
     /**
      * 删除并返回栈顶
      * @return 栈顶的对象,如果栈为空则返回null */
     public  T pop();
     /**
      * 取出栈顶
      * @return 栈顶的对象,如果栈为空则返回null */
     public  T peek();
     /**
      * 检查栈是否为空
      * @return 如果栈为空返回true */
     public  boolean  isEmpty();
     /**
      * 从栈中删除所有元素 */
     public  void  clear();
}

程序栈

当一个程序执行时,一个被称为程序计数器的专用存储单元指向当前指令。当一个方法被调用时,程序的运行时环境为这个方法创建一个称为活动记录或栈帧的对象,这个活动记录显示该方法在执行过程中的状态。具体说,活动记录含有方法的实参、局部变量和当前指令的引用,即程序计数器的一个副本。在这个方法被调用时,活动记录被压入称为程序栈(或者称为Java栈)中。

由于一个方法可以调用另一个方法,程序栈往往含有多个活动记录。位于栈顶的活动记录,属于当前正在执行的方法,紧接在栈顶下的记录,属于调用当前方法的方法。


当main开始执行,他的活动记录位于程序栈顶,如图A

当main调用methodA时,一个新的记录被压入栈,此时程序计数器为50,图B展示methodA刚开始执行时,main更新记录与methodA的新纪录

当methodA调用methodB时,程序计数器为120,一个新的活动记录被压入栈。图C展示当methodB刚开始执行时main为改变的记录、methodA更新后的记录以及methodB的新纪录。

在methodB执行过程中,活动记录被更新,但main和methodA的记录保持不变。

Java类库:类Stack


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public  class  Stack<T> {
                               
     public  T push(T item);
     public  T pop();
     public  T peek();
     public  boolean  empty();
     /**
      * 在栈中查找指定对象
      * @param desiredItem 待查找的对象
      * @return 如果desiredItem在栈中,则返回其位置;如果不在则返回-1;栈顶的位置是-1 */
     public  int  search(T desiredItem);
     /**
      * @return 栈的一个遵循Java接口的Iterator的迭代器 */
     public  Iterator<T> iteraotr();
     /**
      * @return 栈的一个遵循Java接口ListIterator的迭代器 */
     public  ListIterator<T> listIterator();
}

2.基于链表的实现

如果用链表表示栈,则第一个结点应该引用栈顶元素。

类的框架

栈的链表实现有一个数据域topNode,它是链表的表头引用,默认构造函数将这个数据域设置为null。



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public  class  LinkedStack<T>  implements  StackInterface<T>, Serializable {
     private  Node topNode;  //引用链表中第一个结点
     public  LinkedStack() {
         topNode =  null ;
     }
     private  class  Node  implements  Serializable {
         private  T data;  //栈的元素
         private  Node next;  //指向下一个结点的连接
     }
     // 在栈顶插入
     public  void  push(T newEntry) {
         Node newNode =  new  Node(newEntry, topNode);
         topNode = newNode;
     }
     // 删除栈顶
     public  T pop() {
         T top =  null ;
         if  (topNode !=  null ) {
             top = topNode.getData();
             topNode = topNode.getNext();
         }
         return  top;
     }
     // 检索栈顶
     public  T peek() {
         T top =  null ;
         if  (topNode !=  null )
             top = topNode.getData();
         return  top;
     }
     public  boolean  isEmpty() {
         return  topNode ==  null ;
     }
     public  void  clear() {
         topNode =  null ;
     }
}

3.基于数组的实现



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public  class  ArrayStack<T>  implements  StackInterface<T>, Serializable {
     private  T[] stack;  //存放栈元素的数组
     private  int  topIndex;  // 栈顶元素索引
     private  static  final  int  DEFAULT_MAX_SIZE =  50 ;
     public  ArrayStack() {
         this (DEFAULT_MAX_SIZE);
     }
     public  ArrayStack( int  initialCapacity) {
         stack = (T[])  new  Object[initialCapacity];
         topIndex = - 1 ;
     }
     // 在栈顶插入
     public  void  push(T newEntry) {
         topIndex++;
         if  (topIndex >= stack.length) {
             //若数组已满,扩展数组
         }
         stack[topIndex] = newEntry;
     }
     // 删除栈顶
     public  T pop() {
         T top =  null ;
         if  (!isEmpty()) {
             top = stack[topIndex];
             stack[topIndex] =  null ;
             topIndex--;
         }
         return  top;
     }
     // 检索栈顶
     public  T peek() {
         T top =  null ;
         if  (!isEmpty())
             top = stack[topIndex];
         return  top;
     }
     public  boolean  isEmpty() {
         return  topIndex <  0 ;
     }
     public  void  clear() {
         stack =  null ;
     }
}

4.基于向量的实现


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public  class  VectorStack<T>  implements  StackInterface<T>, Serializable {
     private  Vector<T> stack;  //栈顶是最后一个元素
     public  VectorStack() {
         stack =  new  Vector();  // 需要时向变量大小将成倍增加
     }
     public  VectorStack( int  maxSize) {
         stack =  new  Vector(maxSize);
     }
     // 在栈顶插入
     public  void  push(T newEntry) {
         stack.addElement(newEntry);
     }
     // 删除栈顶
     public  T pop() {
         T top =  null ;
         if  (!isEmpty()) {
             top = stack.lastElement();
             stack.removeElement(stack.size() -  1 );
         }
         return  top;
     }
     // 检索栈顶
     public  T peek() {
         T top =  null ;
         if  (!isEmpty())
             top = stack.lastElement();
         return  top;
     }
     public  boolean  isEmpty() {
         return  stack.isEmpty();
     }
     public  void  clear() {
         stack.removeAllElements();
     }
}









本文转自 LinkedKeeper 51CTO博客,原文链接:http://blog.51cto.com/sauron/1225873,如需转载请自行联系原作者
目录
相关文章
|
机器学习/深度学习 边缘计算 算法
NOMA和OFDMA优化算法分析
NOMA和OFDMA优化算法分析
616 127
|
11月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
546 3
|
11月前
|
存储 边缘计算 算法
【太阳能学报EI复现】基于粒子群优化算法的风-水电联合优化运行分析(Matlab代码实现)
【太阳能学报EI复现】基于粒子群优化算法的风-水电联合优化运行分析(Matlab代码实现)
203 0
|
编解码 算法 5G
MIMO雷达空间谱估计中Capon算法与MUSIC算法的对比分析及实现
MIMO雷达空间谱估计中Capon算法与MUSIC算法的对比分析及实现
1077 2
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
793 1
|
人工智能 自然语言处理 算法
2025 年 7 月境内深度合成服务算法备案情况分析报告
2025年7月,中央网信办发布第十二批深度合成算法备案信息,全国389款产品通过备案,服务提供者占比超七成。截至7月14日,全国累计备案达3834款,覆盖文本、图像、音视频等多模态场景,广泛应用于生活服务、医疗、金融等领域。广东以135款居首,数字人、AI客服等C端应用主导,民营企业成主力,国企聚焦公共服务。随着AI政策推动,备案已成为AI产品合规上线关键环节。
|
12月前
|
机器学习/深度学习 算法 5G
【MUSIC、最大似然与克拉美-罗下界】MUSIC与ESPRIT 算法来估计到达角(AoA),并尝试推导克拉美-罗下界(CRLB)以分析其性能研究(Matlab代码实现)
【MUSIC、最大似然与克拉美-罗下界】MUSIC与ESPRIT 算法来估计到达角(AoA),并尝试推导克拉美-罗下界(CRLB)以分析其性能研究(Matlab代码实现)
787 0
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
302 0
栈区的非法访问导致的死循环(x64)
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
314 0
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。

热门文章

最新文章