Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对单链表排序时出现运行时错误_C++_Sorting_Infinite Loop_Singly Linked List - Fatal编程技术网

C++ 对单链表排序时出现运行时错误

C++ 对单链表排序时出现运行时错误,c++,sorting,infinite-loop,singly-linked-list,C++,Sorting,Infinite Loop,Singly Linked List,我已经编写了一个链表(针对数据类型int)实现。 似乎工作正常,但当我尝试对列表进行排序时,所有的奇数 元素应位于所有偶数元素之后,并保留偶数和奇数的原始顺序 在MS Visual Studio中调试时,我发现在oddevenSort()函数中,for循环似乎在无限地进行……好像tail->next没有被更新为nullptr。 我似乎无法理解我的逻辑错误在哪里 #include<iostream> template<class T> class SLL_Node { p

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

在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;
    }
}
#包括
模板
类SLL_节点
{
公众:
T信息;
SLL_节点*下一步;
SLL_节点();
SLL_节点(tel,SLL_节点*n=nullptr);
};
模板
类SLL
{
私人:
SLL_节点*头部,*尾部;
大小;
公众:
SLL();
~SLL();
bool isEmpty()常量;
size\u t获取\u size()常量;
无效添加到头(T el);
无效添加到尾部(T el);
void delete_at(size_t);//在某个索引处删除。索引从1开始。如果索引超出范围或列表为空,则抛出错误//消息。
void display()const;//逻辑主要用于基本数据类型,而不是用户定义的数据//类型(包括类)
void oddevenSort();
};
模板
bool SLL::isEmpty()常量
{
if(tail==nullptr)
返回true;
其他的
返回false;
}
模板
SLL_节点::SLL_节点():下一个{nullptr}
{}
模板
SLL_节点::SLL_节点(tel,SLL_节点*n):信息{el},下一个{n}
{}
模板
SLL::SLL()
{
尺寸=0;
头=尾=空PTR;
}
模板
void SLL::将_添加到_尾(T el)
{
++大小;
如果(!isEmpty())
{
tail->next=新SLL_节点(el);
tail=tail->next;
}
其他的
头部=尾部=新的SLL_节点(el);
}
模板
void SLL::将_添加到_头(T el)
{
head=新的SLL_节点(el,head);
if(tail==nullptr)//如果为空
{
尾=头;
}
++大小;
}
模板
void SLL::display()常量
{
std::cout(下一步)
{
std::cout info next},*pred{head};
for(size_t i{2};inext;
pred=pred->next;
}
pred->next=tmp->next;
如果(tmp==尾部)
{
tail=pred;
}
删除tmp;
tmp=nullptr;
}
}
}
其他的
{
标准::coutinfo)%2)!=0)
{
添加到尾部(t->info);
在(计数)处删除_;
}
++计数;
}
}
main

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;
}

intmain()
{
slla;
a、 将_添加到_头(1);
a、 将_添加到_头(2);
a、 将_添加到_尾(3);
a、 将_添加到_尾(4);
a、 将_添加到_头(6);
a、 将_添加到_尾(7);
a、 将_添加到_头(5);
a、 显示();
//a、 oddevenSort();
a、 显示();
返回0;
}

考虑一个示例输入
oddevenSort
a(1)->b(2)->c(3)->null

  • 在第一次迭代中,
    t
    指向
    a(1)
    使用 数据
    1
    附加在列表末尾,如
    b(2)->c(3)->d(1)->null
  • 在第二次迭代中,
    t
    将指向节点
    b(2)
    ,并且没有做任何更改 在名单上
  • 在第三次迭代中,
    t
    将指向节点
    c(3)
    创建新节点 数据
    3
    ,附加在列表末尾,如
    b(2)->d(1)->e(3)->null
  • 在第4次迭代中,
    t
    将指向
    d(1)
    ,它将在列表末尾创建新节点。迭代在不中断循环的情况下递归地进行
  • 每次都不需要删除和创建新节点。您可以分离偶数和奇数节点并生成最终列表

    下面是更新后的代码片段

    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;
    }
    
    模板
    void SLL::oddevenSort()
    {
    SLL_节点tempOddHeader;
    SLL_节点*tempOddPtr=&tempOddHeader;
    SLL_节点tempEvenHeader;
    SLL_节点*tempEvenPtr=&tempEvenHeader;
    SLL_节点*t=头部;
    tempOddHeader.next=nullptr;
    tempEvenHeader.next=nullptr;
    while(t)
    {
    如果((t->info)%2)!=0){
    //追加到奇数列表
    tempOddPtr->next=t;
    tempOddPtr=tempOddPtr->next;
    t=t->next;
    tempOddPtr->next=nullptr;
    }
    否则{
    //追加到偶数列表
    tempEvenPtr->next=t;
    tempEvenPtr=tempEvenPtr->next;
    t=t->next;
    tempEvenPtr->next=nullptr;
    }
    }
    tempEvenPtr->next=tempOddHeader.next;
    head=tempEvenHeader.next;
    tail=tempOddPtr;
    }
    
    删除(计数)
    这是否会导致
    t
    指向的内容出现问题?@drescherjm我现在已经添加了
    delete\u at()
    定义。请看一看问题不在于删除,而在于
    t
    所指的内容。您删除了t指向的节点,然后尝试在删除的节点上执行
    t=t->next
    。在调用
    delete_at(count)
    之前,我应该执行
    t=t->next
    ?您可能不应该在该函数中使用delete_at()。并从for(;;)中删除
    t=t->next
    ,而将
    t=t->next
    放在循环体中,仅在不删除时使用。