Link链表的反转

来源:互联网 发布:优酷网络电影 编辑:程序博客网 时间:2024/05/16 06:34

尊重原创,转载请标明出处   http://blog.csdn.net/abcdef314159

上一篇简单介绍了LinkedList,代码都很简单,基本上没有什么可说的,这一篇就来介绍一下链表的使用,反转链表,这个链表和LinkedList是不一样的,因为LinkedList是双向链表,不需要反转也可以从后往前遍历,这里创建的链表是单向的,只能从前往后,不能从后往前,如果想要从后往前遍历,就需要把链表反转,先创建一个节点类

public class LinkNode {    public int val;    public LinkNode next;    public LinkNode(int x) {        val = x;    }}
上面是一个节点类,下面再写一个打印的类
    public static void printLink(LinkNode mLink) {        LinkNode tempNoe = mLink;        while (tempNoe != null) {            System.out.print(tempNoe.val + "\t");            tempNoe = tempNoe.next;        }        System.out.println();    }
先来看第一个反转的方法
public static LinkNode reverseList1(LinkNode head) {//反转当前链表,prev是指前一个节点,表示已经反转好的链表,最开始的时候为nullLinkNode prev = null;while (head != null) {//这里可以认为head是当前节点,因为下面通过不停的赋值,让head始终指向当前节点,//tem是临时节点,保存的是当前节点的下一个,如果不保存,在执行head.next = prev//的时候把当前节点之后的节点都搞丢了。LinkNode tmp = head.next;//让前一个节点等于当前节点的下一个(前一个节点是已经反转好的),这个是反转的关键,//因为反转是从头结点开始的,而prev可以认为是前面几个已经反转好的节点,然后挂载在//当前节点的下一个,所以这里不停的通过white循环,然后不断的把已反转好的prev挂载到//当前节点后面,最终实现了链表的反转。head.next = prev;//挂载完之后让head等于prev节点,表示已经反转过来了,prev表示反转之后的链表prev = head;//让保存的tmp节点等于head,实际就相当于在往后挪了一位。然后在循环head = tmp;}return prev;//返回反转后的节点。}
下面初始化一下链表
    public static LinkNode initLink() {        LinkNode node1 = new LinkNode(1);        LinkNode node2 = new LinkNode(2);        LinkNode node3 = new LinkNode(3);        LinkNode node4 = new LinkNode(4);        LinkNode node5 = new LinkNode(5);        LinkNode node6 = new LinkNode(6);        node1.next = node2;        node2.next = node3;        node3.next = node4;        node4.next = node5;        node5.next = node6;        return node1;    }
在调用reverseList1方打印一下,看一下结果
123456654321
上一排是正常打印,下一排是经过反转之后的结果,实现了链表的反转,那么还有没有其他方式,继续看
    public static LinkNode reverseList2(LinkNode head) {//可以把head节点当做当前节点,如果当前节点为null,或者没有后继节点,直接返回当前节点,//因为就一个节点没法反转        if (head == null || head.next == null)            return head;//递归遍历,从当前节点的下一个节点开始,prev表示已经反转好的,所以这一步执行完之后//当前节点head之后的都已反转完成(当前节点head没有反转)        LinkNode prev = reverseList2(head.next);//既然head.next已经反转完成,那么head.next显然是已经反转到链表最后了,然后再让head等于head.next的下一个,//把head节点放到已经反转的链表的最后。其实每次head.next都是为null,因为在下一步把它置为null了,然后//再让head等于head.next的下一个        head.next.next = head;//然后让head.next节点为空,因为这里当前节点head是已经反转好的最后一个节点,所以可以置为null。        head.next = null;        return prev;    }
再看一下打印结果
123456654321

也实现了反转,如果不好理解可以在改一下,接着往下看

    public static LinkNode reverseList3(LinkNode head) {        if (head == null || head.next == null)            return head;//在reverseList2中可能这一点不太好理解,虽然prev是已经反转之后的列表,但是prev指向的//是表头,那怎么样才能把head添加到表尾,只能通过循环,找到最后一个。        LinkNode prev = reverseList3(head.next);        LinkNode current = prev;        while (current.next != null)            current = current.next;//找最后一个        current.next = head;//把head添加到最后一个的next中        head.next = null;        return prev;    }
接着往下看
    public static LinkNode reverseList4(LinkNode head) {//这个和reverseList1差不多        if (null == head) {            return head;        }//还是一样,pre是表示已经反转好的链表,这里的pre暂且认为他是等于head节点的,仅仅等于head这一个节点//不包含head后面的节点,暂且这样认为,虽然不对        LinkNode pre = head;        LinkNode cur = head.next;//cur认为是当前节点        LinkNode _next;//_next认为是当前节点的下一个节点        while (null != cur) {            _next = cur.next;//保存当前节点的下一个节点//pre是表达已经反转好的链表,让他等于当前链表的下一个,就是挂载在当前链表的下一个            cur.next = pre;//挂载完之后表示又反转好了一个,然后让他等于pre,因为pre就是已经反转好的链表            pre = cur;//跳到下一个链表循环,继续循环            cur = _next;        }        //将原链表的头节点的下一个节点置为null,再将反转后的头节点赋给head,这里为什么要置null,因为如果不置null,//head.next一直是有值的,这个会造成死循环,那为什么reverseList1中最后没有把head.next置为null,那是因为一开始//的时候就让head.next = prev; 而最开始prev是大于null的,其实已经把prev置为null了        head.next = null;        head = pre;//反转之后的链表赋值给head        return head;//其实上一步也可以不赋值,直接返回pre就可。    }
继续看
    public static LinkNode reverseList5(LinkNode prev, LinkNode curr) {//prev是前一个节点,表示已经反转好的链表,可以为null,如果curr是first节点,那么prev就是null,//就表示还没有排序        LinkNode next = curr.next;        if (next == null) { // 没有下个节点则停止循环。            curr.next = prev;            return curr;        }// 将反转好的节点prev赋值给当前节点的下一个,这里在第一次调用的时候prev为null,curr是头结点,//所以第一步的时候就已经把尾节点置为null了。        curr.next = prev; //这里是通过递归,不断的取出当前节点,然后在不断的让已反转好的节点挂载到当前节点中        return reverseList5(curr, next);    }
继续
    public static LinkNode reverseList6(LinkNode head) {        //cuur可以认为是当前节点        LinkNode curr = head.next;        //_next表示是当前节点curr节点的下一个节点,在下面循环中用到        LinkNode _next = curr.next;        //让头结点孤立起来,让他没有后继节点,成为孤零零的一个节点,这时我们可以认为head节点是已经反转好的节点        head.next = null;        while (_next != null) {            //让已经反转好的节点head成为当前节点的下一个,实现反转            curr.next = head;            //因为curr链表已经是反转之后的了,所以让curr等于head,head表示已经反转好的链表            head = curr;            //让下一个节点成为当前节点,然后下面循环            curr = _next;            //移动到下一个节点,继续            _next = _next.next;        }        //curr是最后一个节点,因为上面循环结束的条件是_next != null,而_next可以认为是curr的下一个节点        //当curr的下一个节点为null的时候,说明curr是尾节点,所以这里把前面已经反转好的节点挂载到最后一个节点,        //最终实现所以节点反转。        curr.next = head;        return curr;    }
继续
    public static LinkNode reverseList7(LinkNode head, LinkNode next) {        //这个和reverseList5很相似,如果下一个节点为null,直接返回        if (next == null) {            return head;        }        //head可以认为是已经反转好的,如果head节点的下一个是next,要把head节点的下一个置为null,        //否则会出现死循环,因为head暂且认为是已经反转好的,然后会挂载到next的下面,如果不置为null,        //那么相互挂载,就会出现死循环。这里要明白这一点,head的next是已经反转好的head节点的下一个,        // 不是已经反转好的最后一个        if (head.next.equals(next)) {            head.next = null;        }        if (next.next != null) {            //保存next的下一个,下面递归的时候传进去            LinkNode next2 = next.next;            //head可以认为是反转好的,直接赋值给next的下一个            next.next = head;            //递归            return reverseList7(next, next2);        }        //将反转好的head赋值给next的下一个        next.next = head;        return next;    }
接着往下看
    public static LinkNode reverseList8(LinkNode head) {        LinkNode tail = head.next;        if (tail.next != null) {            LinkNode prev = reverseList8(tail);// prev表示已经反转好的            LinkNode last = prev;            while (last.next != null)                last = last.next;//找到最后一个            last.next = head;//挂载到最后一个上            head.next = null;            return prev;        }        tail.next = head;        head.next = null;        return tail;    }
再看
    public static LinkNode reverseList9(LinkNode head) {        //这个和第一个很相似        if (head == null || head.next == null) {            return head;        }        LinkNode preNode = null;        LinkNode curNode = head;        LinkNode nextNode;        while (curNode != null) {            nextNode = curNode.next;            curNode.next = preNode;            preNode = curNode;            curNode = nextNode;        }        return preNode;    }


原创粉丝点击