在链表中交换元素

Swapping elements inside linked list

本文关键字:元素 交换 链表      更新时间:2023-10-16

>我有一个链表,

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在本例中将保持为空);

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

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 

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

使用指向指针的指针将简化逻辑,并且在交换 (*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);