交换链表中的元素

时间:2016-05-27 14:04:38

标签: c++ linked-list

我有一个由

节点组成的链表
struct Node{
    Node(string k , string v , Node * n){
        key = k;
        val = v;
        next_hash = n;
    }
    string key;
    string val;
    Node *next_hash = NULL;
    Node *next_node = NULL;
    Node *prev_node = NULL;
};

我正在创建双链表(对于此示例,next_hash将保持为NULL);

我已经创建了一个使用。添加节点的方法。

void add(string k , string v){
    Node *tmp = new Node( k , v , NULL);
    if( first == NULL ){
        first = tmp;
        last  = tmp;
    }else{
        last -> next_node = tmp;
        tmp  -> prev_node = last;
        last              = tmp;
    }
}

我想创建一个交换节点的方法。我创建了

 void swap( string k , string l){
        size_t klucik = hashfn(k);
        size_t kluc   = hashfn(l);

        Node *one = first;
        Node *two = first;
        while( one ){
            if( one -> key == k ){
                break;
            }

            one = one -> next_hash;
        }
        while ( two ){
            if( two -> key == l ){
                break;
            }

            two  = two -> next_hash;
        }

        Node *two_temp = two -> prev_node;
        Node *two_tmp = two -> next_node;

        if( one -> prev_node){
            one -> prev_node -> next_node = two;
            two -> prev_node = one -> prev_node;
        }
        else{
            first = two;
            two -> prev_node = NULL;
        }
        if( one -> next_node){
            one -> next_node -> prev_node = two;
            two -> next_node = one -> next_node;
        }else{
            two -> next_node = NULL;
            last = one;
        }
        if( two_temp ){
            two_temp -> next_node = one;
            one -> prev_node = two_temp;
        }
        else{
            first = one;
            one -> prev_node = NULL;
        }
        if( two_tmp ){
            two_tmp-> prev_node = one;
            one -> next_node = two_tmp;
        }
        else{
            last = one;
            one -> next_node = NULL;
        }

    }

如果我交换的是不在其他节点旁边的节点,则此方法有效。 如果我这样做,它会抛出指向自身的infnte循环。

是否有任何优雅的方法可以创建通用交换方法,该方法可以计算链表中节点的所有可能位置,而不需要大量的if条件?

我试过,因为评论建议首先交换节点然后使用指针在节点内部     void swap(string k,string l){

    Node *one = first;
    Node *two = first;
    while( one ){
        if( one -> key == k ){
            break;
        }
        one = one -> next_node;
    }
    while ( two ){
        if( two -> key == l ){
            break;
        }
        two  = two -> next_node;
    }

    Node *two_temp = two -> prev_node;
    Node *two_tmp = two -> next_node;

    if( one -> prev_node)
        one -> prev_node -> next_node = two;
    else
        first = two;

    if( one -> next_node)
        one -> next_node -> prev_node = two;
    else
        last = two;

    if( two -> prev_node )
        two -> prev_node -> next_node = one;
    else
        first = one;

    if( two -> next_node )
        two -> next_node -> prev_node = one;
    else
        last = one;

    if( one -> next_node == two ){
        two -> next_node = one;
        two -> prev_node = one -> prev_node;
        one -> next_node = two_tmp;
        one -> prev_node = two_temp;
    }
    else if(one -> prev_node == two ){
            two -> next_node = one -> next_node;
            two -> prev_node = one;
            one -> next_node = two;
            one -> prev_node = two_temp;
    }
    else{
        two -> next_node = one -> next_node;
        two -> prev_node = one -> prev_node;
        one -> next_node = two_tmp;
        one -> prev_node = two_temp;
    }
}

使用此测试数据

one.add("one","1");
one.add("two","2");
one.add("three","3");
one.add("four","4");
one.swap("one","two");
one.print(); // outputs 2 1 3 4
cout << " ============ " << endl;
one.swap("three","two");
one.print(); // outputs 2 4 

我似乎无法找到交换节点的正确方法。

1 个答案:

答案 0 :(得分:1)

使用指针指针将简化逻辑,并且在交换(* p ...,* p ...)期间不会改变它们。交换了内容(指向节点的指针),但没有交换指针的指针。

Node **pnpone;   // ptr to next ptr to one
Node **pppone;   // ptr to prev ptr to one
Node **pnptwo;   // ptr to next ptr to two
Node **ppptwo;   // ptr to prev ptr to two
// ...
    if(one->prev_node)
        pnpone = &(one->prev_node->next_node);
    else
        pnpone = &first;
    if(one->next_node)
        pppone = &(one->next_node->prev_node);
    else
        pppone = &last;
    if(two->prev_node)
        pnptwo = &(two->prev_node->next_node);
    else
        pnptwo = &first;
    if(two->next_node)
        ppptwo = &(two->next_node->prev_node);
    else
        ppptwo = &last;
    std::swap(*pnpone, *pnptwo);
    std::swap(*pppone, *ppptwo);
    std::swap(one->prev_node, two->prev_node);
    std::swap(one->next_node, two->next_node);