劍指Offer面試題:6.用兩個棧實現隊列


一、題目:用兩個棧實現隊列

題目:用兩個棧實現一個隊列。隊列的聲明如下,請實現它的兩個函數appendTail和deleteHead,分別完成在隊列尾部插入結點和在隊列頭部刪除結點的功能。

  原文是使用C++結合模板實現的定義,這里我們采用C#結合泛型來實現這個隊列的定義,我們要實現的就是兩個方法:AppendTail與DeleteHead

    public class CQueue<T>
    {
        private Stack<T> stack1;
        private Stack<T> stack2;

        public CQueue()
        {
            this.stack1 = new Stack<T>();
            this.stack2 = new Stack<T>();
        }

        public void AppendTail(T item)
        {
        }

        public T DeleteHead()
        {
        }
    }

二、解題思路

  一個隊列包含了兩個棧stack1和stack2,因此這道題的意圖是要求我們操作這兩個“先進后出”的棧實現一個“先進先出”的隊列CQueue。對於兩個棧而言,對於插入操作,不妨假設都先插入到stack1,也就實現了入隊操作。但是出隊操作,則需要借助stack2的過渡:

  當stack2中不為空時,在stack2中的棧頂元素是最先進入隊列的元素,可以彈出。如果stack2為空時,我們把stack1中的元素逐個彈出並壓入stack2。由於先進入隊列的元素被壓到stack1的底端,經過彈出和壓入之后就處於stack2的頂端了,又可以直接彈出。下圖展示了一個使用兩個棧實現隊列的實例:

三、解決問題

3.1 代碼實現

    public void AppendTail(T item)
    {
        stack1.Push(item);
    }

    public T DeleteHead()
    {
        if(stack2.Count <= 0)
        {
            while(stack1.Count > 0)
            {
                T item = stack1.Pop();
                stack2.Push(item);
            }
        }

        if(stack2.Count == 0)
        {
            throw new Exception("The queue is empty!");
        }

        T head = stack2.Pop();
        return head;
    }

  借用作者的話:本題解法的代碼雖然只有只有20幾行代碼,但形成正確的思路卻不容易

3.2 單元測試

  (1)往空的隊列里添加、刪除元素

    [TestMethod]
    public void CQueueTest1()
    {
        CQueue<char> queue = new CQueue<char>();
        queue.AppendTail('a');
        queue.AppendTail('b');
        queue.AppendTail('c');

        char head = queue.DeleteHead();
        Assert.AreEqual(head, 'a');
    }

    [TestMethod]
    public void CQueueTest2()
    {
        CQueue<char> queue = new CQueue<char>();
        queue.AppendTail('a');
        queue.AppendTail('b');
        queue.AppendTail('c');

        char head = queue.DeleteHead();
        head = queue.DeleteHead();

        Assert.AreEqual(head, 'b');
    }

  (2)往非空的隊列里添加、刪除元素

    [TestMethod]
    public void CQueueTest3()
    {
        CQueue<char> queue = new CQueue<char>();
        queue.AppendTail('a');
        queue.AppendTail('b');
        queue.AppendTail('c');

        char head = queue.DeleteHead();
        head = queue.DeleteHead();

        queue.AppendTail('d');
        head = queue.DeleteHead();

        Assert.AreEqual(head, 'c');
    }

    [TestMethod]
    public void CQueueTest4()
    {
        CQueue<char> queue = new CQueue<char>();
        queue.AppendTail('a');
        queue.AppendTail('b');
        queue.AppendTail('c');

        char head = queue.DeleteHead();
        head = queue.DeleteHead();

        queue.AppendTail('d');
        head = queue.DeleteHead();

        queue.AppendTail('e');
        head = queue.DeleteHead();

        Assert.AreEqual(head, 'd');
    }

  (3)連續刪除元素直至隊列為空

    [TestMethod]
    public void CQueueTest5()
    {
        CQueue<char> queue = new CQueue<char>();
        queue.AppendTail('a');
        queue.AppendTail('b');
        queue.AppendTail('c');

        char head = queue.DeleteHead();
        head = queue.DeleteHead();

        queue.AppendTail('d');
        head = queue.DeleteHead();

        queue.AppendTail('e');
        head = queue.DeleteHead();
        head = queue.DeleteHead();

        Assert.AreEqual(head, 'e');
    }

  單元測試的結果如下圖所示:

  代碼覆蓋率結果如下圖所示,可以看到,還需要繼續增加測試用例才能使得覆蓋率達到100%:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM