编写一个重新排列链表的函数,将节点置于列表中奇数位置的节点之后的偶数位置

时间:2013-10-16 12:07:14

标签: c linked-list

编写一个重新排列链表的函数,将节点置于列表中奇数位置的节点之后的偶数位置,保留平均值和赔率的相对顺序。

我在Sedgewick的书写算法中发现了这个问题。我试过但失败了。我试图将所有节点放在另一个链表上的偶数位置。很感谢你帮助我。一个好主意就足够了。谢谢:)。

这是我在C中的代码。

/*
 * File: rearranges.c <Exercise 3.36>
 * Note: Write a function that rearranges a linked list to put the nodes in even
 *       positions after the nodes in odd positions in the list, preserving the
 *       relative order of both the evens and the odds.
 *       NOTICE: I think it's necessary to use linked list with a dummy head.
 * Time: 2013-10-26 10:58
 */
#include <stdio.h>
#include <stdlib.h>

#define LEN 11

typedef struct node *link;
struct node {
    int  item;
    link next;
};

/* Traverse a linked list with a dummy head. */
void traverse(link t) {
    link x = t->next;

    while (x != NULL) {
        printf("%d ", x->item);
        x = x->next;
    }
    putchar('\n');
}

/* Detach even positon nodes from a linked list. */
link detach(link t) {
    link u = malloc(sizeof(*u));
    link x = t, y = u;

    /* x is odd position node. We should ensure that there's still one even
     * position node after x. */
    while (x != NULL && x->next != NULL) {
        y->next = x->next;
        x->next = x->next->next;
        x = x->next;
        y = y->next;
        y->next = NULL;
    }

    return u;
}

/* Combine two linked list */
link combine(link u, link t) {
    link x = u;
    link y = t->next;

    while (y != NULL) {
        link n = y->next;

        y->next = x->next;
        x->next = y;

        x = x->next->next;
        y = n;
    }

    return u;
}

/* The function exchanges the position of the nodes in the list. */
link rearranges(link t) {
    link u = detach(t);
    link v = combine(u, t);

    return v;
}

int main(int argc, char *argv[]) {
    int i;
    link t = malloc(sizeof(*t));
    link x = t;

    for (i = 0; i < LEN; i++) {
        x->next = malloc(sizeof(*x));
        x = x->next;
        x->item = i;
        x->next = NULL;
    }

    traverse(t);
    traverse(rearranges(t));

    return 0;
}

4 个答案:

答案 0 :(得分:1)

curr=head;
end=lastOfList;//last node if size of list is odd or last-1 node 

for(int i=1;i<=listSize()/2;i++)
{
     end->next=curr->next;
     end=end->next;
     end->next=null;
     if(curr->next!=null)
        if((curr->next)->next!=null)
           curr->next=(curr->next)->next;
    curr=curr->next;
}

答案 1 :(得分:0)

您可以实现一个递归解决方案,其中每个调用都返回一个更新的节点,该节点将作为上层调用者的新next引用。我们只需要在列表中找到最后一个元素,然后将每个偶数节点移动到列表的末尾,并更新对最后一个元素的引用。这是我的解决方案(请在查看我和其他解决方案之前尝试自己做)

struct node {
    int val;
    struct node *next;
};

struct node *reorder_aux(struct node *l, int count, struct node **last);
struct node *reorder(struct node *l) {
    struct node *x;
    if (l == NULL)
        return NULL;
    return reorder_aux(l, 1, &x);
}

struct node *reorder_aux(struct node *l, int count, struct node **last) {
    struct node *n;
    if (l->next == NULL) {
        *last = l;
        return l;
    }
    n = reorder_aux(l->next, count+1, last);
    if (count & 1) {
        l->next = n;
        return l;
    }
    else {
        (*last)->next = l;
        l->next = NULL;
        *last = l;
        return n;
    }
}

