简体   繁体   English

在链表中对偶数和奇数进行排序

[英]sorting even and odd numbers in a linked list

Im trying to write a function that takes a random list and sorts it (in c) so that even numbers are first, doing so without creating a second list. 我试图编写一个函数,该函数接受一个随机列表并对其进行排序(在c中),以便偶数在前,而无需创建第二个列表。 What im trying to do is moving a newly found even number to the head of the list (making the previous head the seconnd element). 我想做的是将一个新发现的偶数移到列表的开头(使前一个成为第二个元素)。 Cant understand why my pointers get messed up though - 不能理解为什么我的指针弄乱了-

typedef struct node node;
typedef struct node {
    int data;
    node *next;
};

void sortlist(node *head) {
    if (head == NULL) {
        printf("Empty list \n");
    }
    node *index1 = head->next;
    node *oldhead;
    if (index1 == NULL) {
        return;
    }
    while (index1 != NULL) {
        if (index1->data % 2 == 0) {
            oldhead = head;
            head = index1;
            head->next = oldhead;
        }
        index1 = index1->next;
    }
}

Main idea : Suppose you have a list as below. 主要思想 :假设您有一个如下列表。

1->3->2->4 1-> 3-> 2-> 4

When you want to make the element 2 the new head, you have to do two things. 当您要使元素2成为新的标头时,您必须做两件事。

  • Unlink element 2 and make next element of 3 to 4 . 取消链接元素2并使其下一个元素34 [which you are missing in your code] [您的代码中缺少的]
  • Make a new node and make it the new head of the list. 新建一个节点,使其成为列表的新标题。

Then the list will look like 2->1->3->4 . 然后列表将看起来像2->1->3->4 Again doing the same thing for element 4 , it will look like 4->2->1->3 . 再次对元素4做同样的事情,它看起来像是4->2->1->3

So, I believe you need (tentatively) something like this. 因此,我相信您(暂时)需要这样的东西。

void sortlist(node *head) {
    if (head == NULL) {
        printf("Empty list \n");
    }
    node *current = head->next;
    node *previous = head;
    while(current != NULL){
        if(current->data % 2 == 0){
            previous->next = current->next;
            current->next = head;
            head = current;
        } else{
            previous = previous->next;
            //previous = current; [an equivalent statement]
        }
        current = previous->next;
    }
}

An alternative approach if you want to create a new node and make it the head of the list. 如果您要创建一个新节点并使它成为列表的头,则可以采用另一种方法。

void sortlist(node *head) {
    if (head == NULL) {
        printf("Empty list \n");
    }
    node *current = head->next;
    node *previous = head;
    while(current != NULL){
        if(current->data % 2 == 0){
            previous->next = current->next;
            node* new_node = (struct node*) malloc (sizeof (struct node));
            new_node->data = current->data;
            new_node->next = head;
            head = new_node;
        } else{
            previous = previous->next;
        }
        current = current->next;
    }
}

Update : I have verified both the code snippet. 更新 :我已经验证了两个代码段。 Its working! 它的工作!

This is not enough: when you move a node to the head, you need also to direct its previous to its next . 这还不够:将节点移动到头部时,还需要将其前一个指向下一个 Since your list is linked in only one direction, you need to keep track of what was its previous. 由于列表仅在一个方向上链接,因此您需要跟踪以前的列表。

Moreover, sending the head pointer like this, by value , will not change it in the caller, so the caller will loose track of the head of the list. 而且, 按值发送这样的head指针不会在调用方中更改它,因此,调用方将失去对列表头的跟踪。 Therefore, you need to pass the head pointer in a way that it can be modified and retrieved, that is, send a pointer to that pointer: 因此,您需要以一种可以修改和检索它的方式传递头指针,即向该指针发送一个指针:

void sortlist(node** head) {
    if (*head == NULL) {
        printf("Empty list \n");
    }
    node *index1 = (*head)->next;
    node *prev = *head;

    while (index1 != NULL) {
        if (index1->data % 2 == 0) {
            prev->next = index1->next;
            index1->next = *head;
            *head = index1;
        }
        else {
            prev = index1;
        }
        index1 = prev->next;
    }
}

It is not clear why you skip the head itself and start with head->next. 目前尚不清楚为什么跳过头部本身并从head-> next开始。

Also the head node should be passed by reference because the head is changed in the function. 另外,头节点也应通过引用传递,因为在功能中头已更改。

And it does not make sense to output a message that the list empty because the caller can check itself before calling the function whether the list is empty can not it? 并且输出消息列表为空是没有意义的,因为调用者可以在调用函数之前检查自身,列表是否为空不是吗?

The function can look the following way 该函数可以如下所示

void sortlist(node **head)
{
    for (node **current = head; *current != NULL; )
    {
        if ((*current)->data % 2 == 0 && current != head)
        {
            node *tmp = *current;
            *current = (*current)->next;
            tmp->next = *head;
            *head = tmp;
        }
        else
        {
            current = &(*current)->next;
        }
    }
}

For example if the list contains the following clause 例如,如果列表包含以下子句

0 1 2 3 4 5 6 7 8 9

then after calling the function it will look like 然后在调用该函数后,它将看起来像

8 6 4 2 0 1 3 5 7 9

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM