JAVA中对不带头单链表的一些操作2

1.反转单链表

反转一个点链表呢,就如下所示:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

  //反转单链表
        public Node reverseList1() {
            Node cur = this.head;
            Node prev = null;
            Node newHead = null;
            while (cur != null) {
                Node curNext = cur.next;
                if (curNext == null) {
                    newHead = cur;
                }
                cur.next = prev;
                prev = cur;
                cur = curNext;
            }
            return newHead;
        }

遇到这个问题呢,首先我们会想到去倒过来操作它,但问题是,这个单链表只有不断向后指,当我们想去将每一个结点都指向前面一个结点时,是没有办法去操作他这个前一个节点的,所以我们还是得从前往后操作。过程中呢,我们首先得想到设置三个变量prev,cur,curNext,功能分别是,反转,和追踪下一个要反转的结点。定义cur指向头节点,判断cur是不是为空,不为空进入循环,定义一个curNext让他指向cur的下一个结点,再判断它是否为空,为空就定义一个新头结点newHead让他指向cur,就是反转后的链表的头节点,否则就开始反转,让cur指向前一个结点prev,然后prevcur分别向后移,重复上述操作,直到cur为空反转完成退出循环,返回新的头节点newHead。

2.头插法反转单链表

    //头插法反转单链表
        public Node reverseList2() {
            //Node x = head.next;
            int num = this.head.data;
            Node cur = this.head.next;
            while (cur != null) {
                addFirst(cur.data);
                cur = cur.next;
            }
            Node s = this.head;
            while (s != null) {
                if (s.data == num) {
                    s.next = null;
                    return head;
                }
                s = s.next;
            }
            //  x = null;
       /*     Node u = this.head;
        while(u.next != null) {
            u = u.next;
        }
        u.next = null;*/
            return head;
        }

还有一种方法呢,就是用头插法去反转,这个代码呢是我自己写的,运行结果测试是没有问题的,如果有大佬发现问题,请及时告知小弟改正。步骤的,就是从头节点的下一个结点开始逐渐用头插法插到头节点前面,不过首先需要记下当前头节点的data数据,方便最后将此节点的next置为null,然后到所有结点都反转后,遍历链表使当前的最后一个结点的next置为空,链表就反转完了。

3.返回链表的中间结点

  //返回链表的中间节点
        public Node middleNode() {
            Node fast = this.head;
            Node slow = this.head;
            while (fast != null && fast.next != null) {
                fast = fast.next.next;
                slow = slow.next;
            }
            return slow;
        }

这种题呢,其实并不难,主要是看我们解题的思路,一般人们会去遍历一遍获取长度,一次来返回中间结点,而我们呢,可以用两个结点都先指向头节点,一个走一步,一个走两步,当走的快的那个结点为空或者他的下一个结点为空时,我们就返回当前的走慢的结点,那个循环终止条件主要是根据结点数是奇数还是偶数而变得。

4.返回倒数第K个结点

  //返回倒数第K个节点
        public Node FindKthToTail(int k) {
            if (k <= 0 || k > size()) {
                return null;
            }
            Node fast = this.head;
            Node slow = this.head;
            int i = 0;
            while (i < k - 1) {
                fast = fast.next;
                i++;
            }
            while (fast.next != null) {
                fast = fast.next;
                slow = slow.next;
            }
            return slow;
        }

这个呢,思路和上一个题思路一样,就是先让一个结点走k步,然后两个一人一步走,当前面那个结点走到最后一个结点时,返回走的慢的那个结点,此时就是倒数第K个结点。

5.以给定的x为分割线,小于x的排在大于等于x的数之前,原来数的序列保持不变

  //以给定的x为分割线,小于x的排在大于等于x的数之前,原来数的序列保持不变
        public Node partition(int x) {
            Node cur = this.head;
            Node bs = null;
            Node be = null;
            Node as = null;
            Node ae = null;
            while (cur != null) {
                if (cur.data < x) {
                    if (bs == null) {
                        be = cur;
                        bs = be;
                    } else {
                        be.next = cur;
                        be = be.next;
                    }
                }else {
                    if (cur.data >= x) {
                        if (as == null) {
                            ae = cur;
                            as = ae;
                        } else {
                            ae.next = cur;
                            ae = ae.next;
                        }
                    }

                }
                cur = cur.next;

            }

               if(bs == null) {
                   return as;
               }else {
                   be.next = as;
                   if(as!= null) {
                   ae.next = null;
                   }
                   return bs;
               }
        }
    }

这题的思路,就是先遍历一遍链表,然后与X 作比较,小于x的放在bs-be链表里,大于x的放在as-ae的链表里,放前,分别先判断两个链表是否为空,分别做相应的操作,之后,再判断,如果bs为空则返回第二个链表,即as,若不为空,则把两个链表链接,be指向as,此时在做判断,如果as不为空,则需要把aenext置为空,最后,再返回**bs,**整个表就返回了。

6.将两个已经排好序的链表从小到大排成一个新的链表

public class TestDemo {

    public static Node mergeTwoLists(Node headA, Node headB) {
        Node newHead = new Node(-1);
        Node tmp =  newHead;
        while(headA != null && headB != null) {
            if(headA.data < headB.data) {
                tmp.next = headA;
                headA = headA.next;
                tmp = tmp.next;
            }else {
                tmp.next = headB;
                headB = headB.next;
                tmp = tmp.next;
            }
        }
          if(headA != null) {
              tmp.next = headA;
          }
        if(headB != null) {
            tmp.next = headB;
        }
        //1、当两个单链表都不为空的时候

        //2、第一步完成后   其中一个单链表不为空  一个为空

        return newHead.next;
    }

我们可以重新创建一个链表,将两个链表里的值分别做好比较后放入新的链表里,新创建一个头节点,做好标记,然后创建一个结点指向该节点,当两个链表都不为空时,比较两个链表的值,将较小的放入链表中,然后各一步走,继续比较,跳出循环后,我们需要判断是哪个链表遍历完了,哪个完了,就将当前的tmp直接指向另一个链表的当前的头节点就行了,最后需要注意的是,我们需要返回的,是新头节点的下一个结点。

7.判断两个链表是否相交

 //判断两个单链表是否相交
    public static  Node getIntersectionNode(Node headA,Node headB) {
        if(headA == null || headB == null) {
            return null;
        }
        int count1 = 0;
        int count2 = 0;
        Node pL = headA;
        Node pS = headB;
        while(pL != null) {
            pL = pL.next;
            count1++;
        }
        while(pS != null) {
            pS = pS.next;
            count2++;
        }
        pL = headA;
        pS = headB;
        int len = count1-count2;
        if(len<0) {
            pL = headB;
            pS = headA;
            len = count2-count1;
        }
        while(len > 0) {
            pL =pL.next;
            len--;
        }
        while(pL!= null && pS != null && pL != pS) {
            pL = pL.next;
            pS = pS.next;
        }
        if(pL!= null  && pL == pS) {
            return pL;
        }
        return null;
    }

判断相交呢,这是个y字形的,就是遇到相同的结点后两个链表就结合成一个了,后面的完全相同,还需要注意的是,这里的判断链表是否相交,是比较的两个节点的地址是否相同,而不是他们的data,如果其中一个链表为空的话,自然是没有相交,之后,我们先让比较长的链表走和短的链表相差的步数,然后一人一步走做比较,出循环后判断,如果是因为pLpS 为空跳出的话,说明没找到相交点,直接返回null,否则是因为pL==pS的话,则找到相交点,返回这个结点。

猜你喜欢

转载自blog.csdn.net/AIJXB/article/details/105350241
今日推荐