微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

迭代器while循环运行额外循环

如何解决迭代器while循环运行额外循环

我有一个双链列表类,其中有一个函数使用我的类迭代器遍历集合。但是在1个特定的地方,它运行了一个额外的循环,我无法弄清楚为什么。

当前合并模板

template <typename T>
void DlList<T>::merge(SortedList& other) {  
    iterator it = back_->prev_;
    iterator oit = other.begin();   
    while (oit.current_->next_ != NULL) {
        std::cout << *it << "    " << *oit << std::endl;
        it.current_->next_ = oit.current_;
        back_->prev_ = oit.current_;
        //back_->prev_->next_ = back_;
        //other.back_->prev_ = other.back_->prev_->prev_;
        it++;
        oit++;
    }
}

它总是会反复执行,并且会花费额外的时间,并且在列表中添加一个空节点,我不明白为什么。

任何见识都非常有用!

编辑添加了完整的项目示例以解释功能的意图 我正在研究模板化的数据结构类,该类是使用哨兵节点的双向链表。 该列表是基于insert()排序的,并且我正在使用合并功能,其中每个列表的节点必须组合到this-> list中。节点必须移动并且不能创建新节点。并且如果两个列表中都存在相同的值,则另一个节点值必须在当前节点值之后。

我编码了我认为是逻辑的实现,但是我得到的输出不符合预期,结果对我来说也没有意义,因此如果有人可以解释我如何获得结果,将不胜感激。

类定义

class SortedList {
    struct Node {
        T data_;
        Node* next_;
        Node* prev_;
        Node(const T& data = T{},Node* nx = nullptr,Node* pr = nullptr) {
            data_ = data;
            next_ = nx;
            prev_ = pr;
        }
    };
    Node* front_;
    Node* back_;

public:
    class const_iterator {
        friend class SortedList;
        Node* current_;
        const_iterator(Node* n)
        {
            current_ = n;
        }
    public:
        const_iterator() {
            //Set to safe state         
            current_ = nullptr;
        }
        const_iterator& operator++() {
            current_ = current_->next_;
            return *this;
        }
        const_iterator operator++(int) {
            const_iterator old = *this;
            current_ = current_->next_;
            return old;
        }
        const_iterator& operator--() {
            current_ = current_->prev_;
            return *this;
        }
        const_iterator operator--(int) {
            const_iterator old = *this;
            current_ = current_->prev_;
            return old;
        }
        bool operator==(const_iterator rhs) {
            return (current_ == rhs.current_) ? true : false;
        }
        bool operator!=(const_iterator rhs) {
            return !(*this == rhs);
        }
        bool operator>(const_iterator rhs) {
            return current_->data_ > rhs->current_->data_;
        }
        const T& operator*()const {
            return current_->data_;
        }
    };
    class iterator :public const_iterator {
        friend SortedList;
        iterator(Node* n) :const_iterator(n) {};
    public:
        iterator() : const_iterator() {};
        //prefix
        iterator& operator++() {
            this->current_ = this->current_->next_;
            return *this;
        }
        //post-fix
        iterator operator++(int) {
            iterator old = *this;
            this->current_ = this->current_->next_;
            return old;
        }
        iterator& operator--() {
            this->current_ = this->current_->prev_;
            return *this;
        }
        iterator operator--(int) {
            iterator old = *this;
            this->current_ = this->current_->prev_;
            return old;
        }
        T& operator*() {
            return this->current_->data_;
        }
        const T& operator*()const {
            return this->current_->data;
        }
    };
    SortedList();                                   //done
    ~SortedList();
    SortedList(const SortedList& rhs);
    SortedList& operator=(const SortedList& rhs);
    SortedList(SortedList&& rhs);
    SortedList& operator=(SortedList&& rhs);
    iterator begin() {
        return iterator(front_->next_);
    }
    iterator end() {
        return iterator(back_);
    }
    const_iterator cbegin() const {
        return const_iterator(front_->next_);
    }
    const_iterator cend() const {
        return const_iterator(back_);
    }
    iterator insert(const T& data);
    iterator search(const T& data);
    const_iterator search(const T& data) const;
    iterator erase(iterator it);
    void merge(SortedList& other);
    bool empty() const;
    int size() const;
};

首次合并功能尝试


template <typename T>
void SortedList<T>::merge(SortedList& other) {
    
    iterator it = this->begin();
    iterator oit = other.begin();
    while (oit !=  other.end()) {               
        std::cout << *oit << " " << *it << std::endl;
        if (*oit < *it) {
            oit.current_->prev_->next_ = oit.current_->next_;
            oit.current_->next_->prev_ = oit.current_->prev_;
            oit.current_->next_ = it.current_;
            oit.current_->prev_ = it.current_->prev_;
            it.current_->next_ = oit.current_;
        }
        else {
            oit.current_->prev_->next_ = oit.current_->next_;
            oit.current_->next_->prev_ = oit.current_->prev_;
            oit.current_->next_ = it.current_->next_;
            oit.current_->prev_ = it.current_;
            it.current_->prev_ = oit.current_;
        }
        oit++;
        it++;
    }
}

