栈,后进先出
队列,先进先出
1.数组实现栈
public class MyStack<E> {
private Object[] stack;
private int size;
public MyStack(){
stack=new Object[10];
}
public boolean isEmpty(){
return size==0;
}
public E peek(){
if(isEmpty()){
return null;
}
return(E) stack[size-1];
}
public E pop(){
E e=peek();
stack[size-1]=null;
size--;
return e;
}
public E push(E item){
ensureCapacity(size+1);
stack[size++]=item;
return item;
}
public void ensureCapacity(int size){
int len=stack.length;
if(size>len){
int newLen=10;
stack=Arrays.copyOf(stack,newLen);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MyStack<Integer> s=new MyStack<Integer>();
s.push(1);
s.push(2);
System.out.println("栈中元素个数"+s.size);
System.out.println("栈顶元素"+s.pop());
System.out.println("栈中元素个数"+s.size);
System.out.println("栈顶元素"+s.pop());
}
}
/*
栈中元素个数2
栈顶元素2
栈中元素个数1
栈顶元素1
*/
2.链表实现栈
class Node<E>{
Node<E> next=null;
E data;
public Node(E data){
this.data=data;
}
}
public class LinkedListStack<E> {
Node<E> top=null;
public boolean isEmpty(){
return top==null;
}
public void push(E data){
Node<E> newNode=new Node<E>(data);
newNode.next=top;
top=newNode;
}
public E pop(){
if(this.isEmpty()){
return null;
}
E data=top.data;
top=top.next;
return data;
}
public E peek(){
if(isEmpty()){
return null;
}
return top.data;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MyStack<Integer> s=new MyStack<Integer>();
s.push(1);
s.push(2);
System.out.println("栈顶元素"+s.pop());
}
}
注意:该实现不是线程安全的,下面程序会讲到,要实现线程安全的栈,需要对入栈和出栈进行同步
3.用O(1)的时间复杂度求栈中最小元素
利用o(1)时间复杂度求栈中最小元素,遍历栈的时间复杂度为O(n);由于每次压栈和出栈都有可能改变栈中的min,增加一个存放min的栈。
空间换取时间:实现时使用两个栈结构,一个存储数据,一个存储栈的最小元素;如果当前入栈的元素比原来栈中的最小值还小,则把这个值压入保存最小值元素栈中;出栈时,如果当前出栈的元素恰好为当前栈中的min,保存最小值的栈顶元素也出栈
public class StackMin {
MyStack<Integer> elem;
MyStack<Integer> min;
public StackMin(){
elem=new MyStack<Integer>();
min=new MyStack<Integer>();
}
public void push(int data){
elem.push(data);
if(min.isEmpty()){
min.push(data);
}
else{
if(data<min.peek()){
min.push(data);
}
}
}
public int pop(){
int topData=elem.peek();
elem.pop();
if(topData==this.min()){
min.pop();
}
return topData;
}
public int min(){
if(min.isEmpty()){
return Integer.MAX_VALUE;
}
else{
return min.peek();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
StackMin s=new StackMin();
s.push(1);
s.push(2);
s.push(0);
s.push(5);
s.push(7);
// for(int i=0;i<5;i++){
// System.out.println(s.pop());
// }
System.out.println("栈min"+s.min());
}
}
4.链表实现队列
public class MyQueue<E> {
private Node<E> head=null;
private Node<E> tail=null;
public boolean isEmpty(){
return head==tail;
}
public void put(E data){
Node<E> newNode=new Node<E>(data);
if(head==null&&tail==null){
head=newNode;
tail=newNode;
}
else{
tail.next=newNode;
tail=newNode;
}
}
public E pop(){
if(this.isEmpty()){
return null;
}
E data=head.data;
head=head.next;
return data;
}
public int size(){
Node<E> tmp=head;
int n=0;
while(tmp!=null){
n++;
tmp=tmp.next;
}
return n;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MyQueue<Integer> q=new MyQueue<Integer>();
q.put(1);
q.put(2);
q.put(3);
System.out.println("队列长度"+q.size());
System.out.println("队首元素"+q.pop());
System.out.println("队首元素"+q.pop());
}
}
5.数组实现队列
public class MyQueueArray <E>{
private LinkedList<E> list=new LinkedList<E>();
private int size=0;
public synchronized void put(E e){
list.addLast(e);
size++;
}
public synchronized E pop(){
size--;
return list.removeFirst();
}
public synchronized boolean empty(){
return size==0;
}
public synchronized int size(){
return size;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MyQueueArray<Integer> q=new MyQueueArray<Integer>();
q.put(8);
q.put(2);
q.put(3);
System.out.println("队列长度"+q.size());
System.out.println("队首元素"+q.pop());
System.out.println("队首元素"+q.pop());
}
}
6.利用两个栈模拟队列操作
利用Java类库提供的Stack来实现:
package stack;
/*
* 两个栈实现队列:A为入栈,B为出栈
* 入栈,入A即可
* 出栈,如果B不为空,直接弹出B中数据
* 如果B空,依次弹出A中的数据放入B中,再弹出B中的数据
*/
import java.util.Stack;
public class StackQueue<E> {
private Stack<E> sa=new Stack<E>();
private Stack<E> sb=new Stack<E>();
public synchronized void put(E e){
sa.push(e);
}
public synchronized E pop(){
if(sb.isEmpty()){
while(!sa.isEmpty()){
sb.push(sa.pop());
}
}
return sb.pop();
}
public synchronized boolean empty(){
return sa.isEmpty()&&sb.isEmpty();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
StackQueue<Integer> sq=new StackQueue<Integer>();
sq.put(2);
sq.put(8);
sq.put(5);
System.out.println("队列首元素"+sq.pop());
System.out.println("队列首元素"+sq.pop());
}
}
7.利用两个队列实现栈
Queue是一个接口,已知的实现类有:ArrayDeque,LinkedList,SynchronousQueue等
package stack;
/*
* 利用两个队列实现栈
* q1入队列,q2出队列,s为栈
* 要压栈,入队列q1即可
* 弹栈,如果q1中只有一个元素,让q1中的元素出队列并输出即可
* 如果q1不只一个元素,q1中所有元素出队列,入队列q2,最后一个元素不入队列q2输出该元素,然后将q2所有元素入q1
*/
import java.util.*;
public class QueueStack<Integer>{
private LinkedList<Integer> q1=new LinkedList<Integer>();
private LinkedList<Integer> q2=new LinkedList<Integer>();
public synchronized void push(Integer item){
q1.addLast(item);
}
public synchronized Integer pop(){
Integer re=null;
if(sSize()!=0){
if(!q1.isEmpty()){
toAnother();
re=q1.removeFirst();
}
else{
toAnother();
re=q2.removeFirst();
}
}
return re;
}
public void toAnother(){
if(!q1.isEmpty()){
while(q1.size()>1){
q2.add(q1.removeFirst());
}
}
else if(!q2.isEmpty()){
while(q2.size()>1){
q1.add(q2.removeFirst());
}
}
}
public int sSize(){
return q1.size()+q2.size();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
QueueStack stack=new QueueStack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
System.out.println(stack.pop());
System.out.println(stack.pop());
stack.push(5);
stack.push(6);
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
}
}