2016-03-15 18 views
-5

我需要输出一个链表中的节点数。我的老师说这个链表跟踪了它的数据并“知道”有多少个节点。所以,我不需要一个while循环来确定链表的大小。我很难弄清楚一个方法,而不是一个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

一种选择是以某种方式在每个节点上存储计数。那么你只需要访问尾部就可以找出有多少个节点。但是这会使诸如添加和删除等操作复杂化。 –

+0

请花些时间阅读[帮助页面](http://stackoverflow.com/help),尤其是名为[“我可以问些什么话题?”](http://stackoverflow.com/help /主题)和[“我应该避免问什么类型的问题?”](http://stackoverflow.com/help/dont-ask)。另请[请阅读如何提出好问题](http://stackoverflow.com/help/how-to-ask),并学习如何创建[最小,完整和可验证示例](http:// stackoverflow .COM /帮助/ MCVE)。 –

回答

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

+0

确实可以使用递归来查找链表的长度,从而避免了while循环,但递归实际上是一种循环,它比直线循环效率更低。 –

+0

@MichaelWalz,正如答案中所提到的,是的,程序语言通常效率较低。 OP说:“我很难找出一种方法来打印出尺寸。”所以我给出了唯一明智的答案。正如我所说的,链接列表的长度存储在一个节点类型中会破坏链表的目的,尽管在链接的包装类中可以很容易地完成。 – Matt

+1

好的。顺便说一句upvote是我的;-) –