在C ++中分离链表中的偶数节点和奇数节点

时间:2016-12-09 23:41:51

标签: c++ algorithm linked-list

所以,我自学数据结构和算法。在解决一些问题时,我遇到了以下问题:我必须隔离链表的奇数和偶数节点。

http://www.geeksforgeeks.org/segregate-even-and-odd-elements-in-a-linked-list/

以下是问题陈述:

给定一个整数链接列表,编写一个修改链表的函数,使所有偶数出现在修改后的链表中的所有奇数之前。另外,保持偶数和奇数的顺序相同。

我知道这个问题被问了很多次。但我仍然无法找到答案。我知道有多种方法可以解决这个问题,但试图通过以下方式解决这个问题

    1. Traversing over the original list and moving all the odd elements to new oddlist. 
       Same time delete those elements from the original list.
    2. Now original list should have even elements and oddlist will have odd elements.
    3. concatenate original list and oddlist 

看起来很简单 我认为只需删除节点并调整几个指针就可以解决问题,但事实并非如此

#include <iostream>
#include <stdlib.h>

using namespace std;

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


struct Node *Insert_at_bottom(struct Node* head, int data) {
    struct Node *node;

    node = new struct Node;
    node->data = data;
    node->next = NULL;
    //node->prev = NULL;

    struct Node *temp;

    if (head == NULL) {
        head = node;
        return head;
    }

    temp = head;
    while(temp->next != NULL){
        temp = temp->next;
    }

    temp->next = node;
    //node->prev = temp;
    return head;
}




struct Node *seperate_elements(struct Node *head) {
    struct Node *temp = head;
    struct Node *oddhead = NULL;
    struct Node *temp1 = NULL;
    while (temp != NULL) {
        if (temp->data%2 == 0) {
            cout << "even:" << temp->data << "\n";


        }
        else{
            cout << "odd:" << temp->data << "\n";
            oddhead = Insert_at_bottom(oddhead, temp->data);

            // I am messing something here. Not sure what!!!
            temp1 = temp->next;
            temp->next = temp1->next;
            //temp->next = temp->next->next;
            free(temp1);
        }

        temp = temp->next;
    }
    return oddhead;
}

struct Node *concate_list(struct Node *head, struct Node *oddhead) {
    struct Node *temp = head;
    while(head->next!=NULL)
    {
        head = head->next;
    }
    head->next = oddhead;
    return temp;

}

void print_list(struct Node *head){
    while(head){
        cout << head->data << " ";
        head = head->next;
    }
}

int main(){

    struct Node *head = NULL;
    struct Node *head2 = NULL;
    struct Node *finalhead = NULL;
    head = Insert_at_bottom(head, 1);
    head = Insert_at_bottom(head, 2);
    head = Insert_at_bottom(head, 8);
    head = Insert_at_bottom(head, 4);
    head = Insert_at_bottom(head, 5);
    head = Insert_at_bottom(head, 7);

    head2 = seperate_elements(head);


    finalhead = concate_list(head, head2);
    //cout << "\n";
    print_list(finalhead);

    return 0;
}

所以当我执行上面的代码时,我得到了

1 8 4 5 1 5 instead of 2 8 4 1 5 7

现在,我想在删除节点时我遗漏了一些东西。不知道我在这里做错了什么。我想我没有正确地关注指针调整。我真的很感激这里的任何帮助。

谢谢,

1 个答案:

答案 0 :(得分:2)

如果您不想创建第二个列表,这不是必需的,那么您可以做的最好的事情是这样的算法:

1)找到列表的最后一个元素(你可以在线性时间内完成)

2)开始遍历列表,每次找到奇数元素时,将其放在列表的末尾。这很简单,你只需要调整前一个元素,下一个元素,奇数元素本身和最后一个元素的指针。

做#2直到你找不到列表的最后一个元素。要跟踪这一点,你必须为最后一个元素保存两个指针,一个在你将奇数元素放在最后一个元素时会更新,另一个只是标记原始列表的结尾,允许你终止算法