【问题标题】:Runtime error in sorting a singly linked list对单链表进行排序时出现运行时错误
【发布时间】:2020-05-31 17:04:41
【问题描述】:

我已经编写了一个链表(针对数据类型 int)实现。 当我尝试对列表进行排序时,似乎工作正常 except 元素应该排在所有偶数元素之后,并保留偶数和奇数的原始顺序。

在 MS Visual Studio 中调试时,我发现在 oddevenSort() 函数中,for 循环似乎在无限进行……好像不知何故 tail->next 没有更新为 nullptr。 我似乎无法理解我的逻辑错误在哪里。

#include<iostream>

template<class T>
class SLL_Node
{
public:
    T info;
    SLL_Node* next;
    SLL_Node();
    SLL_Node(T el, SLL_Node<T>* n = nullptr);

};

template<class T>
class SLL
{
private:
    SLL_Node<T>* head, * tail;
    size_t size;
public:
    SLL();
    ~SLL();
    bool isEmpty() const;
    size_t get_size() const;
    void add_to_head(T el);
    void add_to_tail(T el);
    void delete_at(size_t); //delete at a certain index. Index starting from 1. Throws an error //message if index out of bounds or list empty. 

    void display()const; //the logic is for mostly primitive data types and not user defined data //types (including classes)
    void oddevenSort();
};

template<class T>
bool SLL<T>::isEmpty() const
{
    if (tail == nullptr)
        return true;
    else
        return false;
}

template<class T>
SLL_Node<T>::SLL_Node() : next{ nullptr }
{}

template<class T>
SLL_Node<T>::SLL_Node(T el, SLL_Node<T>* n) : info{ el }, next{ n }
{}

template<class T>
SLL<T>::SLL()
{
    size = 0;
    head = tail = nullptr;
}

template<class T>
void SLL<T>::add_to_tail(T el)
{
    ++size;
    if (!isEmpty())
    {
        tail->next = new SLL_Node<T>(el);
        tail = tail->next;
    }
    else
        head = tail = new SLL_Node<T>(el);
}

template<class T>
void SLL<T>::add_to_head(T el)
{
    head = new SLL_Node<T>(el, head);
    if (tail == nullptr) //if empty
    {
        tail = head;
    }
    ++size;
}

template<class T>
void SLL<T>::display()const
{
    std::cout << '\n';
    for (SLL_Node<T>* tmp{ head }; tmp != nullptr; tmp = tmp->next)
    {
        std::cout << tmp->info << "->";
    }
    std::cout << "NULL\n";
}

template<class T>
void SLL<T>::delete_at(size_t index)
{


    if (index >= 1 && index <= size) //bound checking 
    {
        if (!isEmpty()) //we dont need is empty since size takes care of that but still adding it for clarity
        {

            if (head == tail && index == 1) //if list only has one node and we delete head node
            {
                delete head;
                head = tail = nullptr;
            }

            //otherwise if list more than one node

            else if (index == 1) //if deleting head node
            {
                SLL_Node<T>* tmp{ head };
                head = head->next;
                delete tmp;
                tmp = nullptr;
            }

            else //deleting other nodes
            {
                SLL_Node<T>* tmp{ head->next }, * pred{ head };
                for (size_t i{ 2 }; i < index; ++i)
                {
                    tmp = tmp->next;
                    pred = pred->next;
                }
                pred->next = tmp->next;
                if (tmp == tail)
                {
                    tail = pred;
                }
                delete tmp;
                tmp = nullptr;
            }

        }
    }

    else
    {
        std::cout<<"\nError! Either the list is empty or the index entered is out of bounds!\n";
    }
}

template<class T>
void SLL<T>::oddevenSort()
{
    SLL_Node<T>* t=head;
    size_t count{1};
    for (; t != nullptr; t = t->next)
    {
        if (((t->info) % 2) != 0)
        {
        add_to_tail(t->info);
        delete_at(count);

        }
        ++count;
    }
}

主要

int main()
{
    SLL<int> a;
    a.add_to_head(1);
    a.add_to_head(2);
    a.add_to_tail(3);
    a.add_to_tail(4);
    a.add_to_head(6);
    a.add_to_tail(7);
    a.add_to_head(5);
    a.display();
    //a.oddevenSort();
    a.display();
    return 0;
}

【问题讨论】:

  • delete_at(count); 这不会导致t 指向的问题吗?
  • @drescherjm 我现在添加了delete_at() 定义。请看一下
  • 问题不在于 delete_at() 它是 t 指向的。您删除 t 指向的节点,然后尝试在已删除的节点上执行 t = t-&gt;next
  • 那么在调用delete_at(count) 之前我应该​​先t=t-&gt;next 吗?
  • 你可能不应该在这个函数中使用 delete_at()。并从 for (;;) 中删除 t = t-&gt;next,而是将 t = t-&gt;next 放在循环体中,并且仅在不删除时使用它。

标签: c++ sorting infinite-loop singly-linked-list


【解决方案1】:

考虑oddevenSort a(1)-&gt;b(2) -&gt;c(3)-&gt;null 的示例输入

  1. 在第一次迭代时t 指向a(1) 创建新节点 数据1 附加在列表末尾,例如 b(2)-&gt;c(3)-&gt;d(1)-&gt;null
  2. 在第二次迭代中t 将指向节点b(2) 并且没有进行任何更改 在名单上。
  3. 第三次迭代t 将指向节点c(3) 创建新节点 带有数据3,它附加在列表的末尾,例如 b(2)-&gt;d(1)-&gt;e(3)-&gt;null
  4. 在第四次迭代t 将指向d(1),它在列表末尾创建新节点。迭代不断递归地进行,而不会中断循环。

每次你不需要删除和创建新节点。您可以分离偶数和奇数节点并制作最终列表。

这是更新的sn-p

template<class T>
void SLL<T>::oddevenSort()
{
    SLL_Node <T>tempOddHeader;
    SLL_Node <T> *tempOddPtr = &tempOddHeader;
    SLL_Node <T> tempEvenHeader;
    SLL_Node <T> *tempEvenPtr = &tempEvenHeader;

    SLL_Node<T>* t = head;
    tempOddHeader.next = nullptr;
    tempEvenHeader.next = nullptr;

    while(t)
    {
        if (((t->info) % 2) != 0) {
            //append to the odd list
            tempOddPtr->next = t;
            tempOddPtr = tempOddPtr->next;
            t = t->next;
            tempOddPtr->next = nullptr;
        }
        else {
            //append to the even list
            tempEvenPtr->next = t;
            tempEvenPtr = tempEvenPtr->next;
            t = t->next;
            tempEvenPtr->next = nullptr;
        }
    }

    tempEvenPtr->next = tempOddHeader.next;
    head = tempEvenHeader.next;
    tail = tempOddPtr;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-24
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多