如何在不使用while循环的情况下确定链接列表的大小?

时间:2016-03-15 07:39:36

标签: c++ while-loop linked-list size

我需要打印出链表中的节点数。我的老师说链接列表跟踪其数据并“知道”其中有多少节点。所以,我不需要一个while循环来确定链表的大小。我无法找出除了while循环之外的方法来打印出大小。

这是链表:

template <class T>
class LinkedList
{
private:
struct ListNode
{
  T data ;
  struct ListNode * next;
};

ListNode *head;

public:
LinkedList() { head = nullptr; }
 ~LinkedList();

// Linked list operations
void insertNode(T);
bool deleteNode(T);
void displayList() const;
};


/////////// Implementation portion of linked list with template  //////////////

// displayList: print all list data
template <class T>
void LinkedList<T>::displayList() const
{
ListNode * ptr = head;

while (ptr != nullptr)
{
    cout << ptr->data << endl;
    ptr = ptr->next;
}
}

// insertNode: add a node in list order
template <class T>
void LinkedList<T>::insertNode(T newValue)
{
ListNode *newNode;
ListNode *pCur;
ListNode *pPre = NULL;

newNode = new ListNode;
newNode->data = newValue;
newNode->next = nullptr;

if (head == nullptr)
{
  head = newNode;
}
else
{
    pCur = head;
    pPre = nullptr;
    while (pCur != nullptr && pCur->data < newValue)
    {
        pPre = pCur;
        pCur = pCur->next;
    }

    if (pPre == nullptr)
    {
        head = newNode;
        newNode->next = pCur;
    }
    else
    {
        pPre->next = newNode;
        newNode->next = pCur;
    }
}
}

// deleteNode: delete a node if found
template <class T>
bool LinkedList<T>::deleteNode(T toBeDeleted)
{
ListNode *pCur;
ListNode *pPre;

if (!head)
    return true;

pCur = head;
pPre = NULL;
while (pCur != NULL && pCur->data < toBeDeleted)
{
     pPre = pCur;
     pCur = pCur->next;
}

if (pCur != NULL && pCur->data == toBeDeleted)
{
    if (pPre)
        pPre->next = pCur->next;
    else
        head = pCur->next;
    delete pCur;
    return true;
}
return false;
}


// destructor, delete all nodes
template <class T>
LinkedList<T>::~LinkedList()
{
ListNode *ptr = head;
while (ptr != NULL)
{
    head = head->next;
    delete ptr;
    ptr = head;
}
}

1 个答案:

答案 0 :(得分:1)

使用您已定义的代码,列表的大小不会直接存储在列表中。除此之外,链表的主要优点是每个节点都不知道列表的其余部分,并且存储大小会破坏其目的。

但是,您可能误解了不使用while循环的问题。每个节点都知道它的长度是1+(它的尾部长度),因此获得链表长度的更合适的实现是递归,而不是迭代。

这是一个非常简单的LinkedList类的示例,它使用递归实现简单方法。如您所见,代码不使用迭代,只检查它自己的数据,然后为下一个节点调用相同的方法。虽然在大多数情况下,程序语言中的递归效率较低,但对于这样的结构来说,毫无疑问它是优雅的。

#include <iostream>

template<class T>
class LinkedList
{
private:
    T data;
    LinkedList* next;
public:
    LinkedList()
        : LinkedList(T()) {
    }
    LinkedList(T value)
        : data(value), next(nullptr) {
    }
    ~LinkedList() {
        delete next;
    }

    void insertNode(T newValue) {
        if (!next) {
            next = new LinkedList(newValue);
            return;
        }

        next->insertNode(newValue);
    }

    void displayList() const {
        std::cout << data << std::endl;
        if (next) {
            next->displayList();
        }
    }

    T& at(int N) {
        if (N == 0) {
            return this->data;
        }
        return next->at(N-1);
    }

    int size() {
        if (!next) {
            return 1;
        }

        return 1+next->size();
    }
};


int main(int argc, char const *argv[])
{
    LinkedList<int>* test = new LinkedList<int>(0);

    for (int i = 1; i < 10; ++i) {
        test->insertNode(i);
    }

    std::cout << "List of length: " << test->size() << std::endl;
    test->displayList();

    return 0;
}

您已经注意到我还没有包含deleteNode,因为在列表中只有一个节点的情况下,为上面的过度简化类编写它是不可能的。实现这一点的一种可能方法是使用一个包装类,就像在原始代码中一样,它是指向链表开头的指针。请参阅here