主测试器

int main() {
    int num[] = { 3,5,1,2,6,8,9,11 };
    int num2[] = { 1,4,12,7,9 };

    SortedList<int> l;
    SortedList<int> l2;
    for (int i = 0; i < 8; i++)
    {
        l.insert(num[i]);
        l2.insert(num2[i]);
    }
     SortedList<int>::iterator result;
     SortedList<int>::iterator result2 = l2.begin();
     result = l.begin();
     while (result != l.end()) {
         std::cout << *result << "    " << *result2 << std::endl;
         ++result;
         ++result2;
     }
     l.merge(l2);

输出

1    1
2    4
3    5
5    6
6    7
8    8
9    9
11    12

1 1
2 2
3 3
5 5
6 6
8 8
9 9
11 11
0 0

我不明白为什么我的第二个输出为* it和* oit显示相同的值,我很确定错误是我如何分配oit.current _-> next&prev,但是我不确定。

任何见解都适用。

解决方法

您似乎想将两个排序的双向链接列表合并在一起。您的方法存在一些问题,因此,我将向您展示我的代码:

#include <iostream>
using namespace std;

struct node {
    node* next;
    node* prev;
    int val;
    
    node(int i_val)
      : next(nullptr),prev(nullptr),val(i_val)
    {}
};

void connect(node* a,node* b) {
    if (a != nullptr) {
        if (a->next != nullptr) {
            a->next->prev = nullptr;
        }
        a->next = b;
    }
    if (b != nullptr) {
        if (b->prev != nullptr) {
            b->prev->next = nullptr;
        }
        b->prev = a;
    }
}

struct DlList {
    node* first_node;
    node* last_node;
    
    DlList()
      : first_node(nullptr),last_node(nullptr)
    {}
    
    ~DlList() {
        for (node* n = first_node; n != nullptr; n = n->next) {
            delete n->prev;
        }
        delete last_node;
    }
    
    void push(int new_val) {
        node* new_node = new node(new_val);
        connect(last_node,new_node);
        last_node = new_node;
        if (first_node == nullptr) {
            first_node = new_node;
        }
    }
    
    void merge_sorted(DlList& other) {
        node* this_node = first_node;
        node* other_node = other.first_node;
        node* n = nullptr; // goes through each node of the new list in order
        while (this_node != nullptr || other_node != nullptr) {
            node* next_n;
            if (other_node == nullptr || 
                    (this_node != nullptr && this_node->val <= other_node->val)) {
                // entered if other_node is nullptr or this_node comes before other_node
                next_n = this_node;
                this_node = this_node->next;
            }
            else {
                // entered if this_node is nullptr or other_node comes before this_node
                next_n = other_node;
                other_node = other_node->next;
            }
            connect(n,next_n);
            if (n == nullptr) { // first time through loop
                first_node = next_n;
            }
            n = next_n;
        }
        last_node = n;
        
        // *this takes ownership of all of other's nodes
        other.first_node = nullptr;
        other.last_node = nullptr;
    }
};

int main() {
    std::cout << "running test" << std::endl;
    
    int num[] = { 1,2,3,5,6,8,9,11 };
    int num2[] = { 1,4,7,12 };

    DlList l;
    DlList l2;
    for (int i = 0; i < 8; i++)
    {
        l.push(num[i]);
        l2.push(num2[i]);
    }
    l.merge_sorted(l2);
    
    for (node* n = l.first_node; n != nullptr; n = n->next) {
        std::cout << n->val << " ";
    }
    std::cout << std::endl;
}

您可以在以后添加迭代器和其他更高级别的抽象,但是现在我认为它们使逻辑变得复杂且晦涩难懂。在您的情况下,我也没有看到需要“列表的最后一个”节点,因为nullptr就足够了。当然,如果您愿意的话,可以很容易地添加这些内容,只是出于演示目的,它们被省略了。

请注意,我是如何制作一个专用的connect函数来完成所有指针分配的,因为它们应该在两个节点上完成。它也处理一堆nullptr大小写的组合,因此您不必担心在函数外部检查null指针。 (请注意,第一次通过合并循环如何将null指针连接到next_n)。现在,您几乎不必担心指针分配了,只需说“连接这两个节点”就更清楚了。

我的合并功能遍历新创建的列表中的每个节点。它从* this和other的两个可用节点中选择下一个节点。然后,它将当前节点连接到下一个节点,并将当前节点前进到下一个节点。当列表中的一个或另一个用完(this_node或other_node变为nullptr)时,它会进行特殊处理,这确实发生在给定的测试用例中。请注意将first_node和last_node分配在正确的位置,并在合并后清除其他位置,以防止出现双重所有权问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。