数据结构之栈与队列
Posted weiziqiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之栈与队列相关的知识,希望对你有一定的参考价值。
1.栈与队列
栈与队列是程序设计中广泛使用的两种重要的线性数据结构。
栈是LIFO(Last In First Out),先存进去的数据只能最后被取出来,进出顺序逆序,即先进后出,后进先出。
队列是FIFO(First In First Out),它保持进出顺序一致,即先进先出,后进后出。
2.如何实现栈
两种方式实现,数组和链表
1 public class MyStack<E> { 2 3 /* 4 * 用数组实现栈 先进后出,后进先出 5 * 思路:定义一个数组,用来保存入栈的数据,数组初始化大小为10 6 * 用size表示入栈数据的个数 而size-1则是对应的数组下标 7 * (由于是数组,需要考虑扩容的问题) 8 * 入栈时,需要判断数据个数是否超出数组大小,如果超出 使用Arrays.copyOf(,)来扩容 9 * 10 * 出栈时,则直接获取栈顶数据,即根据size-1获取后进的数据元素的数组下标,然后将对应出栈 11 * 的数据元素的数组下标处置空。 12 * 13 */ 14 private Object[] stack; 15 private int size; //初始化为0 16 private int newLen; 17 18 public MyStack(){ 19 stack = new Object[10]; 20 } 21 //判读是否栈为空 22 public boolean isEmpty(){ 23 return size==0; 24 } 25 //查看堆栈顶部的对象,而不将其从堆栈中移除。 26 public E peek(){ 27 if(isEmpty()) 28 { 29 return null; 30 } 31 return (E)stack[size-1]; 32 } 33 //栈顶元素 出栈 34 public E pop(){ 35 E e = peek(); 36 stack[size-1]=null; 37 size--; 38 return e; 39 } 40 41 //入栈 42 public E push(E item){ 43 ensureCapacity(size+1); 44 stack[size++] = item; 45 return item; 46 } 47 // 48 private void ensureCapacity(int size) { 49 int len = stack.length; 50 if(size>len) 51 { 52 int newLen = 10; 53 //copy stack to newLen+len of length ’s array 54 stack = Arrays.copyOf(stack, newLen+len); 55 } 56 } 57 58 59 public static void main(String[] args) { 60 MyStack<Integer> ms = new MyStack<>(); 61 System.out.println(ms.size); 62 ms.push(1); 63 ms.push(2); 64 65 System.out.println(ms.size); 66 System.out.println("栈顶元素:"+ms.pop()); 67 System.out.println("栈顶元素:"+ms.pop()); 68 69 }
1 /* 2 * 使用链表实现栈 先进后出 后进先出 3 * 思路: 栈顶位置top 根据链表 进行前插法 将入栈的元素放在链表头部 4 * 出栈的时候,就直接可以从链表头部取出 5 */ 6 class Node<E>{ 7 Node<E> next = null; 8 E data; 9 Node(E data){ 10 this.data = data; 11 } 12 } 13 class Stack<E>{ 14 Node<E> top = null; 15 16 //判读是否栈空 17 public boolean isEmpty(){ 18 return top==null; 19 } 20 //读栈顶元素 21 public E peek(){ 22 if(isEmpty()){ 23 return null; 24 } 25 return top.data; 26 } 27 28 //取出栈顶元素 29 public E pop(){ 30 if(isEmpty()){ 31 return null; 32 } 33 E data = top.data; 34 top = top.next; 35 return data; 36 } 37 38 39 40 //元素入栈 41 public void push(E data){ 42 Node<E> newNode = new Node<E>(data); 43 newNode.next = top; 44 top = newNode; 45 } 46 }
3.如何实现队列
Java中是实现了Queue队列的接口,具体实例化的时候需要用到LinkedList等其他实例化类
使用LinkedList和链表
1 public class MyQueue<E> { 2 /* 3 * 使用(list)实现队列 先进先出 后进后出 4 * 思路使用LinkedList 本质是双向链表 5 * 入队 链表后插入 6 * 出队 获取链表头部元素 并remove掉 7 */ 8 private LinkedList<E> list = new LinkedList<E>(); 9 private int size ; 10 public synchronized void push(E e){ 11 list.add(e); 12 //list.addLast(e); 13 size++; 14 } 15 public synchronized E pop(){ 16 E e = list.removeFirst(); 17 size--; 18 return e; 19 } 20 21 public synchronized boolean empty(){ 22 return size==0; 23 } 24 25 public synchronized int size(){ 26 return size; 27 } 28 29 30 public static void main(String[] args) { 31 32 33 MyQueue<Integer> mq = new MyQueue<>(); 34 mq.push(4);// 35 mq.push(2); 36 37 System.out.println(mq.size); 38 System.out.println(mq.pop()); 39 System.out.println(mq.size); 40 } 41 42 }
class Queue<E>{ Node<E> head = null; Node<E> tail = null; //判读是否队空 public boolean isEmpty(){ if(head == null && tail==null){ return true; } else return false; } //读队头 public E peek(){ if(isEmpty()) return null; return head.data; } //从队头 出队 public E pop(){ if(isEmpty()) return null; E e = head.data; head= head.next; return e; } //进队尾 public void push(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 int size(){ if(head == null) return 0; int len = 1 ; Node<E> l = head; while(l.next!=null){ len++; l = l.next; } return len; } public static void main(String[] args) { //使用链表实现队列 Queue<Integer> q = new Queue(); q.push(1); q.push(2); q.push(3); System.out.println(q.size()); System.out.println(q.pop()); System.out.println(q.peek()); } } class Node<E>{ Node<E> next = null; E data; Node(E data){ this.data = data; } }
4.如何使用两个栈模拟队列操作
1 public class TwoStackForQueue<E> { 2 3 /* 4 * 用法两个stack 实现队列操作 队列是先进先出的 5 * 思想:设置两个stack A,B, stackA为入队的栈,stackB为出队的栈 6 * 入队直接进栈A,出栈需要判断栈B是否为空,如果为空,需要将栈A中的元素放入栈B中 7 * 如果不为空 直接获取栈B的栈顶元素 8 */ 9 Stack<E> A = new Stack<>(); 10 Stack<E> B = new Stack<>(); 11 public static void main(String[] args) { 12 TwoStackForQueue<Integer> queue = new TwoStackForQueue<>(); 13 queue.put(1); 14 queue.put(2); 15 queue.put(3); 16 // int i = queue.pop(); 17 // System.out.println(i); 18 // i = queue.pop(); 19 // System.out.println(i); 20 // i = queue.pop(); 21 // System.out.println(i); 22 while(!queue.empty()){ 23 int i = queue.pop(); 24 System.out.println(i); 25 } 26 27 } 28 //判断是否队空 29 public boolean empty(){ 30 return A.isEmpty() && B.isEmpty(); 31 } 32 33 //出队 34 public synchronized E pop(){ 35 /*if(B.isEmpty()){ 36 if(A.isEmpty()) 37 return null; 38 while(!A.isEmpty()) 39 { 40 B.push(A.pop()); 41 } 42 return B.pop(); 43 } 44 return B.pop();*/ 45 //优化 46 if(B.isEmpty()){ 47 while(!A.isEmpty()) 48 { 49 B.push(A.pop()); 50 } 51 } 52 return B.pop(); 53 } 54 //入队 55 public synchronized void put(E e){ 56 A.push(e); 57 } 58 59 60 61 62 }
5.如果使用两个队列模拟栈操作
1 public class TwoQueueForStack<E> { 2 3 /* 4 * 使用两个队列实现栈 栈的特点是先进后出,后进先出 5 * 思路:两个Queue 使用LinkedList实例化 LinkedList实际上是一个双向链表 6 * q1作为入栈的队列 即直接将入栈的数据放入q1 7 * q2作为出栈的队列 即需要出栈时,如果q1只有一个元素 直接出栈 8 * 如果q1不止一个元素,即可以将q1队列中的数据依次放入q2,最后一个不放入,最后一个元素输出 9 * 再将q2中的元素依次放回q1 10 */ 11 private Queue<E> q1 = new LinkedList<E>(); 12 private Queue<E> q2 = new LinkedList<E>();; 13 public static void main(String[] args) { 14 TwoQueueForStack<Integer> stack = new TwoQueueForStack<>(); 15 stack.put(1); 16 stack.put(2); 17 stack.put(3); 18 while(!stack.empty()){ 19 int i = stack.pop(); 20 System.out.println(i); 21 } 22 23 } 24 25 //判断是否栈空 26 public boolean empty(){ 27 return q1.isEmpty() && q2.isEmpty(); 28 } 29 30 //出栈 31 public synchronized E pop(){ 32 int size = q1.size(); 33 if(size==1) 34 return q1.poll(); 35 36 int i=1; 37 while(!(i==size)){ 38 q2.add(q1.poll()); 39 i++; 40 } 41 E e = q1.poll(); 42 43 while(!q2.isEmpty()){ 44 q1.add(q2.poll()); 45 } 46 return e; 47 } 48 //入栈 49 public synchronized void put(E e){ 50 q1.add(e); 51 } 52 53 }
以上是关于数据结构之栈与队列的主要内容,如果未能解决你的问题,请参考以下文章