自己实现栈和队列

栈和队列

双向链表实现

package 链表;
//https://leetcode-cn.com/problems/design-linked-list/submissions/
public class _707_设计链表 {
	/*
	 * ["MyLinkedList","addAtHead","addAtHead","addAtHead","addAtIndex","deleteAtIndex","addAtHead","addAtTail","get","addAtHead","addAtIndex","addAtHead"]
[[],[7],[2],[1],[3,0],[2],[6],[4],[4],[4],[5,0],[6]]
	 */
	public static void main(String[] args) {
		MyLinkedList linkedList = new MyLinkedList();
		linkedList.addAtHead(7); 
		linkedList.addAtHead(2);
		linkedList.addAtHead(1);  //1->2->7
		
	
		linkedList.addAtIndex(3,0);   //1->2->7->0
	System.out.println(linkedList.size);
		linkedList.deleteAtIndex(2);  //1->2->0
		linkedList.addAtHead(6);  //6->1->2->0

		linkedList.addAtTail(4);  //6->1->2->0->4
		System.out.println(linkedList.size);
		System.out.println("-------------------");
		System.out.println(linkedList.get(0));
		System.out.println(linkedList.get(1));
		System.out.println(linkedList.get(2));
		System.out.println(linkedList.get(3));		
		System.out.println(linkedList.get(4));
		linkedList.addAtHead(4);
		linkedList.addAtIndex(5,0);  
		linkedList.addAtHead(6);
		
	}
}
class MyLinkedList {
	int size;
	DoubleListNode head,tail;
	
    /** Initialize your data structure here. */
    public MyLinkedList() {
    	size = 0;
    	head = new DoubleListNode(0);
    	tail = new DoubleListNode(0);
    	head.next = tail;
    	tail.pre = head;
    }
    
    //获得指定位置的元素
    /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
    public int get(int index) {
    	if(index >= size || index < 0) return -1;
    	
    	
    	DoubleListNode cur = head;
    	for(int i =0;i<index+1;i++) {
    		cur = cur.next;
    	}
    	return cur.val;
    }
    
    //头插法
    /** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
    public void addAtHead(int val) {
    	DoubleListNode newNode = new DoubleListNode(val);
    	
    	head.next.pre = newNode;
    	newNode.next = head.next;
    	head.next = newNode;
    	newNode.pre = head;
    	size++;
    }
    
    //尾插法
    /** Append a node of value val to the last element of the linked list. */
    public void addAtTail(int val) {
    	DoubleListNode newNode = new DoubleListNode(val);
    	tail.pre.next = newNode;
    	newNode.pre = tail.pre;
    	newNode.next = tail;
    	tail.pre = newNode;
    	size++;
    	
    }
    
    //添加指定位置的元素
    /** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
    public void addAtIndex(int index, int val) {
    	if(index <= 0) {
    		addAtHead(val);
    		return;
    	}
    	if(index == size)  {
    		addAtTail(val);
    		return ;
    	}
    	if(index > size) return;
    	
    	DoubleListNode newNode = new DoubleListNode(val);
    	DoubleListNode cur = head;
    	for(int i =0;i < index+1;i++) {
    		cur = cur.next;
    	}
    	cur.pre.next = newNode;
    	newNode.pre = cur.pre;
    	cur.pre = newNode;
    	newNode.next = cur;
    	size++;
    	
    }
    
    //删除指定位置的元素
    /** Delete the index-th node in the linked list, if the index is valid. */
    public void deleteAtIndex(int index) {
    	if(index < 0 || index >= size) return;
    	
    	DoubleListNode cur = head;
    	for(int i =0;i<index+1;i++) {
    		cur = cur.next;
    	}
    	
    	cur.next.pre = cur.pre;
    	
    	   	
    	cur.pre.next = cur.next;  
    	size--;
    }
}
class DoubleListNode {
	int val;
	DoubleListNode next;
	DoubleListNode pre;
	public DoubleListNode(int val) {
		super();
		this.val = val;
	}
}

实现双端队列,然后使用队列实现栈

package day2;
//使用双向链表实现队列
public class Code03_DoubleEndsQueueToStackAndQueue {
	//定义链表节点
	public static class Node<T> {
		public T value;
		public Node<T> last;
		public Node<T> next;
		
		public Node(T data) {
			value = data;
		}
	}
	
	public static class DoubleEndsQueue<T> {
		public Node<T> head;
		public Node<T> tail;
		
		//头插法
		public void addFromHead(T value) {
			Node<T> cur = new Node<T>(value);
			if(head == null) {
				head = cur;
				tail = cur;
			} else {
				head.last = cur;
				cur.next = head;
				head = cur;
			}	
		}
		
