以下程序不应该崩溃吗?

时间:2014-05-30 14:13:39

标签: c linked-list

我正在经历一个应该“压扁”链接列表的程序。 要看看flatten的意思,这里是链接的代码 http://www.geeksforgeeks.org/flattening-a-linked-list/

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

// A Linked List Node
typedef struct Node
{
    int data;
    struct Node *right;
    struct Node *down;
} Node;

/* A utility function to insert a new node at the begining
   of linked list */
void push (Node** head_ref, int new_data)
{
    /* allocate node */
    Node* new_node = (Node *) malloc(sizeof(Node));
    new_node->right = NULL;

    /* put in the data  */
    new_node->data  = new_data;

    /* link the old list off the new node */
    new_node->down = (*head_ref);

    /* move the head to point to the new node */
    (*head_ref)    = new_node;
}

/* Function to print nodes in the flattened linked list */
void printList(Node *node)
{
    while(node != NULL)
    {
        printf("%d ", node->data);
        node = node->down;
    }
}

// A utility function to merge two sorted linked lists
Node* merge( Node* a, Node* b )
{
    // If first list is empty, the second list is result
    if (a == NULL)
        return b;

    // If second list is empty, the second list is result
    if (b == NULL)
        return a;

    // Compare the data members of head nodes of both lists
    // and put the smaller one in result
    Node* result;
    if( a->data < b->data )
    {
        result = a;
        result->down = merge( a->down, b );
    }
    else
    {
        result = b;
        result->down = merge( a, b->down );
    }

    return result;
}

// The main function that flattens a given linked list
Node* flatten (Node* root)
{
    // Base cases
    if ( root == NULL || root->right == NULL )
        return root;

    // Merge this list with the list on right side
    return merge( root, flatten(root->right) );
}

// Driver program to test above functions
int main()
{
    Node* root = NULL;

    /* Let us create the following linked list
       5 -> 10 -> 19 -> 28
       |    |     |     |
       V    V     V     V
       7    20    22    35
       |          |     |
       V          V     V
       8          50    40
       |                |
       V                V
       30               45
    */
    push( &root, 30 );
    push( &root, 8 );
    push( &root, 7 );
    push( &root, 5 );

    push( &( root->right ), 20 );
    push( &( root->right ), 10 );

    push( &( root->right->right ), 50 );
    push( &( root->right->right ), 22 );
    push( &( root->right->right ), 19 );

    push( &( root->right->right->right ), 45 );
    push( &( root->right->right->right ), 40 );
    push( &( root->right->right->right ), 35 );
    push( &( root->right->right->right ), 20 );

    // Let us flatten the list
    root = flatten(root);

    // Let us print the flatened linked list
    printList(root);

    return 0;
}

我的问题是,在合并列表时,NULL指针永远不会在结果链接列表的末尾附加,所以当我们调用printList()时,程序不应该崩溃,因为链接列表不会最后有一个NULL?

2 个答案:

答案 0 :(得分:1)

没有。这段代码看起来相当不错。

让我们这样看待它。我们知道每个Node对象都是有效的。两个列表中的最后一个列表中的最后一个列表为last->down == NULL。当我们执行merge()时,我们永远不会更改新last->down的值,因此它会保留正确的NULL值。

为了更清楚一点,我们只在有两个节点时更改node->down的值,并且每次只更改其中一个节点。所以merge()的最后一次迭代,我们将传递一个指向节点的指针,以及一个指向NULL的指针。在这种情况下,我们将单独保留最终节点(并且它必须指向NULL,或者指向最终指向NULL的元素链)。

答案 1 :(得分:0)

merge函数预先检测到NULL指针:

if (a == NULL)
    return b;
if (b == NULL)
    return a;

在递归调用merge()时分配这些返回值:

result->down = merge( a->down, b );
…
result->down = merge( a, b->down );

flatten()函数担心使用right指针。但是,AFAICS,没有重置正确的指针。 printList()函数不会查看它们,但如果您使用正确的指针进行打印,那么您会发现行为中存在一些怪癖。试试这个经过修改的printList()

void printList(Node *node)
{
    while(node != NULL)
    {
        printf(" %d", node->data);
        if (node->right != NULL)
        {
            putchar('[');
            printList(node->right);
            putchar(']');
        }
        node = node->down;
    }
    putchar('\n');
}

输出结果为:

 5[ 10[ 19[ 20 20 22 30 35 40 45 50
] 20 20 22 30 35 40 45 50
] 19[ 20 20 22 30 35 40 45 50
] 20 20 22 30 35 40 45 50
] 7 8 10[ 19[ 20 20 22 30 35 40 45 50
] 20 20 22 30 35 40 45 50
] 19[ 20 20 22 30 35 40 45 50
] 20 20 22 30 35 40 45 50

所以,代码并不完美,但没有 - 我不希望它崩溃。