在每个步骤中,如果当前节点l是偶数节点(由count确定),那么我们将此节点追加到末尾,并告诉上层调用者它的{{1 }指针应更新到我们的next(因为我们的next将是一个奇数节点)。如果我们是一个奇数节点,我们只需更新我们的next指向返回的任何递归调用(这将是指向奇数节点的指针),并返回当前节点,因为我们不会移动我们自己到了清单的最后。

这是一个很好的运动!

答案 2 :(得分:0)

#include <stdio.h>

struct list {
    struct list *next;
    int ch;
    };

void swap_odd_even (struct list **pp)
{
struct list *one, *two ;

for( ; (one = *pp) ; pp = &one->next) {
    two = one->next;
    if (!two) break;
    *pp = two;
    one->next = two->next;
    two->next = one;
    }
}

struct list arr[] =
{ {arr+1, 'A'} , {arr+2, 'B'} , {arr+3, 'C'} , {arr+4, 'D'}
, {arr+5, 'E'} , {arr+6, 'F'} , {arr+7, 'G'} , {arr+8, 'H'}
, {arr+9, 'I'} , {arr+10, 'J'} , {arr+11, 'K'} , {arr+12, 'L'}
, {arr+13, 'M'} , {arr+14, 'N'}, {arr+15, 'O'} , {arr+16, 'P'}
, {arr+17, 'Q'} , {arr+18, 'R'} , {arr+19, 'S'} , {arr+20, 'T'}
, {arr+21, 'U'} , {arr+22, 'V'}, {arr+23, 'W'} , {arr+24, 'X'}
, {arr+25, 'Y'} , {NULL, 'Z'} };
int main (void) {
    struct list *root , *ptr;

    root = arr;
    for (ptr=root ; ptr; ptr = ptr->next ) {
        printf( "-> %c" , ptr->ch );
        }
    printf( "\n" );

    printf( "Swap\n" );
    swap_odd_even ( &root);

    for (ptr=root ; ptr; ptr = ptr->next ) {
        printf( "-> %c" , ptr->ch );
        }
    printf( "\n" );

   return 0;
}

答案 3 :(得分:0)

在下文中,每次调用swap_nodes时,另一个奇数下沉到最后一个沉没奇数。每次迭代时,均匀组合在一起,它们会冒泡到列表的末尾。这是一个例子:

/*
[0]-1-2-3-4-5
1-[0-2]-3-4-5
1-3-[0-2-4]-5
1-3-5-[0-2-4]
*/

#include <stdio.h>
#include <stdlib.h>
#define LIST_LENGTH 10

struct node{
    int id;
    struct node *next;
};

void print_list(struct node *current)
{
    while(NULL != current){
        printf("node id = %d\n",current->id);
        current = current->next;
    }
    printf("Done\n");
}

struct node *swap_nodes(struct node *head_even, struct node *tail_even, struct node    *next_odd)
{
    tail_even->next = next_odd->next;
    next_odd->next = head_even;
    return next_odd;
}

struct node *reorder_list(struct node *head)
{
    struct node *head_even;
    struct node *tail_even;
    struct node *next_odd;
    struct node *last_odd;
    if(NULL == head->next){
        return head;
    }
    head_even = head;
    tail_even = head;
    next_odd = head->next;
    last_odd = head->next;
    head = swap_nodes(head_even, tail_even, next_odd);
    if(NULL != tail_even->next){
        tail_even = tail_even->next;
    }
    while (NULL != tail_even->next) {
        next_odd = tail_even->next;
        last_odd->next = swap_nodes(head_even, tail_even, next_odd);
        last_odd = last_odd->next;
        if(NULL != tail_even->next){
            tail_even = tail_even->next;
        }       
    }
    return head;    
} 

int main(void)
{
    int i;
    struct node *head = (struct node *) malloc(LIST_LENGTH*sizeof(struct node));
    struct node *mem = head;
    if(NULL == head){
        return -1;
    }
    struct node *current = head;
    for(i=0;i<LIST_LENGTH-1;i++){
        current->next = current + 1;
        current->id = i;
        current = current->next;
    }
    current->next = NULL;
    current->id = i;
    head = reorder_list(head);
    print_list(head);
    free(mem);  
    return 0;
}