将节点移动到单链表的开头

时间:2014-06-16 20:32:18

标签: algorithm sorting linked-list pascal quicksort

在Pascal中,当我有一个单独链接的列表,其节点定义如下,

pNode = ^Node;
Node = record
    data : data;
    next : pNode;
end;

当我像这样遍历列表时

while y<>z do begin
        if y^.data < x^.data then begin
          { HERE I WOULD LIKE TO MOVE y IN FRONT OF X }
        end;
        y:=y^.next;
end;

其中x是枢轴(列表的开头),y是'index',z是列表的尾部(结束)(是的,我试图在单链表上执行快速排序)。我如何完成评论中的任务?

我制定了程序insertAfter

procedure List.insertAfter(n : pNode; var what : data);
var newn : pNode;
begin
  new(newn);
  newn^.data := what;
  newn^.next := n^.next;
  n^.next := newn;
end;

insertInstead

procedure List.insertInstead(n : pNode; var what : data);
begin
    List.insterAfter(n, n^.data);
    n^.data:=what;
end;

,同样deleteAfter(n : pNode)

procedure List.deleteAfter(n : pNode);
var q : pNode;
begin
    q := n^.next;
    n^.next := n^.next^.next;
    dispose(q);
end;

delete(n : pNode)

procedure List.delete(n : pNode);
begin
    if n^.next <> tail then begin
        n^.data := n^.next^.data;
        deleteAfter(n);
    end
    else begin
        dispose(tail);
        tail:=n;
        tail^.next := nil;
    end;
end;

现在当我放入迭代时,而不是评论

list.insertInstead(x,y^.data);
list.delete(y);

,它不起作用,大概是因为y^.next现在没有指向与移动前相同的节点。

所以问题是:如何将节点移动到开头,y^.next仍然指向同一个节点?

PS:我已经尝试过显而易见的:使用和辅助变量来存储移动前y的实际值,但它似乎随y一起变化。

以下是原始代码:StackListQuicksort

2 个答案:

答案 0 :(得分:2)

也许最简单的方法就是改变(交换)节点的值。

{ HERE I WOULD LIKE TO MOVE y IN FRONT OF X }
tmp := x^.data
x^.data := y^.data
y^data := tmp

更新:以下是类似的答案:https://stackoverflow.com/a/1536046/2490538

Zdravím。

答案 1 :(得分:1)

我想我可能会看到这个问题。插入代码的第一行

 list.insertInstead(x,y^.data);

工作正常。它在x之后立即放置一个新节点并用y的数据填充它(所以你现在有效地在节点x之后有一个节点y的副本。

但我不认为第二行

 list.delete(y);

做你想要的。它确实从列表中“删除”节点y(如您所愿),但是通过将数据从y后面的节点移动到y的位置并删除该节点来实现。所以现在y.next指向原始y之后的节点之后的节点。也许图表会有所帮助。

在list.delete(y)之​​前

 node:     ... - y - a - b - c - ... - z
 data:     ... - Y - A - B - C - ... - Z
                     ^ 
                     y.next points here (data is A)

list.delete(y)之​​后

 node:     ... - y - b - c - ... - z
 data:     ... - A - B - C - ... - Z
                     ^ 
                     y.next points here (data is B)
                 ^
                 y points here (data is A)

所以,如果你在行中增加y

 y:=y^.next;

在你的迭代循环中你会错过测试数据A.你可以通过删除y:= y ^ .next来解决这个问题。线。但是,行

中的while循环仍然存在问题
 while y<>z do begin

因为指向节点y的指针不再改变(因为你删除了y:= y ^ .next),y将永远不会等于z。最简单(但可能不是最优雅)的解决方法可能是用

替换该行
 while y^.next <>z do begin

并添加最后一个案例以测试最后一个节点。

主循环看起来像(没有测试):

 while y^.next <> z do begin
         if y^.data < x^.data then begin
                 list.insertInstead(x,y^.data);
                 list.delete(y);
         end;
 end;
 if y^.data < x^.data then begin
         list.insertInstead(x,y^.data);
         list.delete(y);
 end;

或者,通过定义新程序

 procedure list.moveiflessthan(x,y : pnode);
 begin
      if y^.data < x^.data then begin
              list.insertInstead(x,y^.data);
              list.delete(y);
      end;
 end;

你得到了

 while y^.next <> z do
         if y^.data < x^.data then 
                 list.moveiflessthan(x,y);
 if y^.data < x^.data then
         list.moveiflessthan(x,y);

如果你到达列表的末尾(我还没有检查),可能仍然会出现最终结果错误,但我相信你可以解决这个问题......