【问题标题】:Traversing a non-STL linked-list in C++, possible?在 C++ 中遍历非 STL 链表,可能吗?
【发布时间】:2011-07-04 20:09:44
【问题描述】:

假设我正在使用非标准链表类List.h。该类功能正常,模板化,具有添加/删除到前面和添加/删除到后面、isEmpty() 等典型功能。

此列表没有任何 begin() 和 end() 功能。此外,链表类是否必须包含迭代器功能?还是我在创建新列表时可以自己创建的东西?

我习惯使用 STL,所以我通常会使用以下代码:

typedef vector<OBJECT>::iterator QuoteIt;
for(QuoteIt i = deposits.begin(); i != deposits.end(); ++i)

无论如何,假设我创建了一个新的“列表”。

List<int>deposits;

甚至是对象列表

List<OBJECT>deposits;

假设我addToBack() 20 个不同的整数,这样就创建了适当的新节点数。

现在,我怎样才能遍历这个列表,以便找到所有这些整数的总和?这是可能的,还是我目前的功能阻止了这种情况?我必须为我的列表类实现某种迭代器?

现在我知道我可以保留一个外部变量,每次我调用addToBack() 来跟踪我的总和。但是,我希望代码也与对象列表兼容。 (我希望能够在一个节点中搜索一个值,并最终在同一个节点中检索另一个值)

我已经习惯了使用 stl::list 并使用迭代器创建一个 for 循环,我真的不知道如何让它与其他类一起使用。

顺便说一句,这里是List()的代码:

template<class NODETYPE>
class List{

public:
List();
~List();
void insertAtFront(const NODETYPE &);
void insertAtBack(const NODETYPE  &);
bool removeFromFront( NODETYPE &);
bool removeFromBack( NODETYPE &);
bool isEmpty() const;

private:
ListNode< NODETYPE > *firstPtr; //pointer to first node
ListNode< NODETYPE > *lastPtr;
//Function to allocate a new node
ListNode< NODETYPE > *getNewNode ( const NODETYPE &);

};
//default constructor
template <class NODETYPE>
List< NODETYPE > ::List()
:  firstPtr(0),
   lastPtr(0)
{
cout<<"Creating Nodes! \n\n!"<<endl;
}
//deconstructor
template <class NODETYPE>
List<NODETYPE>::~List(){
    if(!isEmpty() ){
        cout<<"Destroying nodes!"<<endl;
        ListNode<NODETYPE> *currentPtr=firstPtr;
        ListNode<NODETYPE> *tempPtr;

        while( currentPtr !=0){
            tempPtr = currentPtr;
            currentPtr=currentPtr->nextPtr;
            delete tempPtr;
        }
    }
cout<<"All nodes destroyed! \n\n";
}

template <class NODETYPE>
bool List <NODETYPE>::removeFromFront( NODETYPE & value){
if ( isEmpty() )
    return false;
else{
    ListNode<NODETYPE> *tempPtr = firstPtr;

    if (firstPtr== lastPtr)
        firstPtr=lastPtr = 0;
    else
        firstPtr=firstPtr->nextPtr;

    value = tempPtr->data;
    delete tempPtr;

    return true;
}    
}     
template <class NODETYPE>
bool List<NODETYPE>::removeFromBack(NODETYPE &value)
{
    if (isEmpty())
        return false;
    else{
        ListNode< NODETYPE> *tempPtr = lastPtr;
        if( firstPtr == lastPtr)
            firstPtr = lastPtr = 0;
        else{
            ListNode<NODETYPE> *currentPtr=firstPtr;

            //Finds second to last element
            while(currentPtr->nextPtr !=lastPtr)
                currentPtr=currentPtr->nextPtr;

            lastPtr = currentPtr;
            currentPtr->nextPtr=0;
        }

        value = tempPtr->data;
        delete tempPtr;

        return true;
    }
}