		 //尾插法
		public void addFromBottom(T value) {
			Node<T> cur = new Node<T>(value);
			if(tail == null) {
				tail = cur;
				head = cur;
			} else {
				tail.next = cur;
				cur.last = tail;
				tail = cur;	
			}
					
		}
		//从头部取出元素
		public T popFromHead() {
			Node<T> temp = head;
			if(head == null) {
				return null;
			} 
			if(head == tail) {
				head =null;
				tail = null;
			} else {
				temp = head;
				head = temp.next;		
				head.last = null;
				temp.next = null;
			}
			return temp.value;				
		}
		
		//从尾部取出元素
		public T popFromBottom() {
			Node<T> temp = tail;
			if(head == null) {
				return null;
			} 
			if(head == tail) {
				head =null;
				tail = null;	
			} else {
				temp = tail;
				tail = temp.last;
				tail.next = null;
				temp.last = null;
			}
			return temp.value;					
		}
		
		//是否为空
		public boolean isEmpty() {
			return head == null;	
		}	
	}
	//实现双端对列
	public static class MyStack<T> {
		private DoubleEndsQueue<T> queue;

		public MyStack() {
			queue = new DoubleEndsQueue<T>();
		}
	
		public void push(T value) {
			queue.addFromHead(value);
		}

		public T pop() {
			return queue.popFromHead();
		}

		
		public boolean isEmpty() {
			return queue.isEmpty();
		}
	}
	public static class MyQueue<T> {
		private DoubleEndsQueue<T> queue;

		public MyQueue() {
			queue = new DoubleEndsQueue<T>();
		}

		public void push(T value) {
			queue.addFromHead(value);
		}

		public T poll() {
			return queue.popFromBottom();
		}

		public boolean isEmpty() {
			return queue.isEmpty();
		}
	}

	public static void main(String[] args) {
		DoubleEndsQueue<Integer> dq = new DoubleEndsQueue<Integer>();
		dq.addFromBottom(3);
		dq.addFromBottom(1);
		dq.addFromBottom(2);
		dq.addFromBottom(4);
		dq.addFromHead(5);
		dq.addFromHead(0);
		dq.addFromBottom(7);
		
		System.out.println(dq.popFromHead());
		System.out.println(dq.popFromHead());
		System.out.println(dq.popFromHead());
		System.out.println(dq.popFromHead());
		System.out.println(dq.popFromHead());
		System.out.println(dq.popFromHead());
		System.out.println(dq.popFromHead());	
	}
}

数组实现(面试中一般出现固定大小)

栈比较容易实现

package day2;

public class Code05_RingArray {
	
	public static class MyStack {
		private int[] arr;
		private int top;
		private int size;		
		private  final int maxLimit;
		
		public MyStack(int limit) {
			arr = new int[limit];
			top = -1;	
			size = 0;
			this.maxLimit = limit;
		}
		
		//入栈
		public void push(int value) {
			if(size == maxLimit) {
				throw new RuntimeException("栈满了");
			}
			size++;
			arr[++top] = value;	
		}
		//出栈
		public int pop() {
			if(size == 0) {
				throw new RuntimeException("队列为空");
			}
			size--;	
			return arr[top--];
		}
		
		//为空
		public boolean isEmpty() {
			return size == 0;
			
		}
	}
	public static void main(String[] args) {
		MyStack s = new MyStack(5);
		s.push(1);
		s.push(2);
		s.push(3);
		s.push(4);
		s.push(5);
		while(!s.isEmpty()) {
			System.out.println(s.pop());
		}	
	}
}

队列实现使用rebuffer,循环队列

public static class MyQueue {
		private int[] arr;
		private int pushi;
		private int polli;
		private int size;
		private final int limit;

		public MyQueue(int k) {
			arr = new int[k];
			pushi = 0;
			polli = 0;
			size = 0;
			this.limit = k;
		}
		
		//元素插入成功返回true
		public boolean enQueue(int value) {
			if(isFull()) return false;
			arr[pushi] = value;
			pushi = nextIndex(pushi);
			size++;
			return true;
		}
		//元素删除成功返回true	
		public boolean deQueue() {
			if(isEmpty()) return false;
			polli = nextIndex(polli);			
			size--;
			return true;
		}
//		队首获取元素。如果队列为空,返回 -1 	
		public int Front() {
			if(isEmpty()) return -1;
			
			return arr[polli];	
		}
//		获取队尾元素。如果队列为空,返回 -1 。	
		public int Rear() {
			if(isEmpty()) return -1;
			return arr[lastIndex(pushi)];	
		}
		
		//是否为空
		public boolean isEmpty() {
			return size == 0;
		}
		//是否为满
		public boolean isFull() {
			return size == limit;	
		}
		// 如果现在的下标是i,返回下一个位置
		private int nextIndex(int i) {
			return i < limit - 1 ? i + 1 : 0;
		}
		private int lastIndex(int i) {
			return i > 0 ? i - 1 : limit-1;
		}
	}

