【Java数据结构】栈和队列基础

本文参考链接:
栈:https://www.cnblogs.com/fzz9/p/8167546.html
后缀表达式:https://blog.csdn.net/ring_k/article/details/79598961
队列:https://www.jianshu.com/p/1b8270f3c881
《数据结构与算法分析——Java语言描述》原书第二版

1.栈

1.1 基本概念
栈(Stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶(top)。
对栈的基本操作有push(进栈)和pop(出栈),前者相当于插入,后者则是删除最后插入的元素。对空栈进行pop或top一般被认为是栈ADT中的一个错误。另一方面,当运行push时空间用尽是一个实现限制,而不是ADT错误。
栈有时叫做LIFO(先进后出)表。
在这里插入图片描述
1.2 代码示例(顺序栈)

public class SqStack<T> {
13     private T data[];//用数组表示栈元素
14     private int maxSize;//栈空间大小(常量)
15     private int top;//栈顶指针(指向栈顶元素)
16     
17     @SuppressWarnings("unchecked")
18     public SqStack(int maxSize){
19         this.maxSize = maxSize;
20         this.data = (T[]) new Object[maxSize];//泛型数组不能直接new创建,需要使用Object来创建(其实一开始也可以直接使用Object来代替泛型)
21         this.top = -1;//有的书中使用0,但这样会占用一个内存
22     }
23 
24     //判断栈是否为空
25     public boolean isNull(){
26         boolean flag = this.top<=-1?true:false;
27         return flag;
28     }
29     
30     //判断是否栈满
31     public boolean isFull(){
32         boolean flag = this.top==this.maxSize-1?true:false;
33         return flag;
34     }
35     
36     //压栈
37     public boolean push(T vaule){
38         if(isFull()){
39             //栈满
40             return false;
41         }else{
42             data[++top] = vaule;//栈顶指针加1并赋值
43             return true;
44         }
45     }
46 
47     //弹栈
48     public T pop(){
49         if(isNull()){
50             //栈为空
51             return null;
52         }else{
53             T value = data[top];//取出栈顶元素
54             --top;//栈顶指针-1
55             return value;
56         }
57     }
58     
59 }

1.3 应用场景
(1)平衡符号
编译器检查程序的语法错误,但是常常由于缺少一个符号(如遗漏一个花括号或是注释起始符)引起编译器列出上百行的诊断,而真正的错误并没有找出。在这种情况下,一个有用的工具就是检验是否每件事情都能成对的程序。于是,每个右花括号、右方括号及右圆括号必然对应其相应的左括号。序列[()]是合法的,但[(])是错误的。
为简单起见,我们仅就()、[]、和{}进行校验并忽略出现的任何其他字符。这个简单算法用到一个栈,简述如下:
做一个空栈。读入字符直到文件结尾。如果字符是一个开放符号(如{、(、[),则将其推入栈中。如果字符是一个封闭符号(}、)、]),则当栈为空时报错。否则,将栈元素弹出,如果弹出的符号不是对应的开放符号,则报错。在文件结尾,如果栈非空则报错。
(2)后缀表达式
具体请参考:https://blog.csdn.net/ring_k/article/details/79598961
(3)十进制转换为N进制
如将十进制123456转换为16进制,我们需要用123456除以16后取余压栈,然后用商继续除以16取余压栈,重复以上操作,直到商为0,这样保存在栈中的余数从栈顶到栈底开始排列形成的数字就是16进制了。(注:大于等于10的余数我们要用字母来表示)。

public class StackUtils{
 4     public static SqStack<?> ss ;
 5     
 6     //弹栈出所有元素
 7     public static Object[] popAll(SqStack<?> s){
 8         ss = s;
 9         if(ss.isNull()){
10             return null;
11         }else{
12             Object[] array = new Object[ss.getTop()+1];
13             int i = 0;
14             while(!ss.isNull()){
15                 array[i]=ss.pop();
16                 i++;
17             }
18             return array;
19         }
20     }
21     
22     //使用栈进行进制装换
23     public static String integerToNhex(Integer num,int hex){
24         //对传入的进制进行判断
25         if(hex<=0||hex>36){
26             return "请输入有效的进制";
27         }else if(num==0){
28             return "0";
29         }else if(num>0){//正数
30             SqStack<Integer> stack = new SqStack<Integer>(16);
31             int index = num;
32             while(num!=0){
33                 num = num / hex ;
34                 int remainder = index % hex;//取余压栈
35                 stack.push(remainder);
36                 index = num;
37             }
38             Object[] o = popAll(stack);//弹栈取出余数
39             StringBuilder sb = new StringBuilder();
40             for(Object i : o){
41                 int in = (int)i;
42                 //取出的数字如果>=10需要用字母代替
43                 if(in>=10){
44                     char c = (char) ('a'+in-10);
45                     sb.append(c);
46                 }else{
47                     sb.append(i);
48                 }
49             }
50             return sb.toString();
51         }else{//负数
52             num = -num;//先去负号
53             SqStack<Integer> stack = new SqStack<Integer>(16);
54             int index = num;
55             while(num!=0){
56                 num = num / hex ;
57                 int remainder = index % hex;//取余压栈
58                 stack.push(remainder);
59                 index = num;
60             }
61             Object[] o = popAll(stack);//弹栈取出余数
62             StringBuilder sb = new StringBuilder();
63             sb.append("-");//添加负号
64             for(Object i : o){
65                 int in = (int)i;
66                 //取出的数字如果>=10需要用字母代替
67                 if(in>=10){
68                     char c = (char) ('a'+in-10);
69                     sb.append(c);
70                 }else{
71                     sb.append(i);
72                 }
73             }
74             return sb.toString();
75         }
76     }
77     
78 }

2.队列

1.基本概念
像栈一样,队列(queue)也是表。然而,使用队列时插入在一端进行而删除则在另一端进行。
队列的基本操作是enqueue(入队),它是在表的末端(叫做队尾rear)插入一个元素,和dequeue(出队),它是删除(并返回)在表的开头(叫做队头front)的元素。即队列是一个FIFO(先进先出)的操作。
在这里插入图片描述
2.应用场景
有许多使用队列给出高效运行时间的算法。它们当中有些可以在图论中找到,这里先给出某些应用队列的简单例子。
当作业送交给一台行式打印机的时候,它们就以到达的顺序被排列起来。因此,被送往行式打印机的作业基本上被放到一个队列中。
事实上,每一个实际生活中的排队都(应该)是一个队列。例如,在一些售票口排列的队列都是队列,因为服务的顺序是先到先买票。
另一个例子是关于计算机网络的。有多种PC机的网络设置,其中磁盘是放在一台叫做文件服务器的机器上的。使用其他计算机是按照先到先使用的原则访问文件的,因此其数据结构是一个队列。
进一步的例子如下:

  • 当所有的接线员忙不开的时候,对大公司的呼叫一般都被放到一个队列中;

  • 在大型的大学里,如果所有的终端都被占用,由于资源有限,学生们必须在一个等待表上签字登记。在终端上呆得时间最长的学生将首先被强制离开,而等待时间最长的学生则将是下一个被允许使用终端的用户。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值