如何自定义实现堆栈?

755 阅读8分钟
原文链接: blog.csdn.net


(尊重劳动成果,转载请注明出处:blog.csdn.net/qq_25827845… 冷血之心的博客)


      堆栈(Stack)是一种常见的数据结构,符合后进先出(First In Last Out)原则,通常用于实现对象存放顺序的逆序。栈的基本操作有push(添加到堆栈),pop(从堆栈删除),peek(检测栈顶元素且不删除)。


实现方式1:

使用一个队列实现,可以使用LinkedList或者ArrayDeque实现,主要是实现其常用的push、pop以及peek方法。

  1. import java.util.ArrayDeque;  
  2. import java.util.Deque;  
  3. import java.util.LinkedList;  
  4.   
  5. public class MyStackTest{  
  6.     public static void main(String[] args) {  
  7.         MyStack<Integer> stack = new MyStack<Integer>();  
  8.         // 将0、1、2、3、4存入堆栈stack  
  9.         for (int i = 0; i <  5; i++) {  
  10.             stack.push(i);  
  11.         }  
  12.         System.out.println("After pushing 5 elements: " + stack);  
  13.         int m = stack.pop();  
  14.         System.out.println("Popped element = " + m);  
  15.           
  16.         System.out.println("After popping 1 element : " + stack);  
  17.         int n = stack.peek();  
  18.         System.out.println("Peeked element = " + n);  
  19.         System.out.println("After peeking 1 element : " + stack);  
  20.     }  
  21. }  
  22. class MyStack<T> {  
  23. //  private Deque<Integer> queue = new ArrayDeque<Integer>();  
  24.     private Deque<Integer> queue = new LinkedList<Integer>();  
  25.     // push存入元素  
  26.     public void push(Integer element) {  
  27.         queue.addFirst(element);  
  28.     }  
  29.     // pop取出元素  
  30.     public Integer pop() {  
  31.         return queue.removeFirst();  
  32.     }  
  33.     // peek获取元素,但是并不取出元素  
  34.     public Integer peek() {  
  35.         return queue.getFirst();  
  36.     }  
  37.   
  38.     public String toString() {  
  39.         return queue.toString();  
  40.     }  
  41.   
  42. }  
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;

public class MyStackTest{
	public static void main(String[] args) {
		MyStack<Integer> stack = new MyStack<Integer>();
		// 将0、1、2、3、4存入堆栈stack
		for (int i = 0; i < 5; i++) {
			stack.push(i);
		}
		System.out.println("After pushing 5 elements: " + stack);
		int m = stack.pop();
		System.out.println("Popped element = " + m);
		
		System.out.println("After popping 1 element : " + stack);
		int n = stack.peek();
		System.out.println("Peeked element = " + n);
		System.out.println("After peeking 1 element : " + stack);
	}
}
class MyStack<T> {
//	private Deque<Integer> queue = new ArrayDeque<Integer>();
	private Deque<Integer> queue = new LinkedList<Integer>();
    // push存入元素
	public void push(Integer element) {
		queue.addFirst(element);
	}
	// pop取出元素
	public Integer pop() {
		return queue.removeFirst();
	}
    // peek获取元素,但是并不取出元素
	public Integer peek() {
		return queue.getFirst();
	}

	public String toString() {
		return queue.toString();
	}

}
LinkedList:特有方法:
addFirst();
addLast();


getFirst();
getLast();
获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException

removeFirst();
removeLast();
获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException


在JDK1.6出现了替代方法。

offerFirst();
offerLast();

peekFirst();
peekLast();
获取元素,但不删除元素。如果集合中没有元素,会返回null。



pollFirst();
pollLast();
获取元素,但是元素被删除。如果集合中没有元素,会返回null。




实现方式2:

