数据结构:栈+队列
一。栈(stack)
1.概念:
栈是一种特殊的线性表,只允许在固定的一端进行插入或删除操作
栈的出入原则是后进先出,可以把它理解成羊肉串,在最上面的羊肉是最后一个串上去的,也是第一个被吃到的
入栈:在栈顶进行导入 ,出栈:也在栈顶进行操作
2.栈的使用:
(1)push(E e): 将e入栈,并返回e
(2)pop( ):将栈顶元素出出去,并返回栈顶元素的数值
(3)peek( ):获取栈顶元素的数据
(4)size( ):获取栈的长度
(5)empty( ):获取栈是否为空
import java.util.Stack;
public class Test2 {
public static void main(String[] args) {
Stack<Integer> s=new Stack<>();
s.push(11);
s.push(22);
s.push(33);
s.push(44);
System.out.println(s.size());
s.pop();
System.out.println(s.size());
System.out.println(s.peek());
}
}
3.栈的模拟实现:
栈的本质是使用数组,来将数据进行存储
import java.util.Arrays;
import java.util.Stack;
public class Test2 {
int[] array;
int size;
public Test2(){
array=new int[3];
}
public int push(int e){
if(full()){
array= Arrays.copyOf(array,2*array.length);
array[size-1]=e;
size++;
}else{
array[size-1]=e;
size++;
}
return e;
}
public int peek(){
int e=array[size-1];
return e;
}
public int pop(){
int e=peek();
size--;
return e;
}
public boolean full(){
return size==array.length;
}
public boolean empty(){
return 0==size;
}
}
上述代码就是使用数组实现栈的代码,从上面的各个方法的实现能更好的理解stack中自带的方法
4. 栈的典型例题:逆波兰表达式
逆波兰表达式:
例:中序表达式:9+(3-1)3+8/2 后序表达式:931-3+82/+
后序表达式的由来就是把中序表达式所有运算加上括号,当括号内的运算有运算符时,把运算符放到括号后,然后把括号去掉,以此类推就成了上面这个例子中的后序表达式
用中序转后序表达式很难实现,但是后转中就可以使用栈进行实现
思路:先遍历数组,把数据放到栈中,当遇到运算符号时从栈中出两个元素,进行次运算符对应的运算,运算完将算出的值放到栈中,以此类推直到便利完整个数组,最后栈中只会留下一个数据,把数据提出就是中序表达式的答案
import java.util.Stack;
public class Test1 {
public static int arr(String[] ret){//123+*3+
Stack<Integer> hi=new Stack<>();
for(int i=0;i<ret.length;i++){
if(isnumber(ret[i])){//是数字
hi.push(Integer.parseInt(ret[i]));
}else{
int a=hi.pop();
int b=hi.pop();
if(ret[i].equals("+")){
hi.push(a+b);
}else if(ret[i].equals("-")){
hi.push(a-b);
}else if(ret[i].equals("*")){
hi.push(a*b);
}else if(ret[i].equals("/")){
hi.push(a/b);
}
}
}
return hi.pop();
}
public static boolean isnumber(String hehe){
if(hehe.equals("+") || hehe.equals("-") || hehe.equals("*") || hehe.equals("/")){
return false;
}
return true;
}
public static void main(String[] args) {
String[] ret={"1","2","3","+","*","3","+"};
System.out.println(arr(ret));
}
}
二。队列(Queue)
1.概念:
一端进行插入,一端进行删除操作,它的工作原理与栈是相反的,队列是先进先出
队列就相当于一个管道,从一头进,再从另一头出,第一个进的元素就是第一个出的元素
进行插入操作的这一端叫做队尾
进行删除操作的这一端叫做队首
2.队列的使用:
在java中Queue是一个接口,本质上是通过链表来实现的
(1)offer(E e ):入队列,向队列中添加元素(这个方法的返回值是boolean类型)
(2)poll( ):出队首元素,并且返回队首元素的值
(3)peek( ):返回队首元素的值
(4)size( ):获取队列的长度
(5)isEmpty( ):获取队列是否为空
import java.util.LinkedList;
import java.util.Queue;
public class Test3 {
public static void main(String[] args) {
Queue<Integer> q=new LinkedList<>();
q.offer(12);
q.offer(22);
q.offer(33);
q.offer(44);
System.out.println(q.size());
q.poll();
System.out.println(q.size());
System.out.println(q.peek());
}
}
3.队列的模拟实现:
本质上使用链表的形式进行实现
import java.util.LinkedList;
import java.util.Queue;
public class Test3 {
static class ListNode{
public int val;
public ListNode next;
public ListNode prev;
public ListNode(int val){
this.val=val;
}
}
public ListNode head;
public ListNode last;
public boolean offer(int val){
ListNode node=new ListNode(val);
if(head==null){
head=node;
last=node;
return true;
}else{
last.next=node;
node.prev=last;
last=last.next;
}
return false;
}
public int poll(){
if(head==null){
return -1;
}else if(head.next==null){
int curval=head.val;
head=null;
last=null;
return curval;
}else{
int curval=head.val;
head=head.next;
head.prev=null;
return curval;
}
}
public int peek(){
if(head==null){
return -1;
}
return head.val;
}
public boolean empty(){
return head==null;
}
}
上述代码就是使用链表的方式实现队列的写法
4.循环队列:
本质上使用数组的方法进行循环队列的实现
中间的主要问题是数组长度,怎么判断这个循环队列是空的还是满的
这里使用预留一格的方法进行区分空和满的情况
如果队和尾是相同的,那么就判断成是空,如果(rear+1)%elem.length==front那么就判断成满
public class Test4 {
public int[] elem;
public int front;
public int rear;
public Test4(int k){
elem=new int[k+1];
}
public boolean isEmpty(){
return front==rear;
}
public boolean isFull(){
return (rear+1)%elem.length==front;
}
public boolean enQueue(int value){
if(isFull()){
return false;
}else{
elem[rear]=value;
rear=(rear+1)%elem.length;
return true;
}
}
public boolean deQueue(){
if(isEmpty()){
return false;
}else{
front=(front+1)%elem.length;
return true;
}
}
public int front(){
if(isEmpty()){
return -1;
}
return elem[front];
}
public int Rear(){
if(isEmpty()){
return -1;
}
int index=(rear==0)?elem.length-1:rear-1;
return elem[index];
}
}