【问题标题】:Quicksort Algorithm in a doubly linked list双向链表中的快速排序算法
【发布时间】:2018-05-22 05:07:00
【问题描述】:

我想使用 Quicksort 的算法按姓氏对列表进行排序,但是在交换元素时它不起作用,它会让它们保持原样

在这部分中,链的值被交换

void swap(string* a, string* b){


cout<<"A and B are "<<*a<<" - "<<*b<<endl;

string t = *a;
*a = *b;
cout<<" A is ->"<<*a<<endl;

*b= t;
cout<<"B is ->"<<*b<<endl;

}

这是进行分区的地方。我注意到,当 * i 和 * j 取值时,它们的名称完全相同,因此以后无法进行比较。我觉得奇怪的是,如果它是一个数字,这个列表就可以工作,但是当它是字符串时,就会发生这个错误。

User *i = lower;

但是最后这并没有奏效,因为程序崩溃了,但是如果你改变了字符串的值

User* partition(User *lower, User *high){

cout<<"Lower ->  "<<lower->lastname<<endl;
cout<<"High ->  "<<high->lastname<<endl;
string  pivot = high->lastname;
User *i = bajo->prev;
 for (User *j = lower; j != high; j = j->next)
{
    if (j->lastname.compare(pivot)< 0)
    {
        i = (i == NULL)? lower : i->next;
        cout<<"Atention J e I valen ->"<<i->lastname<<" - "<<j->lastname<<endl;
        swap(&(i->lastname), &(j->lastname));
    }
}
i = (i == NULL)? lower : i->lastname; // Similar to i++
swap(&(i->lastname), &(alto->lastname));
return i;
}

我失败了什么?我怎样才能让它真正达到预期的价值。

编辑:

这是源代码

#include <iostream>
#include<iomanip>
#include <string>
#include<cstdlib>

using namespace std;

class User
{

public :
    string lastname;
    User *next;
    User *prev;
    User()
    {
        lastname= "";
        next=NULL;
        prev=NULL;

    }
    int empty(User *listt)
    {

        if(listt ==  NULL)
        {

            return 1;
        }
        else
        {

            return 0;
        }

    }


    User *Insert(User *listt, string lastName)
    {

        User *temp = new User();

        if(empty(listt))
        {

            temp->lastname=lastName;
            listt = temp;

        }
        else
        {

            temp->lastname=lastName;
            listt->prev=temp;
            temp->next=listt;
            listt=temp;

        }
        return listt;
    }
    void swap(string* a, string* b)
    {

        string t = *a;
        *a = *b;

        *b= t;

    }
    User* partition(User* lower, User* high)
    {

        cout<<"Lower ->  "<<lower->lastname<<endl;
        cout<<"High ->  "<<high->lastname<<endl;
        string  pivot = high->lastname;
        User *i = lower->prev;
        for (User *j = lower; j != high; j = j->next)
        {
            if (j->lastname.compare(pivot)< 0)
            {
                i = (i == NULL)? lower : i->next;
                swap(&(i->lastname), &(j->lastname));
            }
        }
        i = (i == NULL)? lower : i->next; // Similar to i++
        swap(&(i->lastname), &(high->lastname));
        return i;
    }
    User *Last(User *listt)
    {
        User *temp = listt;

        while(temp && temp ->next)
            temp=temp->next;
        return temp;


    }
    void _quickSort( User* lower, User* high)
    {

        if(high != NULL && lower != high&&lower!= high->next)
        {
            User *p = partition(lower,high);
            _quickSort(lower,p->next); //I change this part
            _quickSort(p->next,high);

        }

    }
    void quickSort(User *listt)
    {
        User *h = Last(listt);

        _quickSort(listt, h);


    }
    User *Display(User *listt)
    {

        if(empty(listt))
        {

            cout<<"List empty"<<endl;

        }
        else
        {

            User *temp = new User();
            temp = listt;
            while(temp!= NULL)
            {

                cout<<"The last name is -> "<<temp->lastname<<endl;
                temp=temp->next;
            }

        }
        return listt;


    }
};

int main()
{

    User *listt = NULL;
    User y;
    bool exit = false;
    int opc;
    string lastName;
    while(!exit)
    {

        cout<<"1.-Insert an element"<<endl;
        cout<<"2.-Sort element-(Quicksort)"<<endl;
        cout<<"3.-Show elements"<<endl;
        cout<<"4.-Exitt"<<endl;
        cin>>opc;
        switch(opc)
        {
        case 1:
            cout<<"Inser your last name"<<endl;
            cin>>lastName;
            listt=y.Insert(listt,lastName);
            system("pause");
            system("cls");
            break;
        case 2:
            cout<<"Sorting...."<<endl;
            y.quickSort(listt);
            system("pause");
            system("cls");
            break;
        case 3:
            cout<<"Display..."<<endl;
            y.Display(listt);
            system("pause");
            system("cls");
            break;
        case 4:
            exit = true;
            break;



        }




    }




}

