算法导论 使用单链表实现队列

使用单链表实现队列

1. 算法导论原题

10.2-3
Implement a queue by a singly linked list L. The operations ENQUEUE and DEQUEUE should still take O(1) time.
译:使用一个单链表实现一个队列。入队和出队的时间复杂度都应该是O(1)。

2. 使用单链表实现队列

我们假设链表是用头插法,那么1、2、3插进入链表,在链表中的顺序就变成了3、2、1。如果我们想出队,就必须找到链表尾元素出队。因为要保持出队的时间复杂度是O(1),那么插入操作后要保存第一次插入的结点,出队就可以直接将保存的插入后的结点出队即可,然后出队后还要找到第一次插入的结点的前一个结点,又因为这是单链表,需要遍历整个链表才能找到前一个结点,这显然是违反了时间复杂度为O(1)。
假设链表用尾插法,那么1、2、3插进链表,在链表中的顺序依然是1、2、3、如果我们想出队,只需要将头节点的下一个元素出队。为了保持插入的时间复杂度是O(1),不可能每次插入的时候都去遍历链表,因此需要保存插入后的新节点,插入的操作就在保存的新节点后面插入。因此入队和出队的时间复杂度是O(1),这种方法才是可行的。

3. 实现(C++代码)
//SinglyLink.h
#pragma once

#include <assert.h>
#include <stdio.h>

template<typename ElemType>
class Node
{
public:
    Node(Node<ElemType>* pNext = NULL, ElemType* pData = NULL);
    ElemType const& GetData() const;
    void SetData(ElemType val) ;
    Node<ElemType>* const& GetNext() const;
    void SetNext(Node<ElemType>* val);
private:
    ElemType* m_pData;
    Node<ElemType>* m_pNext;
};

template<typename ElemType>
class SinglyLinkList
{
public:
    SinglyLinkList();
    unsigned int const& GetLength() const;
    bool Insert(ElemType elem, unsigned int pos);
    bool InsertByPosNode(ElemType elem, Node<ElemType>* posNode, Node<ElemType>** RetInsetNode = NULL);
    bool Delete(unsigned int pos, ElemType* elem);
    bool Search(unsigned int pos, ElemType* elem) const;
    bool Visit(ElemType* elem, const unsigned int& pos) const;
    bool Empty();
    Node<ElemType>* HavaHeadNode();
private:
    Node<ElemType>* m_pHeadNode;
    unsigned int m_length;
};


//————————————————————————————————//Node类的实现
template<typename ElemType>
Node<ElemType>::Node(Node<ElemType>* pNext /*= NULL*/, ElemType* pData /*= NULL*/)
    :m_pNext(pNext),m_pData(pData)
{

}


template<typename ElemType>
void Node<ElemType>::SetNext(Node<ElemType>* val)
{
    m_pNext = val;
}

template<typename ElemType>
Node<ElemType>* const& Node<ElemType>::GetNext() const
{
    return m_pNext;
}

template<typename ElemType>
void Node<ElemType>::SetData(ElemType val)
{
    m_pData = val;
}

template<typename ElemType>
ElemType const& Node<ElemType>::GetData() const
{
    return *m_pData;
}

//————————————————————————————————//SinglyLink类实现

template<typename ElemType>
SinglyLinkList<ElemType>::SinglyLinkList()
    :m_pHeadNode(new Node<ElemType>()),m_length(0)
{

}



template<typename ElemType>
bool SinglyLinkList<ElemType>::InsertByPosNode(ElemType elem, Node<ElemType>* posNode, Node<ElemType>** RetInsetNode /*= NULL*/)
{
    Node<ElemType>* insertNode = new Node<ElemType>(posNode->GetNext(),new ElemType(elem));
    posNode->SetNext(insertNode);
    ++m_length;
    *RetInsetNode = insertNode;
    return true;
}


template<typename ElemType>
bool SinglyLinkList<ElemType>::Insert(ElemType elem, unsigned int pos)
{
    if (pos > GetLength() || pos < 0)
    {
        assert(false && "Error: SinglyLink's insert pos is out of range!\n");
        return false;
    }

    for(Node<ElemType>* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext())
    {
        if (pos-- == 0)
        {
            Node<ElemType>* insertNode = new Node<ElemType>(pCurrentNode->GetNext(),new ElemType(elem));
            pCurrentNode->SetNext(insertNode);
            ++m_length;
            return true;
        }
    }
    assert(false && "Error: SinglyLink Insert failed for unknow reason!");
    return false;
}

template<typename ElemType>
bool SinglyLinkList<ElemType>::Delete(unsigned int pos, ElemType* elem)
{
    if (pos >= GetLength() || pos < 0)
    {
        assert(false && "Error: SinglyLink's delete pos is out of range!\n");
    }

    for(Node<ElemType>* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext())
    {
        if (pos-- == 0)
        {
            Node<ElemType>* deleteNode = pCurrentNode->GetNext();
            pCurrentNode->SetNext(deleteNode->GetNext());
            *elem = deleteNode->GetData();
            delete deleteNode;
            --m_length;
            return true;
        }
    }
    assert(false && "Error: SinglyLink pos delete failed for unknow reason!");
    return false;
}

template<typename ElemType>
unsigned int const& SinglyLinkList<ElemType>::GetLength() const
{
    return m_length;
}

