栈(先进后出)
实现栈
1、数组实现
java程序员面试笔试宝典实现:
package JBStack;
import java.util.Arrays;
public class MySqStack<E>{
private Object[] stack; //声明数组
private int size;//数组元素
public MySqStack() {//构造函数
// TODO Auto-generated constructor stub
stack = new Object[10]; //默认大小
}
/**
* 判断是否为空
* @return
*/
private boolean isEmpty(){
return size == 0;
}
/**
* 取出栈顶元素
* @return
*/
private E peek(){
if (size==0) {
return null;//空栈
}
return (E) stack[size-1];//返回数组最后一个元素,即栈顶元素
}
/**
* 出栈
* @return
*/
private E pop(){
if (isEmpty()) {//判断是否为空
return null;
}
E e = peek();//取出栈顶元素
stack[size-1]=null;//栈顶元素置空
size--;//长度递减
return e;//返回栈顶元素值
}
/**
* 入栈
* @param item
* @return
*/
private E push(E item){
ensureCapacity(size+1);//判断是否是满栈,如果栈满则扩充长度
stack[size++]=item;//依次添加,下标从0开始
return item;//返回入栈值
}
/**
* 判断是否是满栈,如果栈满则扩充长度
* @param i
*/
private void ensureCapacity(int i){
int len = stack.length;
if(size>len){
int newLen = 10;
stack = Arrays.copyOf(stack, newLen);//利用数组函数
}
}
public static void main(String[] args) {
MySqStack<Integer> ss = new MySqStack<Integer>();
ss.push(1);
ss.push(2);
ss.push(3);
System.out.println("栈元素个数"+ss.size);
System.out.println("栈顶元素"+ss.pop());
System.out.println("栈顶元素"+ss.pop());
}
}
大话数据结构:
package Stack;
/**
* 栈的顺序储存结构
*
* 问题:构造器中,泛型数组创建是否有更好的方法?
* @author Yongh
*
*/
public class SqStack<E> {
private E[] data; //数据
private int top; //栈顶指针,top=-1时为空栈
private int maxSize; //栈大小
private static final int DEFAULT_SIZE= 10; //栈默认大小
public SqStack() {
this(DEFAULT_SIZE);
}
public SqStack(int maxSize) {
//无法创建泛型数组 data=new E[maxSize];
data=(E[]) new Object[maxSize];
top=-1;
this.maxSize=maxSize;
}
public void push(E e) {
if(top==maxSize-1)
throw new RuntimeException("栈已满,无法进栈!");
top++;
data[top]=e;//先赋值后运算,即T=top++:T=top; top=top+1;而T=++top:先运算后赋值:top=top+1;T=top;
}
public E pop() {
if(top==-1)
throw new RuntimeException("空栈,无法出栈!");
E e=data[top];
top--;
return e;
}
public void printStack() {
if(top==-1) {
System.out.println("空栈");
}else {
for(int i=0;i<=top;i++) {
System.out.println(data[i]);
}
}
}
}
2、链表实现
java程序员面试笔试宝典实现(首选):
package JBStack;
/**
* 链栈实现
* @author Dan
*
* @param <E>
*/
public class MyStack<E> {
Node<E> top = null;//头结点
public class Node<E>{
Node<E> next;
E data;
public Node(E data){
this.data = data;
}
}
/**
* 判断是否为空栈
*/
public boolean isEmpty(){
return top==null;
}
/**
* 入栈
* @param data
*/
public void push(E data){
Node<E> newNode = new Node<E>(data);
newNode.next = top;//在首部插入
top = newNode;
}
/**
* 出栈
* @return
*/
public E pop(){
if (this.isEmpty()) {
return null;
}
E e = top.data;
top.next =top.next;
return e;
}
/**
* 获取栈顶元素
* @return
*/
public E peek(){
if (isEmpty()) {
return null;
}
return top.data;
}
}
大话数据结构:
package Stack;
/**
*
* 栈的链式存储结构
* 栈顶放在单链表的头部
* 类似单链表
* @author Yongh
*/
public class LinkStack<E> {
private StackNode<E> top; //栈顶相当于单链表头结点
private int count; //栈链的长度
/**
* 栈链的结点
* @author Dan
*
* @param <E>
*/
private class StackNode<E>{
E data;
StackNode<E> next;
public StackNode(E data,StackNode<E> next) {
this.data=data;
this.next=next;
}
}
/**
* 初始化栈链
*/
public LinkStack() {
top=new StackNode<E>(null, null);
count=0;
}
/**
* 入栈
* @param e
*/
public void push(E e) {
StackNode<E> node=new StackNode<E>(e, top);//一直是在栈顶操作即头结点出进行插入,初始化node(e,top)
top=node;
count++;
}
/**
* 出栈
* @return
*/
public E pop() {
if(count==0)
throw new RuntimeException("空栈,无法出栈!");
StackNode<E> node; //新建结点
node=top; //存储要删除的栈顶结点
E e=node.data; //获取删除结点的数据
top=top.next; //栈顶指针后移一位
node=null; //释放栈顶结点
count--; //长度减一
return e;
//返回数据
}
public void printStack() {
if(count==0) {
System.out.println("空栈");
}else {
StackNode<E> node=top; //新建栈链点存放要打印的点
for(int i=0;i<count;i++) {
System.out.println(node.data);
node=node.next; //依次从栈顶(链表头结点)向下遍历输出
}
}
}
/*
* 测试代码
*/
public static void main(String[] args) {
LinkStack<Student> linkStack=new LinkStack<Student>();
Student[] students= {new Student("小A",11),new Student("小B",12),new Student("小C",13),
new Student("小D",14),new Student("小E",151)};
for(int i=0;i<5;i++) {
linkStack.push(students[i]);
}
linkStack.printStack();
System.out.println("----");
for(int i=0;i<5;i++) {
System.out.println(linkStack.pop());//先入后出
}
linkStack.printStack();
}
}
如何用O(1)的时间复杂度求栈中最小元素
package JBStack;
/**
* 如何用O(1)的时间复杂度求栈中最小元素
* 1、使用elem 和 min两个栈结构,elem用来存储结构,min用来存储elem最小元素
* 2、在入栈时,如果当前入栈元素比原来栈中元素要小,则把这个值压入min栈中
* 3、在出栈时,先获取当前出栈元素恰好为当前栈中的最小值,则min栈的栈顶元素也出栈。
* 使当前最小值变为其入栈之前的那个最小值。
* @author Dan
*
*/
public class MyStack1{
MyStack<Integer> elem;
MyStack<Integer> min;
public MyStack1(){
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;
}
/**
* 求min中栈顶元素
* @return
*/
public int min() {
if(min.isEmpty())
return Integer.MAX_VALUE;
else
return min.peek();
}
}
队列
实现队列
链表实现
java程序员面试笔试宝典(首选):
package JBQueue;
import org.w3c.dom.Node;
public class MyQueue<E> {
Node<E> head = null;
Node<E> tail = null;
class Node<E> {
Node<E> next;
E data;
public Node(E data){
this.data = data;
}
}
public boolean isEmpty(){
return head==tail;
}
public void put(E data){
Node<E> newNode = new Node<E>(data);
if (head==null&&tail==null) {
head = 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> node = head;
int n = 0;
while(node !=null){
n++;
node = node.next;
}
return n;
}
public static void main(String[] args) {
MyQueue<Integer> queue = new MyQueue<Integer>();
queue.put(1);
queue.put(2);
queue.put(3);
System.out.println("队列长度:"+queue.size());
System.out.println("队列首元素:"+queue.pop());
}
}
大话数据结构:
package Queue;
/**
* 链队列
* 队尾指针指向终端结点
*
* 注意点:出队操作时,若队头是队尾(即队中仅有一个结点),
* 则删除后要将rear指向头结点。
*
* @param <E>
*/
public class LinkQueue<E> {
private QNode front,rear;
private int count;
/**
* 结点
*/
class QNode{
E data;
QNode next;
public QNode(E data,QNode next) {
this.data=data;
this.next=next;
}
}
/**
* 链队列的初始化
*/
public LinkQueue() {
front= new QNode(null, null);
rear = front;
count = 0;
}
/*
* 入队操作(尾结点插入)
*/
public void enQueue(E e) {
QNode node=new QNode(e, null); //将要插入的数据放进新的结点
rear.next=node; //从队尾插入,新的结点为队尾结点的后继
rear=node; //新节点成为队尾结点.
count++; //长度增加
}
/*
* 出队操作
*/
public E deQueue() {
if(rear==front)
throw new RuntimeException("队列为空!");
QNode node=front; //将欲删除的队头结点暂时存给node
E e=node.data; //将欲删除的队头结点的值赋值为e
front = node.next; //将原对头结点后继赋值赋值给头结点后继
if(rear==node) //若队头是队尾,则删除后要将rear指向头结点。
rear=front;
node=null; //置为null
count--;
//通过count来判断,可能更容易理解
//if(count==0)
// rear=front;
return e;
}
/*
* 获取队列长度
*/
public int getLength() {
return count;
}
/*
* 打印输出队列
*/
public void printQueue() {
if(count==0) {
System.out.println("空队列");
}else {
QNode node=front;
for(int i=0;i<count;i++) {
node=node.next;
System.out.print(node.data+" ");
}
System.out.println();
}
}
/*
* 测试代码
*/
public static void main(String[] args) {
LinkQueue<String> lQueue =new LinkQueue<>();
lQueue.printQueue();
lQueue.enQueue("A");
lQueue.enQueue("B");
lQueue.enQueue("c");
lQueue.enQueue("D");
lQueue.printQueue();
lQueue.deQueue();
lQueue.deQueue();
lQueue.enQueue("E");
lQueue.printQueue();
}
}
循环链表实现:
大话数据结构思路:
package Queue;
/**
* <循环队列>
*
* 注意点:表长的表示、队列满的判断、front和rear的改变
* 因为rear可能比front大,也可能比front小,
* 所以队列满的条件应该为:(rear+1)%maxSize==front;
* 同理,队列长度的计算公式为:maxSize-front + (rear+0)===>(rear-front+maxSize)
* 通用计算队列长度公式为:(rear-front+maxSize)%maxSize
* @author Lai
*
*/
public class SqQueue<E> {
private E[] data; //数据域
private int front;//队头(删除)
private int rear; //队尾(插入)
private int maxSize;//队列最大长度
private static final int DEFAULT_SIZE= 10;
/*
* 初始化
*/
public SqQueue(){
this(DEFAULT_SIZE);
}
public SqQueue(int maxSize){
data=(E[]) new Object[maxSize];
this.maxSize=maxSize;
front=0;
rear=0;
}
/*
* 求循环队列长度
*/
public int getLength() {
return (rear-front+maxSize)%maxSize;
}
/*
* 入队操作
*/
public void enQueue(E e) {
if((rear+1)%maxSize==front)
throw new RuntimeException("队列已满,无法入队!");
data[rear]=e; //队尾插入
rear=(rear+1)%maxSize;
//不是rear=rear+1,当rear在数组尾部时,后移一位会转到数组头部
}
/*
* 出队操作
*/
public E deQueue() {
if(rear==front)
throw new RuntimeException("队列为空!");
E e=data[front];//队首插入
front=(front+1)%maxSize;
//不是front++,理由同rear
return e;
}
/*
* 打印操作
*/
public void printQueue() {
int k=front;
for(int i=0;i<getLength();i++) {
System.out.print(data[k]+" ");
k=(k+1)%maxSize;
}
System.out.println();
}
/*
* 测试代码
*/
public static void main(String[] args) {
SqQueue<String> aQueue=new SqQueue<>(5);
aQueue.enQueue("a");
aQueue.enQueue("b");
aQueue.enQueue("c");
aQueue.enQueue("d");
aQueue.printQueue();
System.out.println("-----");
aQueue.getLength();
aQueue.deQueue();
aQueue.deQueue();
aQueue.enQueue("e");
aQueue.printQueue();
}
}
两个栈实现队列
package JBQueue;
/**
* 两个栈实现队列
* 1、利用java内置的stack:import java.util.Stack;
* 2、栈S1用来提供入队列功能,栈s2用来提供出队列的功能
* 3、入队列入栈s1就可以
* 4、出队列分两种情况:
* 4.1 栈s2不为空,直接弹出s2中的数据
* 4.2 栈s2为空,依次弹出栈s1的数据放入到栈s2中,再弹出S2的数据。
*
*/
import java.util.Stack;
public class SSQueue<E> {
Stack<E> s1 = new Stack<E>();
Stack<E> s2 = new Stack<E>();
public boolean Empty(){
return s1.isEmpty() && s2.isEmpty();
}
public synchronized void put(E e){
s1.push(e);
}
public synchronized E pop(){
if(s2.isEmpty()){
while(!s1.isEmpty()){
s2.push(s1.pop());
}
}
return s2.pop();
}
public static void main(String[] args) {
SSQueue<Integer> ssq = new SSQueue<Integer>();
ssq.put(1);
ssq.put(2);
System.out.println("队列首元素:"+ssq.pop());
System.out.println("队列首元素:"+ssq.pop());
}
}
两个队列实现栈
package JBQueue;
import java.util.ArrayDeque;
import java.util.Queue;
/**
* 两个队列实现一个栈
* 1、两个队列q1 q2,q1提供压栈功能 q2提供弹栈功能
* 2、若队列q1只有一个元素,则让q1中的元素出队列并输出即可
* 3、若队列q1中不止一个元素,则队列q1中的所有元素出队列,入队列q2,
* 最后一个元素不入队列q2,
* 输出该元素,然后将队列q2所有入队列q1
* @author Dan
*
*/
public class QQStack {
Queue<Integer> queue1 = new ArrayDeque<Integer>();
Queue<Integer> queue2 = new ArrayDeque<Integer>();
/*
* 向栈中压入数据
*/
public void push(Integer element){
//两个队列都为空时,优先考虑 queue1
if(queue1.isEmpty() && queue2.isEmpty()){
queue1.add(element);
return;
}
//如果queue1为空,queue2有数据,直接放入queue2
if(queue1.isEmpty()){
queue2.add(element);
return;
}
//如果queue2为空,queue1有数据,直接放入queue1中
if(queue2.isEmpty()){
queue1.add(element);
return;
}
}
/*
* 从栈中弹出一个数据
*/
public Integer pop(){
//如果两个栈都为空,则没有元素可以弹出,异常
if(queue1.isEmpty() && queue2.isEmpty()){
try{
throw new Exception("satck is empty!");
}catch(Exception e){
e.printStackTrace();
}
}
//如果queue1中没有元素,queue2中有元素,将其queue2中的元素依次放入queue1中,直到最后一个元素,弹出即可
if(queue1.isEmpty()){
while(queue2.size() > 1){
queue1.add(queue2.poll());
}
return queue2.poll();
}
//如果queue2中没有元素,queue1中有元素,将其queue1中的元素依次放入queue2中,直到最后一个元素,弹出即可
if(queue2.isEmpty()){
while(queue1.size() > 1){
queue2.add(queue1.poll());
}
return queue1.poll();
}
return (Integer)null;
}
public static void main(String[] args) {
QQStack qs = new QQStack();
qs.push(2);
qs.push(4);
qs.push(7);
qs.push(5);
System.out.println(qs.pop());
System.out.println(qs.pop());
qs.push(1);
System.out.println(qs.pop());
}
}