【问题标题】:function to flatten list in to single list将列表展平为单个列表的功能
【发布时间】:2010-12-20 07:55:42
【问题描述】:

给定一个链表结构,其中每个节点代表一个链表,并且 包含其类型的两个指针:

(i) 指向主列表中下一个节点的指针。
(ii) 指向此节点为头的链表的指针。

编写一个 C 函数将列表展平为单个链表。

例如。

如果给定的链表是

  1 -- 5 -- 7 -- 10 
  |    |    | 
  2    6    8 
  |    | 
  3    9 
  | 
  4 

然后转换成

1 - 2 - 3 - 4 - 5 - 6 - 9 - 7 - 8 -10 

我的解决方案

struct node {
    int data; 
    struct node *fwd; //pointer to next node in the main list. 
    struct node *down; //pointer to a linked list where this node is head. 
}*head,*temp,*temp2; 

temp=head; 
while(temp->fwd!=NULL) {
    temp2=temp->fwd; 
    while(temp->down!=NULL) {
        temp=temp->down;
    } 
    temp->down=temp2;
    temp->fwd=NULL;
    temp=temp2;
 }  

如有任何问题请通知我...欢迎其他解决方案和优化

【问题讨论】:

  • 我的解决方案:struct node { int data;结构节点 *fwd; //指向主列表中下一个节点的指针。结构节点 *down; //指向此节点为头的链表的指针。 }*head,*temp,*temp2;温度=头;而(temp->fwd!=NULL){ temp2=temp->fwd; while(temp->down!=NULL) { temp=temp->down; } temp->down=temp2;临时->fwd=NULL;温度=温度2;如果有任何事情请通知我...欢迎其他解决方案和优化
  • @wilhelmtell:从它的写作方式猜测你是对的。
  • 不,这不是家庭作业...这是一个面试问题。请您提出更好的答案..
  • @sjngm 它缺少最后一部分:“或者你得到一个 D”
  • @prp 列表旅行对于一个好的面试问题来说似乎太天真了

标签: c algorithm linked-list


【解决方案1】:

首先,让它发挥作用很重要。由于while(temp->fwd!=NULL),您的解决方案不适用于以下场景:

A) 1 -- 2     B) 1 -- 3
        |        |    |
        3        2    4

试试这个:

#include <stdio.h>

struct node {
    int data;
    struct node *fwd; //pointer to next node in the main list.
    struct node *down; //pointer to a linked list where this node is head.
};

struct node *solve(struct node *head) {
    struct node *temp = head, *fwd;
    while (temp != NULL) {
        fwd = temp->fwd;
        while (temp->down != NULL) {
            temp = temp->down;
        }
        temp->down = fwd;
        temp->fwd = NULL;
        temp = fwd;
    }
    return head;
}

int main(int argc, char **argv) {
    struct node
        n12 = { 12, NULL, NULL },
        n11 = { 11, NULL, &n12 },
        n10 = { 10, NULL, &n11 },
        n8 = { 8, NULL, NULL },
        n7 = { 7, &n10, &n8 },
        n9 = { 9, NULL, NULL },
        n6 = { 6, NULL, &n9 },
        n5 = { 5, &n7, &n6 },
        n4 = { 4, NULL, NULL },
        n3 = { 3, NULL, &n4 },
        n2 = { 2, NULL, &n3 },
        n1 = { 1, &n5, &n2 },
        *result = solve(&n1);

    while (result != NULL) {
        printf("%d%s", result->data, result->down ? " - " : "");
        result = result->down;
    }
    puts("");

    return 0;
}

注意:这当然不涉及node-&gt;down-&gt;fwd。您可能想使用递归函数来解决这个问题,这留作练习。

【讨论】:

    【解决方案2】:

    如果您将“向下”链接视为左子指针,将“前向”链接视为右子指针,那么您正在寻找简单二叉树的有序遍历。也就是你访问节点;然后你访问左(下)孩子,然后你访问右(前)孩子。把它写成递归函数很容易。

    如果第一个节点只有一个向下指针而没有前向指针,您的解决方案将不会遍历任何树。如果有向下指针,它也不会从最后一个指针向下搜索(因为它没有前向指针)。

    我认为(但我不确定 - 我没有测试过)您的解决方案在比示例中的更茂密的树上遇到了麻烦。如果节点 2 有前向指针,我认为搜索该子树会有问题。

    使用递归;它微不足道且可靠。虽然您可以消除简单的尾递归,但这需要的不仅仅是简单的尾递归。

    【讨论】:

    • 如果 Jonathan 的解决方案对您没有意义,只需将头向左倾斜 45 度,同时查看您的列表图表。
    【解决方案3】:
    struct node* flatten_dfwalk(struct node * root)
    {   
    
        struct node *lnode, *rnode, *temp;
    
        if (NULL == root)
        {
            return NULL;
        }
    
    
        lnode = flatten_dfwalk(root->down);
        rnode = flatten_dfwalk(root->next);
    
        if (NULL == lnode)
        {
            return root;
        }
    
        temp = lnode;
        while(lnode->next != NULL)
        {
            lnode = lnode->next;
        }
    
        lnode->next = root->next;
        root->next = temp;
    
        return root;
    }
    

    【讨论】:

      【解决方案4】:

      对我来说,解决方案看起来不错。一个小的变化可能是从解决方案的图表来看,我希望答案应该是一个“水平”列表(使用 fwd 指针)而不是您的解决方案产生的垂直列表(使用向下指针)

      【讨论】:

        【解决方案5】:
            struct node * last;
            void dfs(struct node * root)
            {
                if(root)
                {
                    dfs(root->down);
                    if(last!=NULL)
                    {
                        last->next=root->next;
                        last=NULL;
                    }
                    dfs(root->next);
                    if(root->down)
                    root->next=root->down;
        
                    if(root->next==NULL&&root->down==NULL)
                        last=root;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2018-02-11
          • 1970-01-01
          • 2016-01-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-14
          • 2013-11-13
          • 1970-01-01
          相关资源
          最近更新 更多