java基础:14.4 栈、队列

本文详细介绍了Java中栈和队列的基础知识,包括栈的myStack实现、进制转换、括号匹配和栈混洗问题,以及队列的实现。栈作为一种特殊线性表,常用在逆序输出、递归嵌套和延迟缓冲等问题中。队列则适用于先进先出的情景,而优先队列使用堆实现,确保高优先级元素优先处理。
摘要由CSDN通过智能技术生成


可以使用数组线性表实现栈,使用链表实现队列。

栈可以看做是一种特殊类型的线性表,访问、插入和删除其中的元素只能在栈尾进行。用数组线性表来实现栈比用链表来实现实现效率更高

这里有两种办法可用来设计栈和队列的类。

  • 使用继承:可以通过继承数组线性表类ArrayList 来定义栈类,通过继承链表类LinkedList 来定义队列类。
  • 使用组合:可以将数组线性表定义为栈类中的数据域,将链表定义为队列类中的数据域,

在这里插入图片描述

这两种设计方法都是可行的,但是相比之下,组合可能更好一些,因为它可以定义一个全新的栈类和队列类,而不需要继承数组线性表类与链表类中不必要和不合适的方法。

1、栈

在这里插入图片描述
栈的典型应用

  1. 逆序输出Conversion
    输出次序与处理过程颠倒;递归深读和输出长度不易预知
  2. 递归嵌套 stack permutation + parenthesis
    具有自相似性的问题可递归描述,但分支位置和嵌套深度不固定
  3. 延迟缓冲 evaluation
    线性扫描算法模式中,在预读足够长之后,方能确定可处理的前缀
  4. 栈式计算 RPN
    基于栈结构的特定计算模式

1.1 myStack的实现

public class myStack<E> {

    private java.util.ArrayList<E> list = new java.util.ArrayList<E>();

    public void push(E e){
        list.add(e);
    }

    public E pop(){
        return list.remove(list.size()-1);
    }

    public E top(){
        return list.get(list.size()-1);
    }

    public int getSize(){
        return list.size();
    }
    
    public boolean empty(){       //if stack is empty, return true;
        if(list.size() == 0) return true;
        else return false;
    }
    @Override
    public String toString() {
        return "stack:" + list.toString();
    }
}

 

1.2 栈应用:进制转换问题

逆序输出Conversion :输出次序与处理过程颠倒;递归深读和输出长度不易预知

进制转换 输入一个数,可以转换成任意的n进制。

public class convert {

    public static void main(String []args){
        ConvertBase(-17,2);
    }

    static void ConvertBase (int num , int base){
        myStack s = new myStack();
        char digit [] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        boolean flag = false;

        if(num < 0){
            flag = true;
            num *= -1;
        }

        while (num > 0) {
            s.push(digit[num % base]);
            num /= base;
        }

        if(flag){
            s.push('-');
        }

        for(int i = s.getSize() ; i > 0 ; i--)
            System.out.print(s.pop());
    }
}

 

1.3 栈应用:括号匹配问题

stack permutation + parenthesis
具有自相似性的问题可递归描述,但分支位置和嵌套深度不固定
括号匹配问题 :判断一个类似于“(())()()()))(((()” 是否左括号和右括号可以一一正确匹配上。

    static boolean paren(String s){
        myStack stack = new myStack();
        for(int i=0; i < s.length(); i++){
            if(s.charAt(i) == '(')  stack.push(1);
            else if(!stack.empty())  stack.pop();
            else return false;
        }
        return stack.empty();
    }

这个题在学有限自动机课程时也遇到过,同样的思路~~
 

1.4 栈应用:栈混洗问题

/*
描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。
假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,
但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

输入
第一行:输入N个整数,空格隔开,按先后顺序入栈
第二行:输入N个整数,空格隔开,表示一种出栈顺序
输出
True 或者 False ,意思是第二行数据是否是一个合法的弹出序列
样例输入
1 2 3 4 5
4 5 3 2 1
样例输出
True
*/
在这里插入图片描述

    static boolean sp(){
        Scanner in = new Scanner(System.in);
        System.out.println("enter your number");
        String s1 = in.nextLine();
        String s2 = in.nextLine();
        String a1[] = s1.split(" ");
        String a2[] = s2.split(" ");
        Stack<Integer> s = new Stack<>();

        int a[] = new int[a1.length];    //a 是压入栈的顺序 从 0--a.length
        int b[] = new int[a1.length];     // b 是弹出的顺序 从 0--b.length
        for(int i = 0;i < a.length;i++){
            a[i] = Integer.valueOf(a1[i]);
            b[i] = Integer.valueOf(a2[i]);
        }

        int k = 0;
        for(int i = 0; i < a.length; i++){
            s.push(a[i]);
            while( s.empty()==false && b[k] == s.peek()  )
            {
                s.pop();
                k++;
            }
        }
        if( k == a.length && s.empty())
            return true;
        else
            return false;
    }

 

2、队列的实现

队列,元素只能从队列的末端插入,从开始端访问和删除。由于删除是在线性表的起始位置进行的,所以用链表实现队列比用数组线性表实现效率更高。

package ReWrite;
public class GenericQueue<E> {
	
	// 队列:尾进前出
	private java.util.LinkedList<E> list = new java.util.LinkedList<E>();
	
	/**
	 * 添加一个元素到队列
	 * @param e
	 */
	public void enqueue(E e) { 
		list.addLast(e);
	}
	
	/**
	 * 从队列删除一个元素
	 */
	public E dequeue() {
		return list.removeLast();
	}
	
	
	public int getSize() {
		return list.size();
	}
	
	@Override
	public String toString() {
		return "Queue:" + list.toString();
	}
}

2、栈的实现

package ReWrite;

public class GenericStack<E> {
	
	private java.util.ArrayList<E> list = new java.util.ArrayList<E>();
	
	/**
	 * 添加一个元素到队列
	 * @param e
	 */
	public void push(E e) { 
		list.add(e);
	}
	
	/**
	 * 从队列删除一个元素
	 */
	public E pop() {
		return list.remove(list.size()-1);
	}
	
	
	public int getSize() {
		return list.size();
	}
	
	@Override
	public String toString() {
		return "stack:" + list.toString();
	}
}

3、测试

package ReWrite;

public class Test {
	public static void main(String[] args) {
		
	/*	
		GenericQueue<String> queue = new GenericQueue<String>();
		queue.enqueue("tom");
		queue.enqueue("Ali");
		queue.enqueue("Sua");
		System.out.println("(1)" + queue);
		System.out.println("(1)" + queue.dequeue());
		
	*/
		
		GenericStack<String> stack = new GenericStack<String>();
		stack.push("apple");
		stack.push("orange");
		stack.push("megon");
		System.out.println("(1)" + stack);
		System.out.println("(2)" + stack.pop());
		System.out.println("(3)" + stack.pop());
		System.out.println("(4)" + stack);

	}
}

4、优先队列

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列( priority queue) 中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。例如,医院的急救室为病人赋予优先级,具有最高优先级的病人最先得到治疗。

可以使用堆实现优先队列,其中根结点是队列中具有最高优先级的对象。

package ReWrite;

import Sort.Heap;

public class MyPriorityQueue<E extends Comparable<E>> {
	
	private Heap<E> heap = new Heap<>();
	
	public void enqueue(E newObject) {
		heap.add(newObject);
	}
	
	public E dequeue() {
		return heap.remove();
	}
	
	public int getSize() {
		return heap.getSize();
	}
}

测试:

package ReWrite;

public class Test {
	public static void main(String[] args) {
		Patient p1 = new Patient("John",2);
		Patient p2 = new Patient("Jim",1);
		Patient p3 = new Patient("Tim",5);
		Patient p4 = new Patient("Cindy",7);
		
		MyPriorityQueue<Patient> priorityQueue = new MyPriorityQueue<>();
		priorityQueue.enqueue(p1);
		priorityQueue.enqueue(p2);
		priorityQueue.enqueue(p3);
		priorityQueue.enqueue(p4);
		
		while(priorityQueue.getSize()>0)
			System.out.println(priorityQueue.dequeue());
		

	}
	
	static class Patient implements Comparable<Patient>{
		private String name;
		private int priority;
		
		public Patient(String name, int priority) {
			this.name = name;
			this.priority = priority;
		}
		
		@Override
		public String toString() {
			return name + "(priority:" + priority + ")";
		}
		


		@Override
		public int compareTo(Patient o) {
			return this.priority - o.priority;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值