使用int数组来实现

  1. public class StackTest{  
  2.     public static void main(String[] args) {  
  3.         Stack2 stack = new Stack2();  
  4.         // 将0、1、2、3、4存入堆栈stack  
  5.         for (int i = 0; i <  5; i++) {  
  6.             stack.push(i);  
  7.         }  
  8.         System.out.println("After pushing 5 elements: " + stack);  
  9.         int m = stack.pop();  
  10.         int m1 = stack.pop();  
  11.         int m2 = stack.pop();  
  12.         int m3 = stack.pop();  
  13.         System.out.println("Popped element = " + m3);  
  14.           
  15.         System.out.println("After popping 1 element : " + stack);  
  16.         int n = stack.peek();  
  17.         System.out.println("Peeked element = " + n);  
  18.         System.out.println("After peeking 1 element : " + stack);  
  19.     }  
  20. }  
  21. class Stack2 {  
  22.     /** 
  23.      * 栈的最大深度 
  24.      **/  
  25.     protected int MAX_DEPTH = 10;  
  26.   
  27.     /** 
  28.      * 栈的当前深度 
  29.      */  
  30.     protected int depth = 0;  
  31.   
  32.     /** 
  33.      * 实际的栈 
  34.      */  
  35.     protected int[] stack = new  int[MAX_DEPTH];  
  36.   
  37.     /** 
  38.      * push,向栈中添加一个元素 
  39.      * 
  40.      * @param n 待添加的整数 
  41.      */  
  42.     protected void push(int n) {  
  43.         if (depth == MAX_DEPTH - 1) {  
  44.             throw new RuntimeException("栈已满,无法再添加元素。");  
  45.         }  
  46.         stack[depth++] = n;  
  47.     }  
  48.   
  49.     /** 
  50.      * pop,返回栈顶元素并从栈中删除 
  51.      * 
  52.      * @return 栈顶元素 
  53.      */  
  54.     protected int pop() {  
  55.         if (depth == 0) {  
  56.             throw new RuntimeException("栈中元素已经被取完,无法再取。");  
  57.         }  
  58.   
  59.         // --depth,dept先减去1再赋值给变量dept,这样整个栈的深度就减1了(相当于从栈中删除)。  
  60.         return stack[--depth];  
  61.   
  62.     }  
  63.   
  64.     /** 
  65.      * peek,返回栈顶元素但不从栈中删除 
  66.      * 
  67.      * @return 
  68.      */  
  69.     protected int peek() {  
  70.         if (depth == 0) {  
  71.             throw new RuntimeException("栈中元素已经被取完,无法再取。");  
  72.         }  
  73.         return stack[depth - 1];  
  74.     }  
  75.       
  76.     @Override  
  77.     public String toString() {  
  78.         // TODO Auto-generated method stub  
  79.         return stack.toString();  
  80.     }  
  81. }  
public class StackTest{
	public static void main(String[] args) {
		Stack2 stack = new Stack2();
		// 将0、1、2、3、4存入堆栈stack
		for (int i = 0; i < 5; i++) {
			stack.push(i);
		}
		System.out.println("After pushing 5 elements: " + stack);
		int m = stack.pop();
		int m1 = stack.pop();
		int m2 = stack.pop();
		int m3 = stack.pop();
		System.out.println("Popped element = " + m3);
		
		System.out.println("After popping 1 element : " + stack);
		int n = stack.peek();
		System.out.println("Peeked element = " + n);
		System.out.println("After peeking 1 element : " + stack);
	}
}
class Stack2 {
    /**
     * 栈的最大深度
     **/
    protected int MAX_DEPTH = 10;

    /**
     * 栈的当前深度
     */
    protected int depth = 0;

    /**
     * 实际的栈
     */
    protected int[] stack = new int[MAX_DEPTH];

    /**
     * push,向栈中添加一个元素
     *
     * @param n 待添加的整数
     */
    protected void push(int n) {
        if (depth == MAX_DEPTH - 1) {
            throw new RuntimeException("栈已满,无法再添加元素。");
        }
        stack[depth++] = n;
    }

    /**
     * pop,返回栈顶元素并从栈中删除
     *
     * @return 栈顶元素
     */
    protected int pop() {
        if (depth == 0) {
            throw new RuntimeException("栈中元素已经被取完,无法再取。");
        }

        // --depth,dept先减去1再赋值给变量dept,这样整个栈的深度就减1了(相当于从栈中删除)。
        return stack[--depth];

    }

    /**
     * peek,返回栈顶元素但不从栈中删除
     *
     * @return
     */
    protected int peek() {
        if (depth == 0) {
            throw new RuntimeException("栈中元素已经被取完,无法再取。");
        }
        return stack[depth - 1];
    }
    
    @Override
    public String toString() {
    	// TODO Auto-generated method stub
    	return stack.toString();
    }
}
这种实现方式有个问题,在pop方法中,只是单纯的移动了指针,相当于从堆栈中删除了该元素,其实并没有做到真正删除。虽然也可以实现简单的堆栈功能,但会产生如图所示的现象:



其实数组中在pop一次之后,仍然存着5个元素,并没有减少,这样会导致内存泄漏的问题发生。解决办法如下:

  1. protected int pop() {  
  2.        if (depth == 0) {  
  3.            throw new RuntimeException("栈中元素已经被取完,无法再取。");  
  4.        }  
  5.        int result = stack[--depth];  
  6.        stack[depth] = 0;  
  7.        return result;  
  8.    }  
 protected int pop() {
        if (depth == 0) {
            throw new RuntimeException("栈中元素已经被取完,无法再取。");
        }
        int result = stack[--depth];
        stack[depth] = 0;
        return result;
    }

So,在面试的时候,建议使用队列来实现简单的堆栈哦~




如果对你有帮助,记得点赞哦~欢迎大家关注我的博客,可以进群366533258一起交流学习哦~