【问题标题】:Insertion Sort with a Singly Linked List in C++在 C++ 中使用单链表进行插入排序
【发布时间】:2013-02-15 20:16:08
【问题描述】:

我正在尝试为我的 LinkedList 类编写一个方法,该方法将按名称对 Person 对象的链接列表进行排序。我的方法编译得很好,但是当我尝试对人员列表进行排序时,输出不正确。它也永远不会停止运行。比如这段代码

Person *p1 = new Person("K", "B");
Person *p2 = new Person("A", "A");
Person *p3 = new Person("S", "M");
Person *p4 = new Person("B", "M");

LinkedList ll;
ll.insertFront(*p1);
ll.insertFront(*p2);
ll.insertFront(*p3);
LinkedList newList = ll.insertionSort();
newList.print();
cout << endl;

给出这个输出

B, K

A, A

谁能帮我弄清楚我的算法哪里出错了?谢谢!

这是我用来按名字和名字排序的方法:

int Person::compareName(Person p)
{
    if (lName.compare(p.lName) > 0)
    {
        return 1;
    }
    else if (lName.compare(p.lName) == 0)
    {
        if (fName.compare(p.fName) > 0)
        {
            return 1;
        }
        else return -1;
    }
    else return -1;
}

插入排序方法:

LinkedList LinkedList::insertionSort()
   {
    //create the new list
    LinkedList newList;
    newList.front = front;
    
    Node *n;
    Node *current = front;
    Node *trail = NULL;
    
   for(n=front->link; n!= NULL; n = n->link)//cycle through old chain
{
    Node* newNode = n;
    
    //cycle through new, sorted chain to find insertion point
    for(current = newList.front; current != NULL; current = current->link)
    {
        //needs to go in the front
        if(current->per.compareName(n->per) < 0)
        {
            break;
        }
        
        else
        {
            trail = current;
            
        }
    }
    
    //if it needs to be added to the front of the chain
    if(current == front)
    {
        newNode->link = newList.front;
        newList.front = newNode;
    }
    //else goes in middle or at the end
    else{
        newNode->link = current;
        trail->link = newNode;
    }

    return newList;
}

【问题讨论】:

  • 标题调整;虽然我还没有查看详细信息,但我怀疑这将是一个算法问题而不是语言问题,所以我不确定它有多大关系。
  • 您尝试过调试吗?换句话说,你有没有单步调试过代码,看看它在做什么?
  • 天啊。当我阅读您的代码时,我很想为您编写它,而不是试图理解您在这里做什么。那会更快更容易。你的代码刚刚烤了我的面条。您的 compareName 方法不正确,但它为提供的示例提供了正确的结果,因此问题不存在。请从旧列表中分离一个元素并将其附加到正确位置的新元素,而不是尝试重新链接列表中的断开链接。嗯,这就是我认为你正在做的事情,但我不能确定。

标签: c++ linked-list insertion-sort


【解决方案1】:

您的内部 for 循环中有 current-> 链接,并且在 else 到内部 for 循环中。我假设你在 for 循环中确实有 current = current->link 或者它什么都不做。如果是这样,您将跳过所有其他元素。

您还有语言方面的问题 - 您不是在创建新节点,而是在更改原始列表中的节点。这意味着您在遍历列表时正在更改列表,这会在您对列表进行排序时损坏列表。行为未定义,取决于您添加元素的顺序。

【讨论】:

  • 是的,第二点很重要。问题是对指针的根本误解,它看起来有点像从 Java 中翻译失败。
  • 这也会在 Java 中引起问题,因为一切都是参考。但是,是的,这有家庭作业的味道,所以它可能是 OP 不理解指针。没关系,只要他真的要求正确的跟进并学习。
  • 是的,我了解 Java,而且我刚开始在 C++ 中学习这个类,所以我仍然对指针感到困惑。所以我必须在外循环中创建一个新节点,这样我才能添加它到新的链表?如果我用同一个 person 对象创建一个新节点,我会怎么做呢?我的 Node 类中有一个复制构造函数,但我不知道如何使用它。
  • 所以在 C++ 中你有对象和指针。指针基本上是内存地址——将 RAM 视为一个巨大的数组。指针是该数组的索引。当您对指针执行某些操作时,您对存储在 RAM 中该索引处的变量执行此操作。如果两个类都有一个指向同一个地方的指针,对它做任何事情都会改变两个类的指针。这就是你在这里所做的——你没有创建新节点,所以两个类都看到了变化。
  • 所以我必须为 newList 创建新节点,然后在旧列表上使用解构函数?
【解决方案2】:

即使在您修复了任何链表处理问题(我还没有查看)之后,您的 compareName() 函数也存在缺陷 - 在比较具有相同姓氏的 Person 对象时,它可能会从函数返回不提供值(在Name.compare(p.fName) &lt;= 0 的情况下)。

从比较函数中得到一个不确定的结果几乎会破坏任何排序。

由于这可能是家庭作业,我将把纠正问题留作练习。

【讨论】:

  • 好的,所以我添加了 else return -1;对于 fName.compare(p.fName) 的情况
  • @KristyB:fName.compare(p.fName) == 0的情况需要返回0。
  • 啊,我明白了。错过了那个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-06
  • 2011-08-13
  • 2019-08-26
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
  • 2020-06-13
相关资源
最近更新 更多