在C#中交换双向链表中的节点

时间:2017-09-02 11:36:47

标签: c# doubly-linked-list

我正在尝试使用冒泡排序对双向链表进行排序。我自己编写了双链表。节点包含四个值(firstName,lastName,Id和department)。

以下是我尝试用来对列表进行排序的方法(我正在使用Windows窗体并从表单中调用sortList方法)。

K和I是doubleLinkedList类的节点。

public DoubleLinkedList sortList(ref DoubleLinkedList toSort)
{
  for (toSort.K = toSort.First; toSort.K != endOfTheList(toSort.First); toSort.K = toSort.K.NextLink)
  {
    for(toSort.I = toSort.K.NextLink; toSort.I != endOfTheList(toSort.First); toSort.I = toSort.I.NextLink)
    {
      if (string.Compare(toSort.K.Department, toSort.I.Department) > 0)
      {
        MessageBox.Show(toSort.ToString());
        swap( toSort, toSort.K, toSort.I);
      }
    }
  }

  MessageBox.Show("List is sorted");
  MessageBox.Show(this.ToString());
  return toSort;
}

public void swap(DoubleLinkedList swapList, Node _k, Node _i)
{
    MessageBox.Show("Swapping " + swapList.K.ToString() + "for" + swapList.I.ToString());

    Node temp = _k;
    swapList.K = _i;
    swapList.I = temp;
    MessageBox.Show(swapList.K.ToString() + swapList.I.ToString());
    MessageBox.Show(swapList.ToString());
}

第二个消息框显示节点K和节点I的firstName,lastName,Id和部门已在方法中交换,但它们实际上没有交换双链接列表。

如果有人可以就如何更改这些方法以实际交换列表中的值给我建议,那将非常感激。我在网上找到了例子,但他们使用的是LinkedList<>类,我真的很想使用自己的类。

作为一个例子:Node K = Michelle Sellers,No12,Sales                    节点I = Nick Hodges,No22,Accounts

在交换方法之后,K = Nick Hodges,No22,Accounts和I = Michelle Sellers,No12,Sales,但在实际列表中,节点不会被交换。

1 个答案:

答案 0 :(得分:0)

交换彼此相邻的节点

由于您使用BubbleSort,我将假设您要交换的两个节点彼此相邻。这是一个假设:如果这不成立;问题更复杂。

假设您有一个双重链接列表,如下所示:

First                      Last
|                          |
v                          v
+---+ -> +---+ -> +---+ -> +---+
| 1 |    | 4 |    | 2 |    | 5 |
+---+ <- +---+ <- +---+ <- +---+

-><-指向NextLinkPrevLink的链接。现在我们希望用42交换节点,然后列表如下:

First                      Last
|                          |
v                          v
+---+ -> +---+ -> +---+ -> +---+
| 1 |    | 2 |    | 4 |    | 5 |
+---+ <- +---+ <- +---+ <- +---+

所以现在我们应该问自己:“发生了什么变化”:我们看到了很多变化:

  • 节点1的NextNode现在是节点2;
  • 节点2的NextNode现在是节点4;
  • 节点4的NextNode现在是节点5;
  • 节点5的PrevNode现在是节点4;
  • 节点4的PrevNode现在是节点2;和
  • 节点2的PrevNode现在是节点1.

此外,如果要交换的节点之一是first节点或last节点,那么我们也必须更新这些指针。在这种情况下,节点4通常没有先前节点(如果节点4是start节点),或节点2没有下一个节点(如果节点2是最后一个节点)。所以有很多案例。这当然取决于链表是否引用了first和/或last节点。

所以我们可以编写一个算法:

public void swap(DoubleLinkedList swapList, Node i, Node j) {
    Node h = i.PrevNode;
    Node k = j.NextNode;
    if(swapList.First == i) {
        swapList.First = j;
    }
    if(h != null) {
        h.NextNode = j;
    }
    j.PrevNode = h;
    j.NextNode = i;
    i.PrevNode = j;
    i.NextNode = k;
    if(k != null) {
        k.PrevNode = i;
    }
    if(swapList.Last == j) {
        swapList.Last = i;
    }
}

交换两个随机节点

如果节点是随机的,问题就更严重了。在这里,我们考虑我们想要将节点b与节点f交换的场景:

     -> +---+ -> +---+ -> +---+ ->       -> +---+ -> +---+ -> +---+ ->
...     | a |    | b |    | c |     ...     | e |    | f |    | g |     ...
     <- +---+ <- +---+ <- +---+ <-       <- +---+ <- +---+ <- +---+ <- 

如果我们想将bf交换,我们将不得不:

  • a的{​​{1}}成为NextNode;
  • f的{​​{1}}成为f;
  • NextNode的{​​{1}}成为c;
  • e的{​​{1}}成为NextNode;
  • b的{​​{1}}成为b;
  • NextNode的{​​{1}}成为g;
  • c PrevNode成为f;和
  • f的{​​{1}}成为PrevNode

所以我们可以这样实现:

a