合并2个链接列表并附加到链接列表c ++的末尾

时间:2015-05-29 07:03:29

标签: c++ linked-list

到目前为止我还没有多少,但我正试图使用​​链接列表。

STRUCT:

struct Node 
{
   int value;
   Node *next;
};

如何将节点添加到列表末尾?我只是试图接受一个列表头部的指针和一个作为新节点添加的int值。当我尝试运行我目前所拥有的时,我得到一个例外。

void addNode(Node* head, int x) 
{

    Node* temp = new Node;
    temp->data = x;
    temp->next = NULL;

     if(!head) 
     { 
         head = temp;
         return;
     } 
     else 
     {
         Node* last = head;
         while(last->next) 
         last=last->next;

         last->next = temp;
     }
}

我还没有真正开始合并两个列表。我只知道我需要接收2个链接列表(或指向2个链表的头部?)然后遍历所有节点的列表。

E.G:链表1有3个节点:4,10,20。 链表2有4个节点:2,5,15,60。

合并列表函数将生成一个新的链表,其中包含2,4,5,10,15,20,60作为节点。

编辑:在我的主要部分,我正在调用addNode函数:

Node *head = new Node;

insertAtEnd(head,20);

这是正确的还是可能是异常的原因?

4 个答案:

答案 0 :(得分:1)

按以下方式声明函数

void addNode( Node* &head, int x) ;

而不是此代码段

Node *head = new Node;

insertAtEnd(head,20);

你必须第一次以下列方式调用该函数

Node *head = nullptr; // or NULL

addNode(head,20);

请注意,帖子中没有名称为insertAtEnd的函数。有函数addNode。:)

如果您需要合并两个列表,那么您可以使用此演示程序作为示例。当然,您需要添加一些其他功能,例如删除列表以获得完整的项目。

#include <iostream>

struct Node 
{
    int value;
    Node *next;
};

Node * insert( Node *current, int value )
{
    Node *tmp;

    if ( current == nullptr )
    {
        tmp = new Node { value, nullptr };
    }
    else
    {
        tmp = new Node { value, current->next };
        current->next = tmp;
    }

    return tmp;
}

std::ostream & display( Node *head, 
                        std::ostream &os = std::cout,
                        const char *delimiter = " " )
{
    for ( ; head; head = head->next ) os << head->value << delimiter;

    return os;
}

Node * merge( Node * &head1, Node * &head2 )
{
    Node *new_head = nullptr;
    Node *current  = nullptr; 

    while ( head1 != nullptr && head2 != nullptr )
    {
        Node *tmp;
        if ( head2->value < head1->value )
        {
            tmp = head2;
            head2 = head2->next;
        }
        else
        {
            tmp = head1;
            head1 = head1->next;
        }

        tmp->next = nullptr;
        if ( new_head == nullptr )
        {
            new_head = tmp;
            current = new_head;
        }
        else
        {
            current->next = tmp;
            current = current->next;
        }
    }

    if ( head1 != nullptr ) new_head == nullptr ? new_head : current->next = head1;
    if ( head2 != nullptr ) new_head == nullptr ? new_head : current->next = head2;


    head2 = nullptr;
    head1 = new_head;

    return new_head;
}

int main() 
{
    Node *list1 = nullptr;
    Node *list2 = nullptr;

    list1 = insert( list1, 4 );
    insert( insert( list1, 10 ), 20 );

    display( list1, std::cout << "List1: " ) << std::endl;

    list2 = insert( list2, 2 );
    insert( insert( insert( list2, 5 ), 15 ), 60 );

    display( list2, std::cout << "List2: " ) << std::endl;

    std::cout << std::endl;

    merge( list1, list2 );

    display( list1, std::cout << "List1: " ) << std::endl;
    display( list2, std::cout << "List2: " ) << std::endl;

    return 0;
}

程序输出

List1: 4 10 20 
List2: 2 5 15 60 

List1: 2 4 5 10 15 20 60 
List2: 

答案 1 :(得分:1)

通过这样做:

void addNode(Node* head, int x) 
// here ---------^

然后是这个:

 head = temp; // here

你只是修改本地head指针,它接受从调用者传递的地址值。由于head不是对指针的实际引用(它只是一个指针),因此结果是调用者的指针在head保持不变时传递。你永远不会将你分配的节点附加到列表中,泄漏内存,这将成为一个悲伤的日子......

通过引用传递指针。解决这个问题,然后修复无效的data成员(实际上应该是value和指针指针,用于遍历列表以查找结尾),结果可能如下所示:

#include <iostream>

struct Node
{
    int value;
    Node *next;
};

void addNode(Node*& head, int x)
{
    Node **pp = &head;
    while (*pp)
        pp = &(*pp)->next;
    *pp = new Node;
    (*pp)->value = x;
    (*pp)->next = nullptr;
}

void printList(const Node *head)
{
    for (; head; head = head->next)
        std::cout << head->value << ' ';
    std::cout << '\n';
}

void freeList(Node *&head)
{
    while (head)
    {
        Node *p = head;
        head = p->next;
        delete p;
    }
}

int main()
{
    Node *head = nullptr;

    for (int i=1; i<=5; ++i)
        addNode(head, i);

    printList(head);
    freeList(head);
}

<强>输出

1 2 3 4 5 

我将实现合并的任务留给您,但这足以让您获得可管理的列表并运行。

更新:来自OP的编辑问题:

Node *head = new Node;

insertAtEnd(head,20);

除了现在是一个完全不同的命名函数之外,您的节点是默认初始化的。在您的情况下,这意味着来自Node的结果new Node; valuenext 然后你将它传递给你的函数,它假设一个确定的值(null)来终止你的循环。

这可以通过多种方式修复;上面代码的机制就是这样一种方式。如果列表管理代码理解NULL表示无列表,则不需要首先预先分配头节点。你的addNode原始帖子似乎至少试图遵循这个口头禅。

答案 2 :(得分:0)

这可能是例外原因:

struct Node 
{
   int value;     <-----  Node structure has value property
   Node *next;
};


Node* temp = new Node;
temp->data = x;   <------ Assigning to data property of Node which does not exists
temp->next = NULL;

要添加列表,您可以使用相同的方法

void addNode(Node* head, Node* head2) 
{

  Node* last = head;
  while(last->next) last=last->next;

  last->next = head2;
}

答案 3 :(得分:0)

  

编辑:在我的主要部分,我正在调用addNode函数:

Node *head = new Node;
insertAtEnd(head,20);

这是错误的。您没有初始化head->next,因此在insertAtEnd中,代码while(last->next) last=last->next;将尝试比较未初始化的指针,如果它不为null,则会取消引用它。这可能会导致您的程序崩溃而不是抛出异常。然后,它是未定义的行为,所以任何事情都可能发生。

由于你的插入函数已经涵盖了插入空列表的情况,我只需要调用

head = nullptr;
insertAtEnd(head,20)`;

除此之外,还有一个永远不会更新函数外head指针的错误,这已经在其他答案中得到了解释。