template<typename ElemType>
bool SinglyLinkList<ElemType>::Search(unsigned int pos, ElemType* elem) const
{
    if (pos >= GetLength() || pos < 0)
    {
        assert(false && "Error: SinglyLink's search pos is out of range!\n");
    }

    for(Node<ElemType>* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext())
    {
        if (pos-- == 0 && (pCurrentNode->GetNext() != NULL) )
        {
            *elem = pCurrentNode->GetNext()->GetData();
            return true;
        }
    }

    return false;
}

template<typename ElemType>
bool SinglyLinkList<ElemType>::Visit(ElemType* elem, const unsigned int& pos) const
{
    if (pos >= GetLength() || pos < 0)
    {
        return false;
    }
    return Search(pos,elem);
}

template<typename ElemType>
bool SinglyLinkList<ElemType>::Empty()
{
    return !m_length;
}

template<typename ElemType>
Node<ElemType>* SinglyLinkList<ElemType>::HavaHeadNode()
{
    return m_pHeadNode;
}
//QueueBySinglyLink.h
#pragma once

#include "SinglyLinkList.h"

template<typename ElemType>
class QueueBySinglyLink
{
public:
    QueueBySinglyLink();
    bool EnQueue(ElemType elem);
    bool DeQueue(ElemType* elem);
    bool Empty();
    unsigned int GetLength() const;
    bool Visit(ElemType* elem, const unsigned int& pos) const;
private:
    SinglyLinkList<ElemType>* m_pSinglyLink;
    Node<ElemType>* m_TopNode;
};

template<typename ElemType>
bool QueueBySinglyLink<ElemType>::Empty()
{
    return m_pSinglyLink->Empty();
}

template<typename ElemType>
unsigned int QueueBySinglyLink<ElemType>::GetLength() const
{
    return m_pSinglyLink->GetLength();
}

template<typename ElemType>
bool QueueBySinglyLink<ElemType>::DeQueue(ElemType* elem)
{
    return m_pSinglyLink->Delete(0,elem);
}

template<typename ElemType>
bool QueueBySinglyLink<ElemType>::EnQueue(ElemType elem)
{
    if (m_pSinglyLink->InsertByPosNode(elem,m_TopNode, &m_TopNode))
    {
        return true;
    }
    else
    {
        assert(false && "Error: QueueBySinglyLink Push failed for allocate node");
        return false;
    }
}

template<typename ElemType>
QueueBySinglyLink<ElemType>::QueueBySinglyLink()
    : m_pSinglyLink(new SinglyLinkList<ElemType>()), m_TopNode(m_pSinglyLink->HavaHeadNode())
{

}

template<typename ElemType>
bool QueueBySinglyLink<ElemType>::Visit(ElemType* elem, const unsigned int& pos) const
{
    return m_pSinglyLink->Visit(elem,pos);
}
//Util.h
#pragma once

namespace Util
{
    template<typename T>
    void PrintMemory(const T& dateStruct, unsigned int size)
    {
        cout << "PrintMemory: ";
        for (int i = 0; i != size; i++)
        {
            ElemType tempElem;
            dateStruct.Visit(&tempElem,i);
            printf("%d ",tempElem);
        }
        printf("\n");
        printf("\n");
    }
}
//main.cpp
#include "QueueBySinglyLink.h"
#include "Util.h"
#include <iostream>

using namespace std;

typedef int ElemType;

int main()
{
    QueueBySinglyLink<ElemType> testQueueBySinglyLink;

    Util::PrintMemory(testQueueBySinglyLink,testQueueBySinglyLink.GetLength());
    cout << (testQueueBySinglyLink.Empty() ? "Empty QueueBySinglyLink." : "Not Empty QueueBySinglyLink.") << endl;

    for (int i = 1; i != 5; i++)
    {
        testQueueBySinglyLink.EnQueue(i);
        cout << "\nPush:" << i << endl;
        Util::PrintMemory(testQueueBySinglyLink,testQueueBySinglyLink.GetLength());
        cout << (testQueueBySinglyLink.Empty() ? "Empty QueueBySinglyLink." : "Not Empty QueueBySinglyLink.") << endl;
    }


    for(int i = 1; i!= 5; i++)
    {
        int temp;
        testQueueBySinglyLink.DeQueue(&temp);
        cout << "\nPop:" << temp << endl;
        Util::PrintMemory(testQueueBySinglyLink,testQueueBySinglyLink.GetLength());
        cout << (testQueueBySinglyLink.Empty() ? "Empty QueueBySinglyLink." : "Not Empty QueueBySinglyLink.") << endl;
    }

    return 0;
}
4. 程序运行结果

PrintMemory:
Empty QueueBySinglyLink.

Push:1
PrintMemory: 1
Not Empty QueueBySinglyLink.

Push:2
PrintMemory: 1 2
Not Empty QueueBySinglyLink.

Push:3
PrintMemory: 1 2 3
Not Empty QueueBySinglyLink.

Push:4
PrintMemory: 1 2 3 4
Not Empty QueueBySinglyLink.

Pop:1
PrintMemory: 2 3 4
Not Empty QueueBySinglyLink.

Pop:2
PrintMemory: 3 4
Not Empty QueueBySinglyLink.

Pop:3
PrintMemory: 4
Not Empty QueueBySinglyLink.

Pop:4
PrintMemory:
Empty QueueBySinglyLink.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值