您的位置:首页 > 理论基础 > 数据结构算法

数据结构之栈和队列

2016-03-20 19:29 477 查看

栈和队列篇

先进后出

用数组实现栈

public class StackByArray<E> {

// 栈的长度
private int length;
// 栈
private Object[] array;
// 栈顶的下标
private int topIndex = -1;

/**
* StackByArry:构造方法
*/
public StackByArray(int length) {
this.length = length;
array = new Object[length];
}

/**
* push:入栈
*/
private void push(E e) throws Exception {
if(isFullStack()) {
throw new Exception("栈已满");
}
array[++topIndex] = e;
}

/**
* top: 取出栈顶元素
*/
private E top() throws Exception {
if(isEmpty()) {
throw new Exception("栈为空");
}

E top_elem = (E)array[topIndex];

return top_elem;
}

//出栈
private void pop() throws Exception {
if(isEmpty()) {
throw new Exception("栈已空");
}
array[topIndex] = null;
topIndex--;
}
//清空栈
private void clear() {
Arrays.fill(this.array, null);
this.topIndex=-1;
this.array=new Object[this.length];

}

/**
* isEmptyStack:判断栈是否为空
*/
private boolean isEmpty() {
return (topIndex == -1);
}

/**
* isFullStack:判断栈是否已满

*/
private boolean isFullStack() {
return topIndex == (length - 1);
}

/**
* getLength:取得栈内的数据长度
*/
private int getLength() {
return topIndex + 1;
}

/**
* outPut:栈内容输出
*/
private void outPut() {
for(Object obj : array) {
if(obj != null) {
System.out.print(obj + "  ");
}
}

System.out.println();
}

public static void main(String[] args) throws Exception {
StackByArray<Integer> stack = new StackByArray<Integer>(10);

for(int i = 1; i <= 8; i++) {
stack.push(i);
}
stack.outPut();
System.out.println(stack.top());
stack.pop();
System.out.println(stack.getLength());
stack.clear();
stack.top();
}
}
/*
输出:
1  2  3  4  5  6  7  8
8
7
Exception in thread "main" java.lang.Exception: 栈为空
at datastructure.StackByArray.top(StackByArray.java:52)
at datastructure.StackByArray.main(StackByArray.java:123)
*/


用链表实现栈

链表实现的栈,结点易扩展,不会满

head只是标记下头结点,在栈的实现中没有用

每次新建一个结点(newNode),都使其指向链表最后的结点(current),如此最后添加的结点肯定在链表尾,弹出时依次访问之前的结点(pre),便可维护一个栈

这里pop(),会弹出栈顶元素

public class StackByLink<E> {

private Node head;
private Node current;

class Node{
E data;
Node pre;
public Node(E data){
this.data=data;
}

}

//入栈
public void push(E data){
if(head==null){
head=new Node(data);
current=head;
}
else{
Node node= new Node(data);
node.pre=current;
current=node;
}
}
public E pop()throws RuntimeException{
if(current==null)
throw new RuntimeException("栈已空");
Node node=current;
current=current.pre;
return node.data;
}
public Node top(){
if(current==null)
throw new RuntimeException("栈已空");
return current;
}

public static void main(String[] args) {
StackByLink<Integer> stack= new StackByLink<Integer>();
stack.push(1);
stack.push(4);
stack.push(8);
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
}

}
/*
输出:
8
4
1
Exception in thread "main"
java.lang.RuntimeException: 栈已空
at datastructure.StackByLink.pop(StackByLink.java:46)
*/


两个队列实现一个栈

思路:

将1、2、3依次入队列一, 然后将最后加入的3留在队列一,将1,2入队列二,将3出队列一,此时队列一空了,然后把队列二中的所有数据入队列一;将最上面的2留在队列一,将下面的1入队列二。。。依次循环。

public class StackByDoubleQueue<E>{

Queue<E> queue1 = new ArrayDeque<E>();
Queue<E> queue2 = new ArrayDeque<E>();

public void push(E e){
queue1.add(e);

}
public E pop() throws RuntimeException{
E data;
if(queue1.size()==0)
throw new RuntimeException("栈为空");

while(queue1.size()!=0){
if(queue1.size()==1){
data=queue1.poll();
while(queue2.size()!=0){//把queue2的全部数据放到队列一中
queue1.add(queue2.poll());
}
return data;
}
queue2.add(queue1.poll());
}
throw new RuntimeException("栈为空");
}

public static void main(String[] args) {
StackByDoubleQueue<Integer> stack = new StackByDoubleQueue<Integer>();
stack.push(1);
stack.push(4);
stack.push(8);
System.out.println(stack.pop());
System.out.println(stack.pop());
stack.push(9);
System.out.println(stack.pop());
System.out.println(stack.pop());

}

}


最小栈

这里需要加一个辅助栈,用空间换取时间。辅助栈中,栈顶永远保存着当前栈中最小的数值。具体是这样的:原栈中,每次添加一个新元素时,就和辅助栈的栈顶元素相比较,如果新元素小,就把新元素的值放到辅助栈中,如果新元素大,就把辅助栈的栈顶元素再copy一遍放到辅助栈的栈顶。

