对链表中的名称进行排序

时间:2010-05-31 04:32:07

标签: c++ gcc linked-list

我正在尝试在链接列表中按字母顺序对名称进行排序,但是出现运行时错误。我在这里做错了什么?

#include <iostream>
#include <string>
using namespace std;

struct node{
    string name;
    node *next;
};

node *A;

void addnode(node *&listpointer,string newname){
    node *temp;
    temp = new node;
    if (listpointer == NULL){
        temp->name = newname;
        temp->next = listpointer;
        listpointer = temp;
    }else{
        node *add;
        add = new node;
        while (true){
            if(listpointer->name > newname){
                add->name = newname;
                add->next = listpointer->next;
                break;
            }
            listpointer = listpointer->next;
        }
    }
}

int main(){

    A = NULL;
    string name1 = "bob";
    string name2 = "tod";
    string name3 = "thomas";
    string name4 = "kate";
    string name5 = "alex";
    string name6 = "jimmy";
    addnode(A,name1);
    addnode(A,name2);
    addnode(A,name3);
    addnode(A,name4);
    addnode(A,name5);
    addnode(A,name6);

    while(true){
        if(A == NULL){break;}
        cout<< "name is: " << A->name << endl;
        A = A->next;
    }

    return 0;

}

3 个答案:

答案 0 :(得分:4)

您正试图在addnode中取消引用空指针。在listpointer->name > newname永远不为真的情况下,listpointer最终将设置为NULL,然后尝试在下一次listpointer->name > newname比较中再次取消引用。

...代码中的其他可能的逻辑错误,即。

答案 1 :(得分:1)

我认为错误在于你认为:

if (listpointer == NULL){
    temp->name = newname;
    temp->next = listpointer;
    listpointer = temp;
}

保证listpointer以后永远不会为NULL。但事实并非如此,例如:

void addnode(node *&listpointer,string newname){
   node *temp;
    temp = new node;
    if (listpointer == NULL){
        temp->name = newname;
        temp->next = listpointer;
        listpointer = temp;
    }else{
        node *add;
        add = new node;
        while (true){
            if( (listpointer) == NULL){
            std:cout << "oops (listpointer) == NULL)";
            }

            if(listpointer->name > newname){
                add->name = newname;
                add->next = listpointer->next;
                break;
            }
            listpointer = listpointer->next;
        }
    }
}

将打印出“oops”然后段错误,因为lispointer为NULL并使用 - &gt;在NULL上将导致段错误。这是因为在while(true)循环中,listpointer最终到达结尾并被设置为NULL。然后你得到段错误。

我认为更好的想法是做一些事情:

bool has_inserted;
while ( listpointer != NULL){
  if(listpointer->name > newname){
     add->name = newname;
     add->next = listpointer->next;
     has_inserted = true;
     break;
  }
  listpointer = listpointer->next;
}
if(has_inserted == false){
//insert at end of list
}

此代码也会泄漏内存,因为您不会删除使用new创建的内容。你可能想用valgrind运行这个(和其他代码)看看我的意思。

答案 2 :(得分:0)

我对您的代码做了一些修改:

1 - 通过从代码中删除temp来防止内存泄漏。

2 - 你必须保持列表第一个元素的指针。如果你丢失它,你将无法再添加更多项目,也无法打印列表内容。

3 - 代码必须分析是否必须在列表的顶部,中间或末尾插入新项目。如果在顶部,则必须将列表指针更改为它。

所以我修复了这些错误,你的代码现在很好。

请记住,您的main()应调整为在打印项目时不更改列表指针(A)。如果是这样,您将在打印后失去对列表的控制权,并且将无法再访问或删除其节点。如果您在此测试中不关心它,请忘记它。

void addnode(node *&listpointer,string newname){
    node *add,
         *last,
         *current;

    add = new node;
    add->name = newname;

    if (listpointer == NULL){
        add->next = listpointer;
        listpointer = add;
    }else{
        current = listpointer;
        last    = listpointer;
        while (current && current->name < newname){
            last = current;
            current = current->next;
        }

        if (current == listpointer){
            /* Insert before 1st node */
            add->next = listpointer;
            listpointer = add;
        }
        else{
            /* Insert between last and current 
               or at the end of the list */
            last->next = add;
            add->next = current;
        }
    }
}