數據結構--堆棧(Java版)

一、棧的介紹

棧(stack)又名堆棧,它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱爲棧頂,相對地,把另一端稱爲棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成爲新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成爲新的棧頂元素。

棧的特點:先進後出

二、棧的簡單操作

1、棧的定義

/**
 * 棧的接口
 * @author hoaven
 * @see Stack
 * @see SetOfStacks
 * @see StackWithMin
 */
public interface IStack<T> {
	
	/**
	 * 入棧操作
	 * @param item
	 */
	void push(T item);
	
	/**
	 * 出棧操作
	 * @return
	 */
	T pop();
	
	/**
	 * 返回棧頂元素,但不出棧
	 * @return
	 */
	T peek();
	
	/**
     * 棧是否爲空
     * @return boolean
     */
	boolean isEmpty();
}

2、棧的基本實現

/**
 * 棧的實現
 *
 * @author hoaven
 * @see IStack
 * @see Node		結點元素,具體定義請見鏈表的實現博客
 */
public class Stack<T> implements IStack<T> {
    //棧頂
    Node<T> top;

    public T pop() {
        if (top != null) {
            T item = top.data;
            //棧頂下移
            top = top.next;
            return item;
        }

        return null;
    }

    public void push(T item) {
        Node<T> t = new Node<T>(item);
        //新棧頂的next域指向舊棧頂
        t.next = top;
        top = t;
    }

    public T peek() {
        if (top != null) {
            return top.data;
        }
        return null;
    }


    public boolean isEmpty() {
        return (top == null);
    }
}

//單元測試
@Test
public void testStack(){
		stack = new Stack<Integer>();
		stack.push(1);
		stack.push(2);
		Assert.assertEquals(Integer.valueOf(2), stack.peek());
		Assert.assertEquals(Integer.valueOf(2), stack.pop());
		
		stack.push(3);
		Assert.assertEquals(Integer.valueOf(3), stack.pop());
		Assert.assertFalse(stack.isEmpty());
		Assert.assertEquals(Integer.valueOf(1), stack.pop());
		
		Assert.assertEquals(null, stack.peek());
		Assert.assertEquals(null, stack.pop());
		Assert.assertTrue(stack.isEmpty());
	}

三、其他棧的實現

1、記錄棧的最大存儲容量和棧中內容實際索引值

/**
 * 記錄棧的最大存儲容量和棧中內容實際索引值
 *
 * @author hoaven
 */
public class StackCapacity<T> extends Stack<T> {
    private int capacity;
    private int index = 0;

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    //構造棧時指定棧的最大容量
    public StackCapacity(int capacity) {
        this.capacity = capacity;
    }

    public void push(T data) {
        if (index >= capacity) {
            throw new RuntimeException("棧容量不足");
        }
        super.push(data);
        index++;
    }

    public T pop() {
        index--;
        return super.pop();
    }

    public boolean isFull() {
        return (index == capacity);
    }
}

2、一個能隨時獲取棧中最小值的棧

/**
 * 一個能隨時獲取棧中最小值的棧的實現
 * 實際上有兩個棧,第一個棧記錄所有的元素,第二個棧stackMin記錄每次入棧後當前棧中的最小值
 *
 * @author hoaven
 * @see IStack
 * @see Node
 */
public class StackWithMin extends Stack<Integer> {
    Stack<Integer> stackMin;

    public StackWithMin() {
        stackMin = new Stack<Integer>();
    }

    public void push(Integer item) {
        if (item <= min()) {
            //item爲當前棧中的最小值
            stackMin.push(item);
        }
        //第一個棧也要入棧
        super.push(item);
    }

    public Integer pop() {
        int value = super.pop();
        if (value == min()) {
            //出棧後,stackMin的棧頂就是第一個棧中剩餘元素的最小值
            stackMin.pop();
        }
        return value;
    }

    /**
     * 取得棧中的最小值
     *
     * @return
     */
    public Integer min() {
        if (stackMin.isEmpty()) {
            return Integer.MAX_VALUE;
        } else {
            return stackMin.peek();
        }
    }
}

//測試
@Test
public void testStackWithMin(){
		StackWithMin s = new StackWithMin();
        s.push(4);
        s.push(2);
        Assert.assertEquals(Integer.valueOf(2), s.min());
        
        s.push(3);
        Assert.assertEquals(Integer.valueOf(2), s.min());
        
        s.push(1);
        Assert.assertEquals(Integer.valueOf(1), s.min());
        
        Assert.assertEquals(Integer.valueOf(1), s.peek());
        Assert.assertEquals(Integer.valueOf(1), s.pop());
        Assert.assertEquals(Integer.valueOf(2), s.min());
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章