//Checks to see if list is empty
template< class NODETYPE>
bool List< NODETYPE >::isEmpty() const{
return firstPtr == 0;
}
//returns a pointer to newly created Node
template<class NODETYPE>
ListNode<NODETYPE> *List<NODETYPE>::getNewNode(const NODETYPE &value){
return new ListNode<NODETYPE>(value);
}

【问题讨论】:

  • 我错过了什么吗?填写完这些列表之一后,您如何做任何事情(调用 isEmpty() 除外)。肯定有一些方法可以访问列表中的条目。
  • @Troubadour:removeFromFront 和 removeFromBack 将分别返回列表的顶部和底部。可以将此集合用作堆栈或队列(不允许窥视)。

标签: c++ linked-list


【解决方案1】:

回应:

现在,我如何遍历这个列表,以便找到所有这些整数的总和?这是可能的,还是我目前的功能阻止了这种情况?我必须为我的列表类实现某种迭代器?

您需要实现一种方法来迭代您的列表,该方法不会(作为副作用)破坏您的列表。

【讨论】:

    【解决方案2】:

    回应:

    现在,我怎样才能遍历这个列表,所以我 可以找到所有这些整数的总和吗?是 那可能,或者我现在的 功能可以防止这种情况吗?我会 必须实施某种 我的 List 类的迭代器?

    无论你如何设计一个链表,你必须有某种指向链表开头的指针,并且你必须有办法知道你什么时候在结尾(例如,当“next”为空时,或通过指向结尾的指针)。通过以一种或另一种方式公开这些数据,您始终可以设置列表遍历:

    1. 从头开始。 (在您的情况下,请联系firstPtr。)
    2. 如果您不在最后,请移至下一个元素。 (在您的情况下,请获取 -&gt;nextPtr。)

    使用该模式在您访问每个元素时累积一个值,您应该能够轻松处理您的任务。

    如果您的列表没有让您公开访问它的开头,那么它肯定不是通用列表!

    【讨论】:

    • private: ListNode&lt; NODETYPE &gt; *firstPtr;public: 的简单更改可能就是我所需要的...嗯。
    【解决方案3】:

    您可以通过多种方式进行处理。您可以选择创建自己的迭代器或授予对列表头部的公共访问权限。

    选项 1 与 stl 列表兼容,因此您可能想走那条路。迭代器本质上是一个 ptr,它覆盖 inc 和 dec 运算符以转到列表中的下一个或上一个位置。

    如果你研究过基本的数据结构,你就会知道遍历一个列表是微不足道的。

    Node<type> t = head;
    while (t != NULL)
    {
       // process node here
       t = t->next;
    }
    

    代码可能会有所不同,具体取决于您是否使用虚拟节点。

    【讨论】:

      【解决方案4】:

      由于没有功能可以在不将其从列表中删除的情况下仅获取 节点,因此您不能在不更改 List 类的情况下简单地创建“附加”迭代器。您至少需要做的是

      • 为外部ListIterator 类加好友
      • 朋友免费beginend功能
      • beginend 函数添加到List 类中

      没有这三个中的任何一个,您都无法实现您想要的。

      【讨论】:

        【解决方案5】:

        您的列表似乎有 2 种迭代方式(向前和向后)

        List<int>deposits;
        .. add stuff:
        
        int o;
        int sum = 0;
        while(deposits.removeFromFront(o)) {
          sum+=o;
        }
        

        但不好的是,迭代它,你也会破坏列表, 您可以为 List::firstPtrListNode::nextPtr 提供公共访问器,在这种情况下您可以这样做:

        List<int>deposits;
        .. add stuff:
        
        
        int sum = 0;
        
        for(ListNode<int> *ptr = deposits.firstPtr; ptr ; ptr = ptr->nextPtr) 
          sum+=ptr->data;
        

        但是,如果可以,请使用现有的 STL 容器。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-06
          • 1970-01-01
          • 2013-07-28
          相关资源
          最近更新 更多