[算法与数据结构]-反转链表

230 阅读3分钟

如下链表:

1->2->3->4->5->Null

将其反转:

5->4->3->2->1->Null

其实这种单一直链,我们可以想象成它是一串珠子,每个珠子有它自己的标签,现实生活中,我们要将一串珠子给他换个次序,那么主要就需要做两个步骤:1、解链 2、串链

解链

现实生活中一串珠子,我们要解链的话,就比较直接明了,直接将它全部断开,变成一个珠子一个珠子,而后再重新串联就好,同样的,在计算机中操作,我们也需要将其断开,只是在断开的过程中并没有这么粗暴,需要一步一步进行;

串链

解链的操作完成之后,就需要给它排号顺序,然后一个珠子一个珠子连起来,如5珠子的下一个珠子就是4珠子;

链表的操作无非就是以上两种步骤,只是在代码层面上,无法如此直观明了的进行; 因此我们的程序就相当于是一个解链串链的一个盒子工具,不同的盒子工具有不同的作用,那么我们的反转链表盒子工具,内部的构造究竟是怎样的呢?

迭代反转盒子

顾名思义,迭代反转盒子,就是通过常用的迭代反式去进行处理的如

  • for
  • while

在这里使用while的操作:

function reverseList(head) {
  if(!head) {
    return null;
  }
  let cur = head, pre = null;
  while(cur) {
    let next = cur;
    cur.next = pre;
    pre = cur;
    cur = next;
  }
  return pre;
}

代码非常简短,里面完全体现了解链以及串链的动作; 让咱们来一步一步来对代码进行分析:

首先得确认这串项链是否有珠子,如果连珠子都没有,那就没有必要去进行解链串链操作了

if(!head) return null;

确认了当前这串项链是有珠子的,可以进入我们的解链串链的盒子工具了,首先这个盒子会先准备一个新的项链结束的tag标签null,而解链串链工具盒则定位在项链的第一个珠子,开始动工

let cur = head, pre = null;

解链串链开始工作 这个迭代就像一个流水线工作一样,都是重复的步骤
1、先将cur珠子1解下来,用next拿到后续的项链2->3->4->5->Null
2、将cur珠子1与项链尾pre串起来,得到1条新的项链1->Null
3、cur珠子1取下来了,那么需要解链工具盒将该项链再弹入一点,而串链工具盒就将新的项链弹出1个\

上述步骤如下图 cur珠子1拿下来,珠子2变成了解链工具箱cur珠子 cur珠子1串到新的项链上,因而串链工具箱中的pre珠子变成了1 \

while(cur) {
    let next = cur.next; //next: 2->3->4->5->Null
    cur.next = pre;   //cur: 1->Null
    pre = cur; // pre: 1->Null
    cur = next; // cur: 2->3->4->5->Null
}

上述这段代码表示的其实就是上面两幅图所展示的操作
后续就到3珠子,4,5然而到了Null的标志的时候,其实它不算是一个珠子,所以解链工具盒识别到了该珠子,结束工作,而串链工具盒就将3,4,5依次的串接到新的项链上,且将pre的标签往前打,最后解链工具盒告知串链工具盒没有新珠子串给你了,因此串链工具盒也结束工作,那么得到的新的项链,刚好它的项链头就是pre标记的珠子,所以整条项链完成反转
因此返回return pre,串链工具盒将整条项链吐出来,我们就拿到了反转后的项链了。

结尾

总结一下,链表的操作其实就是解链串链的操作,关键在于如何解,如何串

第一次写文章,如有问题,请指正,非常感谢您的阅读