栈的常见面试题:

1.实现一个特殊的栈,在基本功能的基础上,再实现返回栈中最小元素的功能

  1. pop、push、getMin操作的时间复杂度都是O(1)。

2)设计的栈类型可以使用现成的栈结构。

两个栈,一个栈,和一个最小栈

小于等于压入最小栈,大于不压人。

public static class MinStack {
		Stack<Integer> minStack;
		Stack<Integer> stack;
		
	    /** initialize your data structure here. */
	    public MinStack() {
	    	minStack = new Stack<Integer>();
	    	stack = new Stack<Integer>();
	    }
//	    将元素 x 推入栈中。
	    public void push(int val) {
	    	if(this.minStack.isEmpty()) {
	    		minStack.push(val);
	    	} else if(minStack.peek() > val) {
	    		minStack.push(val);
	    	}
	    	stack.push(val);
	    	
	    }
//	    删除栈顶的元素。
	    public void pop() {
	    	int ans = stack.pop();
	    	if(ans == minStack.peek()) {
	    		minStack.pop();
	    	}
	    }
//	     获取栈顶元素。
	    public int top() {
	    	if(!stack.isEmpty()) {
	    		return stack.peek();
	    	}
	    	return -1;
	    }
//	    检索栈中的最小元素。
	    public int getMin() {
	    	if(!minStack.isEmpty()) {
	    		return minStack.peek();
	    	}
	    	return -1;
	    }
	}

2.如何用栈结构实现队列结构?

两个栈结构拼接队列结构

注意:

pop栈空才能导入数据

push必须一次性导出完整的结构

package day2;

import java.util.Stack;

//使用两个栈实现队列
public class Code06_TwoStacksImplementQueue {
//	定义一个内部类
	public static class TwoStacksQueue {

		public Stack<Integer> stackPush;
		public Stack<Integer> stackPop;
		
//		构造函数
		public TwoStacksQueue() {
			stackPush = new Stack<Integer>();
			stackPop = new Stack<Integer>();
		}
		//push向pop导入数据
		private void pushToPop() {
			//如果出队栈为空
			if(stackPop.isEmpty()) {
				while(!stackPush.isEmpty()) {
					stackPop.add(stackPush.pop());
				}
			}
		}
		
//		入队
		public void add(int pushInt) {
			stackPush.add(pushInt);			
			
		}
		
//		出队
		public int poll() {
			if(stackPop.isEmpty()&& stackPush.isEmpty()) {
				throw new RuntimeException("队列为空");	
			}
			pushToPop();
			return stackPop.pop();	
		}
		//查看队头元素
		public int peek() {
			if(stackPop.isEmpty()&& stackPush.isEmpty()) {
				throw new RuntimeException("队列为空");	
			}
			pushToPop();	
			return stackPop.peek();			
		}		
	}
	public static void main(String[] args) {
		TwoStacksQueue test = new TwoStacksQueue();
		test.add(1);
		test.add(2);
		test.add(3);
		System.out.println(test.peek());
		System.out.println(test.poll());
		System.out.println(test.peek());
		System.out.println(test.poll());
		System.out.println(test.peek());
		System.out.println(test.poll());
		//数据1,1,2,2,3,3。
	}
}

3.如何用队列结构实现栈结构?

两个队列结构,

package day2;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

//使用对列实现栈
public class MyStack {
	public Queue<Integer> queue;
	public Queue<Integer> help;
	
	 /** Initialize your data structure here. */
    public MyStack() {
    	 queue = new LinkedList<Integer>();
    	 help = new LinkedList<Integer>();
    }
    
    /** Push element x onto stack. */
    public void push(int x) {
    	//首先加入主队列
    	queue.offer(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
    	while(queue.size() >1) {
    		help.offer(queue.poll());
    	}
    	Integer ans = queue.poll();
    	//将两个队列指向交换
    	Queue<Integer> tmp = queue;
    	queue = help;
    	help = tmp;
    	//返回出队的值
    	return ans;	
    }
    
    /** Get the top element. */
    public int top() {
    	while(queue.size() >1) {
    		help.offer(queue.poll());
    	}
    	Integer ans = queue.peek();
    	help.offer(queue.poll());
    	//将两个队列指向交换
    	Queue<Integer> tmp = queue;
    	queue = help;
    	help = tmp;
    	//返回出队的值
    	return ans;		
    }
    
    /** Returns whether the stack is empty. */
    public boolean empty() {
    	return queue.isEmpty();	
    }	
}
posted @ 2021-06-28 20:19  IT小五  阅读(61)  评论(0)    收藏  举报