当前位置: 首页 > 知识库问答 >
问题:

合并排序循环链表C

丁良骏
2023-03-14

我试图用C语言合并排序列表。我在法语维基百科上看到了这里的代码,但它给了我一个不正确的列表(即未排序)。不过,该函数编译得很好。请注意,我并没有真正使用top,我可能很快就会把它从结构中去掉。你能帮我找出这个代码的错误吗?我必须把它从算法伪代码翻译成C代码。非常感谢。

P是未排序的输入列表。n是列表的长度。

typedef struct s_stack t_stack;

struct s_stack {
    int     nbr;
    int     top;
    struct s_stack  *previous;
    struct s_stack  *next;
};

typedef t_stack *Pile;

t_stack *merge_sort(Pile p, int n) {
    Pile    q;
    int     Q;
    int     P;

    q = NULL;
    Q = n / 2;
    P = n - Q;

    if (P >= 2) {
        q = merge_sort(p, P);
        if (Q >= 2)
            p = merge_sort(q, Q);
    } else {
        q = p->next;
    }
    q = fusion(p, P, q, Q);
    return (q);
}

t_stack *fusion(Pile p, int P, Pile q, int Q) {
    t_stack *tmp;

    tmp = NULL;
    while (1) {
        if (p->next->nbr > q->next->nbr) {
            /* my input list (not sorted) is circular and 
            I checked it is well linked ! This is the reason 
            why I need to do all that stuff with the nodes 
            It is basically supposed to move the node q->next
            after node p */

            tmp = q->next;
            q->next = tmp->next;
            q->next->previous = q;
            tmp->previous = p;
            tmp->next = p->next;
            p->next->previous = tmp;
            p->next = tmp;

            if (Q == 1)
                break;
            Q = Q - 1;
        } else {
            if (P == 1) {
                while (Q >= 1) {
                    q = q->next;
                    Q = Q - 1;
                }
                break;
            }
            P = P - 1;
        }
        p = p->next;
    }
    return (q);
}

共有1个答案

殳宸
2023-03-14

你的方法有点复杂,但问题并不简单,但你错过了一些必要的步骤:

  • merge\u sort应该将列表分成两半并递归,除非列表很小

这是一个带有主函数的修正版本,用于测试命令行参数。

#include <stdio.h>
#include <stdlib.h>

typedef struct s_stack t_stack;

struct s_stack {
    int     nbr;
    int     top;
    struct s_stack  *previous;
    struct s_stack  *next;
};

t_stack *fusion(t_stack *p, int P, t_stack *q, int Q) {
    t_stack *s;
    t_stack *e;

    s = NULL;
    while (P > 0 && Q > 0) {
        if (p->nbr <= q->nbr) {
            /* select element from p list */
            e = p;
            p = p->next;
            P--;
        } else {
            /* select element from q list */
            e = q;
            q = q->next;
            Q--;
        }
        /* detach e */
        e->previous->next = e->next;
        e->next->previous = e->previous;
        e->next = e->previous = e;
        if (s == NULL) {
            s = e;
        } else {
            /* insert e after s */
            e->previous = s->previous;
            e->next = s;
            s->previous->next = e;
            s->previous = e;
        }
    }
    if (P > 0) {
        /* insert p at the end of s */
        if (s == NULL) {
            s = p;
        }  else {
            /* insert p after s */
            e = p->previous; /* end element of p */
            p->previous = s->previous;
            e->next = s;
            s->previous->next = p;
            s->previous = e;
        }
    }
    if (Q > 0) {
        /* insert q at the end of s */
        if (s == NULL) {
            s = q;
        }  else {
            /* insert q after s */
            e = q->previous; /* end element of p */
            q->previous = s->previous;
            e->next = s;
            s->previous->next = q;
            s->previous = e;
        }
    }
    return s;
}

t_stack *merge_sort(t_stack *s, int S) {
    t_stack *p;
    t_stack *q;
    int     P;
    int     Q;

    if (S < 2) {
        /* single or no elements, already sorted */
        return s;
    }

    /* split p in 2 halves: p[0..P] and q[0..Q] */
    for (q = p = s, P = 0, Q = S; P < Q; P++, Q--) {
        q = q->next;
    }

    p = merge_sort(p, P);
    q = merge_sort(q, Q);
    s = fusion(p, P, q, Q);
    return s;
}

t_stack *append(t_stack *s, int value) {
    t_stack *e = malloc(sizeof(*e));
    e->top = 0;
    e->nbr = value;
    e->next = e->previous = e;
    if (s == NULL) {
        s = e;
    } else {
        /* insert e after s */
        e->previous = s->previous;
        e->next = s;
        s->previous->next = e;
        s->previous = e;
    }
    return s;
}

void print_stack(const char *legend, t_stack *s, int S) {
    printf("%s:", legend);
    while (S-- > 0) {
        printf(" %d", s->nbr);
        s = s->next;
    }
    printf("\n");
    fflush(stdout);
}

int main(int argc, char *argv[]) {
    t_stack *s = NULL;
    int S = 0;
    int i;

    for (i = 1; i < argc; i++) {
        s = append(s, atoi(argv[i]));
        S++;
    }
    print_stack("original stack", s, S);
    s = merge_sort(s, S);
    print_stack("sorted stack", s, S);
    return 0;
}

 类似资料:
  • 我在C语言课程考试前练习一些算法问题,我被这个问题卡住了(至少3个小时甚至4个小时),我不知道如何回答: 您有两个已排序的循环单链接列表,必须合并它们并返回新循环链接列表的标题,而不创建任何新的额外节点。返回的列表也应该进行排序。 节点结构为: 我尝试了很多方法(递归和非递归),但都没有解决问题。 谢谢你的帮助。

  • 我试图借助单链表编写合并排序,节点定义如下, 合并排序的工作方式如下: i、 将未排序的列表划分为n个子列表,每个子列表包含1个元素(1个元素的列表被视为已排序)。 二、。重复合并子列表以生成新排序的子列表,直到只剩下1个子列表。这将是排序列表。代码如下所示。 我像这样打入会电话, 结果是,所有负值似乎都消失了。这里有什么问题?

  • 合并排序通常是对链表排序的首选方式。链表缓慢的随机访问性能使得一些其他算法(如quicksort)表现不佳,而另一些算法(如heapsort)则完全不可能。我一直在努力在链表上做归并排序。它不断返回一个错误。我正在提供我试图执行的代码。请一定要帮我。它不断给出运行时错误。

  • 我的任务是用java实现一个循环链表(升序),但问题是它在无限循环中运行 我创建了一个节点类,其中定义了两个元素。 现在,在列表的第二个类中,我做了一个insert函数,我在start中定义了一个节点head=null,并创建了一个新的nNode。之后,我在head部分中检查,如果head==null,那么第一个元素将是nNode。插入第一个元素后,我将比较下一个元素和head元素,如果head元

  • 我写了一个合并两个已经排序的链表的方法。然而,由于某种原因,列表的最后一个节点没有打印出来。有什么想法吗? 下面是链接列表的合并排序方法。

  • NowCoder 题目描述 解题思路 递归 // java public ListNode Merge(ListNode list1, ListNode list2) { if (list1 == null) return list2; if (list2 == null) return list1; if (list1.val <= lis