1. 程式人生 > >快速找到未知長度單鏈表的中間節點

快速找到未知長度單鏈表的中間節點

變量 div ride span 一個 ima list 方法 .com

在討論之前,我們首先首先要明白,什麽是單鏈表?

單鏈表:鏈接方式存儲的線性表

單鏈表的結點結構
┌──┬──┐
│data│next│
└──┴──┘
 data域--存放結點值的數據域
 next域--存放結點的直接後繼的地址(位置)的指針域(鏈域)
註意:
  ①鏈表通過每個結點的鏈域將線性表的n個結點按其邏輯順序鏈接在一起的。
 ②每個結點只有一個鏈域的鏈表稱為單鏈表(Single Linked List)。

那麽我們先用java設計一下我們的單鏈表

public class MyLinkedList<E> {
    Node<E> first;
    
Node<E> last; public MyLinkedList() { super(); } public void add(E e) { if (first == null) { first = new Node<E>(e, null); } else { if (last == null) { last = new Node<E>(e, null); first.next
= last;// 因為first和last還沒建立關系,所以在這裏要將他們的關系建立起來 } else { Node<E> n = new Node<>(e, null);// 一個臨時的引用n last.next = n;// 將last的next賦值為n的引用 last = n;// 然後再將last重新賦值為n的引用 } } } @Override public String toString() { StringBuilder sb
= new StringBuilder(); sb.append("["); for (Node<E> n = first; n != null; n = n.next) { sb.append(n.item).append(","); } sb.deleteCharAt(sb.length()-1).append("]"); return sb.toString(); } private static class Node<E> { E item; Node<E> next; Node(E element, Node<E> next) { this.item = element; this.next = next; } } }

註意了,在這裏我設計的單鏈表僅僅是為了符合我們討論的問題,並不是完整的單鏈表,同時為了測試,我重寫了toString方法。在這個單鏈表裏面,我並沒有實現List<E>這個接口,因為要實現的方法太多了,而且first和last這兩個成員變量沒有用private修飾符修飾,是不符合封裝的思想,這裏我一切從簡。

我們先往裏面添加一些數值,順便測試下我們設計的單鏈表是否可以

public static void main(String[] args){
        MyLinkedList<Integer> list=new MyLinkedList<>();
        list.add(2);
        list.add(1);
        list.add(5);
        list.add(8);
        list.add(7);
        System.out.println(list.toString());
    }

運行結果:

技術分享

沒錯,我們設計的單鏈表沒問題

①快慢指針:一個指針每次按著順序跳兩次,而另一個指針只跳一次,當第一個指針跳到的元素為空是,那麽第二個指針就處於中間的位置

/**
     * 獲取中間元素
     * 
     * @return
     */
    public E getMiddle() {
        Node<E> n1 = first;// 每次只走一步,慢指針
        Node<E> n2 = first;// 每次走兩步,快指針
        
        L: while (true) {
            if (n2.next != null && n2.next.next != null) {
                n1 = n1.next;
                n2 = n2.next.next;
            } else {
                break L;
            }
        }
        return n1.item;
    }

將上面的代碼添加到MyLinkedList.java裏面,測試

public static void main(String[] args){
        MyLinkedList<Integer> list=new MyLinkedList<>();
        list.add(2);
        list.add(1);
        list.add(5);
        list.add(8);
        list.add(7);
        System.out.println(list.toString());
        System.out.println(list.getMiddle());
    }

結果如下:

技術分享

快速找到未知長度單鏈表的中間節點