【问题讨论】:

  • 欢迎来到 StackOverflow。请阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。
  • 好的,谢谢我改变我的帖子
  • 这些原始指针很容易出错,并且会重复在标准库中已经做得很好的东西。您在意想不到的地方发生崩溃的事实表明错误在其他地方,并且稍后会赶上您 - 这是我们都熟悉的。在这里发布一些非运行代码片段不太可能揭示真正的罪魁祸首。
  • 如果你改变这个值程序崩溃用户 *i = lower;
  • 粗略检查一下,您的 _quickSort 函数似乎选择了一个枢轴,然后执行了两次上半部分,而不是执行下半部分和上半部分。

标签: c++ algorithm codeblocks quicksort doubly-linked-list


【解决方案1】:

实际上,您的交换函数似乎有效,但 string t = *a; 的用法有点奇怪,因为 *a 被认为是一个 int 值,因此您不应该将它分配给字符串,尽管编译器可以以任何一种方式处理它。另一方面,我猜你提到的是将“a”的值复制到一个临时字符串中,它应该作为 string* t = a; 完成,然后你可以做 b = t; 但不是通过引用传递是更好的做法比如

void swap(string &a, string &b){
    string t = a;
    a = b;
    b= t;
}

您可能想要检查您的快速排序实现,请参阅this page 上的参考

【讨论】:

  • 听起来不错,但在我的实现中不起作用
  • 你应该发送类似 swap((i->lastname), (high->lastname));
【解决方案2】:
_quickSort(lower,p->next); //I change this part

这应该是p-&gt;prev。正确的函数:

void _quickSort(User* lower, User* high)
{
    if(high != NULL && lower != high&&lower != high->next)
    {
        User *p = partition(lower, high);
        _quickSort(lower, p->prev); //change it back!
        _quickSort(p->next, high);
    }
}

另外,Display 中存在资源泄漏。不要在显示功能中分配新项目:

User *Display(User *listt)
{
    if(empty(listt))
    {
        cout<<"List empty"<<endl;
    }
    else
    {
        //User *temp = new User(); <== don't allocate new item here
        User *temp = listt;
        while(temp!= NULL)
        {
            cout<<"The last name is -> "<<temp->lastname<<endl;
            temp=temp->next;
        }

    }
    return listt;
}

使用 1000 个项目进行测试:

class User
{
public:
    class Node
    {
    public:
        string lastname;
        Node *next;
        Node *prev;
        Node()
        {
            prev = next = nullptr;
        }
    };

    Node *head;
    User()
    {
        head = nullptr;
    }

    void Insert(string val)
    {
        Node *temp = new Node;
        temp->lastname = val;
        if (head)
        {
            head->prev = temp;
            temp->next = head;
        }
        head = temp;
    }

    void swap(string &a, string &b)
    {
        string t = a;
        a = b;
        b = t;
    }

    Node *Tail()
    {
        Node *temp = head;
        while(temp && temp->next)
            temp = temp->next;
        return temp;
    }

    Node* partition(Node* left, Node* right)
    {
        string pivot = right->lastname;
        Node *i = left->prev;
        for(Node *j = left; j != right; j = j->next)
        {
            if(j->lastname < pivot)
            {
                i = (i == nullptr) ? left : i->next;
                swap(i->lastname, j->lastname);
            }
        }
        i = (i == nullptr) ? left : i->next; // Similar to i++
        swap(i->lastname, right->lastname);
        return i;
    }

    void quickSort(Node* left, Node* right)
    {
        if(!left || !right || left == right || left == right->next) 
            return;
        Node *p = partition(left, right);
        quickSort(left, p->prev);
        quickSort(p->next, right);
    }

    void quickSort()
    {
        quickSort(head, Tail());
    }

    void Display()
    {
        string last;
        for (Node *n = head; n; n = n->next)
        {
            if(n->lastname < last)
            {
                cout << "error ***\n";
                break;
            }
            last = n->lastname;
            cout << n->lastname << endl;
        }
    }
};

int main()
{
    User list;

    list.Insert("z");
    list.Insert("c");
    list.Insert("a");
    list.Insert("g");

    for(int i = 0; i < 1000; i++)
    {
        string str;
        for (int j = 0; j < 3; j++)
            str.push_back('a' + rand() % 26);
        list.Insert(str);
    }

    list.quickSort();
    list.Display();

    return 0;
}

【讨论】:

  • 它适用于数字。出于某种原因,但不是字符。我尝试使用 z c a g 并以这种方式排序 c a g z 。不知道这个方法对不对if (j-&gt;lastname.compare(pivot)&lt; 0)
  • 查看编辑,我用与以前相同的排序例程以更简单的形式重写了该类,它使用您的值正确排序。您的老师是强迫您使用快速排序对链表进行排序还是这是您自己的想法?
  • 哇,你解决了。谢谢,我已经看到了我的错误在哪里。我想检查您是否可以使用字符串进行快速排序,您知道互联网上只有数字示例。
  • 请注意,在实际的 C++ 应用程序中,强烈建议使用 std::vector 而非链表(或 std::list)。链表或std::list 在计算机早期具有轻微的性能优势,但由于现代 CPU 设计、延迟问题等在过去 20 年中发生了变化。这似乎并不明显,但std::vector 是在几乎所有实际应用中都更快(并且更易于使用)。你也可以使用std::sort
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
  • 2023-03-06
  • 2020-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多