public class MinStack {

private Stack<Integer> stack = new Stack<Integer>();//这里不再用泛型,因为需要比较
private Stack<Integer> minStack = new Stack<Integer>();

public void push(int data){
stack.push(data);

if(minStack.size()==0||data<minStack.peek()){
minStack.push(data);
}
else
minStack.push(minStack.peek());
}

public int pop() throws RuntimeException{

if(stack.size()==0){
throw new RuntimeException("栈已空");
}
int data=stack.pop();
minStack.pop();
return data;

}

public int getMin() throws RuntimeException{

if(minStack.size()==0)
throw new RuntimeException("栈已空");
return minStack.peek();

}

public static void main(String args[]) throws RuntimeException{
MinStack stack=new MinStack();
stack.push(4);
stack.push(8);
System.out.println(stack.getMin());
stack.pop();
stack.push(1);
System.out.println(stack.getMin());

}

}

/*
输出:
4
1
*/


栈的压入、弹出序列

题目描述

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

import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA.length==0)
return false;

Stack<Integer> stack = new Stack<Integer>();
int j=0;
for(int i=0;i<pushA.length;i++){

stack.push(pushA[i]);
while(!stack.empty()&&stack.peek()==popA[j]){

j++;
stack.pop();
}

}
if(j==popA.length)
return true;
else
return false;
}
}


队列

用数组实现队列

先进先出

public class QueueByArray<E> {

private int length;
private Object[] array;

private int front;
private int rear;

public QueueByArray(int length){

this.length=length;
this.array=new Object[length];
front=0;
rear=0;
}

public boolean isEmpty(){
return front==rear;

}
public boolean isFull(){

return array.length==rear;

}

//向队尾插入元素
public void push(E e){
if(isFull())
throw new RuntimeException("队列已满");
else
array[rear++]=e;

}
//获得队头元素
public E top(){
if(isEmpty())
throw new RuntimeException("队列为空");
return (E)array[front];

}
public void pop(){

if(isEmpty())
throw new RuntimeException("队列为空");

front++;

}
public void output(){

for(Object obj:array)
if(obj!=null)
System.out.print(obj+" ");

System.out.println();
}

public static void main(String args[]){
QueueByArray<String> queue= new QueueByArray<String>(2);
queue.push("Hello");
queue.push("World");
queue.output();
System.out.println(queue.top());
queue.pop();
System.out.println(queue.top());
queue.pop();
queue.pop();

}
}
/*

输出:
Hello Exception in thread "main" World
Hello
World
java.lang.RuntimeException: 队列为空
at datastructure.QueueByArray.pop(QueueByArray.java:62)
at datastructure.QueueByArray.main(QueueByArray.java:85)
*/


参考

用链表创建队列

新建一个结点,使当前结点(current)的next指向它

弹出时,从head向后遍历弹出

public class QueueByLink<E> {
private Node head;
private Node current;

class Node{
E data;
Node next;
public Node(E data){
this.data=data;
}
}
public void push(E data){
if(head==null){
head = new Node(data);
current=head;
}
else{
current.next=new Node(data);
current=current.next;
}

}
public E pop() throws RuntimeException{
if(head==null)
throw new RuntimeException("队列为空");
Node node =head;
head=head.next;
return node.data;

}
public static void main(String[] args) {
QueueByLink<Integer> queue=new QueueByLink<Integer>();
queue.push(1);
queue.push(4);
queue.push(8);
System.out.println(queue.pop());
System.out.println(queue.pop());
System.out.println(queue.pop());
System.out.println(queue.pop());

}

}
/*
输出:
1
4
8
Exception in thread "main"
java.lang.RuntimeException: 队列为空
at datastructure.QueueByLink.pop(QueueByLink.java:43)
at datastructure.QueueByLink.main(QueueByLink.java:57)

*/


两个栈实现一个队列

思路:

栈1用于存储元素,栈2用于弹出元素,负负得正。

说的通俗一点,现在把数据1、2、3分别入栈一,然后从栈一中出来(3、2、1),放到栈二中,那么,从栈二中出来的数据(1、2、3)就符合队列的规律了,即负负得正。

public class QueueByDoubleStack<E>{

private Stack<E> stack1=new Stack<E>();
private Stack<E> stack2 = new Stack<E>();

public void push(E data){
stack1.push(data);
}
public E pop() throws RuntimeException{

if(stack2.empty()){//stack1中的数据放到stack2之前,
//先要保证stack2里面是空的,每次出队列之前,都要把stack1中的数据完全倾入stack2

while(!stack1.empty()){

stack2.push(stack1.pop());

}

}
if(stack2.empty())//若stack2为空,即stack1,stack2都为空,或stack2中的数据出完了
throw new RuntimeException("队列为空");
return stack2.pop();

}

public static void main(String[] args) {
QueueByDoubleStack<Integer> queue=new QueueByDoubleStack<Integer>();
queue.push(1);
queue.push(4);
queue.push(8);
System.out.println(queue.pop());
queue.push(9);
System.out.println(queue.pop());
System.out.println(queue.pop());
System.out.println(queue.pop());

}

}
/*
输出:
1
4
8
9
Exception in thread "main" java.lang.RuntimeException: 队列为空
at datastructure.QueueByDoubleStack.pop(QueueByDoubleStack.java:40)
at datastructure.QueueByDoubleStack.main(QueueByDoubleStack.java:56)
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: