簡體   English   中英

深度復制鏈接列表-O(n)

[英]Deep Copy Linked List - O(n)

我正在嘗試深層復制鏈表。 我需要一種在線性時間O(n)中執行的算法。 這就是我現在所擁有的,但是我無法弄清楚這是怎么回事。 我的應用程序崩潰了,我懷疑還無法弄清內存泄漏。 這就是我現在所擁有的

 struct node {
    struct node *next;
    struct node *ref;
 };


struct node *copy(struct node *root) {
    struct node *i, *j, *new_root = NULL;

    for (i = root, j = NULL; i; j = i, i = i->next) {
        struct node *new_node;
        if (!new_node) 
        {
            abort();
        }
        if (j) 
        {
            j->next = new_node;
        }
        else 
        {
            new_root = new_node;
        }

        new_node->ref = i->ref;
        i->ref = new_node;
    }
    if (j) 
    {
            j->next = NULL;
    }
    for (i = root, j = new_root; i; i = i->next, j = j->next)
        j->ref =i->next->ref;

      return new_root;
}

誰能指出我在這方面出了錯嗎?

僅此一塊:

    struct node *new_node;
    if (!new_node) 
    {
        abort();
    }

似乎對發生隨機abort()很有用。 new_node未分配,將包含一個隨機值。 !new_node表達式可能已經致命(在某些系統上)。

作為一般提示,您只需要1個for循環。 預先編寫一些代碼來建立new_root

但是,要進行深層復制,還需要克隆任何ref指向的對象。 在我看來,第二個循環將原始內容分配給副本。 但是我不確定ref什么?

我立即注意到的一件事是,您永遠不會為new_node分配空間。 由於不能保證自動變量會被初始化,因此new_node將被設置為該內存之前的任何值。 您可能應該從以下內容開始:

struct node *new_node = (new_node *) malloc(sizeof(struct node));

在C中,或者如果您使用的是C ++:

node* new_node = new node;

復制列表非常簡單。 但是,將ref指針指向新列表中相對於源列表的相同節點的要求將很難以任何有效的方式來實現。 首先,您需要某種方式來識別相對於它們指向源列表的節點。 您可以在每個節點中放入某種標識符,例如將int設置為在第一個節點中設置為0,在第二個節點中設置為1,依此類推。然后,在復制列表之后,您可以再次遍歷列表以進行設置ref指針。 這種方法的問題(除了向每個節點添加另一個變量之外)是,它將使算法的時間復雜度從O(n)跳到O(n ^ 2)。

這是可能的,但是需要一些工作。 我假設使用C ++,並在struct node省略struct關鍵字。

您將需要做一些記賬來跟蹤“ ref”指針。 在這里,我將它們轉換為數值索引並存儲到原始列表中,然后再將指針轉換為新列表。

node *copy_list(node const *head)
{
    // maps "ref" pointers in old list to indices
    std::map<node const *, size_t> ptr_index;
    // maps indices into new list to pointers
    std::map<size_t, node *>       index_ptr;

    size_t length = 0;
    node       *curn; // ptr into new list
    node const *curo; // ptr into old list

    node       *copy = NULL;

    for (curo = head; curo != NULL; curo = curo->next) {
        ptr_index[curo] = length;
        length++;

        // construct copy, disregarding ref for now
        curn = new node;
        curn->next = copy;
        copy = curn;
    }

    curn = copy;
    for (size_t i=0; i < length; i++, curn = curn->next)
        index_ptr[i] = curn;

    // set ref pointers in copy
    for (curo = head, curn = copy; curo != NULL; ) {
        curn->ref = index_ptr[ptr_index[curo->ref]];

        curo = curo->next;
        curn = curn->next;
    }

    return copy;
}

該算法在O( n lg n )中運行,因為它將所有n個列表元素存儲在std::map ,該元素具有O(lg n )插入和檢索復雜性。 可以通過使用哈希表來使其線性化。

注意:未經測試,可能包含錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM