數據結構之鏈表應用

1.單鏈表LRU算法

package linked.singlelist;

import java.util.Scanner;
/**
 * 基於單鏈表LRU算法(java)
 */
public class LRUBaseLinkedList<T> {
    /**
     * 默認鏈表容量
     */
    private final static Integer DEFAULT_CAPACITY = 10;

    /**
     * 頭結點
     */
    private SNode<T> headNode;

    /**
     * 鏈表長度
     */
    private Integer length;

    /**
     * 鏈表容量
     */
    private Integer capacity;

    public LRUBaseLinkedList() {
        this.headNode = new SNode<>();
        this.capacity = DEFAULT_CAPACITY;
        this.length = 0;
    }

    public LRUBaseLinkedList(Integer capacity) {
        this.headNode = new SNode<>();
        this.capacity = capacity;
        this.length = 0;
    }

    public void add(T data) {
        SNode preNode = findPreNode(data);

        // 鏈表中存在,刪除原數據,再插入到鏈表的頭部
        if (preNode != null) {
            deleteElemOptim(preNode);
            intsertElemAtBegin(data);
        } else {
            if (length >= this.capacity) {
                //刪除尾結點
                deleteElemAtEnd();
            }
            intsertElemAtBegin(data);
        }
    }

    /**
     * 刪除preNode結點下一個元素
     *
     * @param preNode
     */
    private void deleteElemOptim(SNode preNode) {
        SNode temp = preNode.getNext();
        preNode.setNext(temp.getNext());
        temp = null;
        length--;
    }

    /**
     * 鏈表頭部插入節點
     *
     * @param data
     */
    private void intsertElemAtBegin(T data) {
        SNode next = headNode.getNext();
        headNode.setNext(new SNode(data, next));
        length++;
    }

    /**
     * 獲取查找到元素的前一個結點
     *
     * @param data
     * @return
     */
    private SNode findPreNode(T data) {
        SNode node = headNode;
        while (node.getNext() != null) {
            if (data.equals(node.getNext().getElement())) {
                return node;
            }
            node = node.getNext();
        }
        return null;
    }

    /**
     * 刪除尾結點
     */
    private void deleteElemAtEnd() {
        SNode ptr = headNode;
        // 空鏈表直接返回
        if (ptr.getNext() == null) {
            return;
        }

        // 倒數第二個結點
        while (ptr.getNext().getNext() != null) {
            ptr = ptr.getNext();
        }

        SNode tmp = ptr.getNext();
        ptr.setNext(null);
        tmp = null;
        length--;
    }

    private void printAll() {
        SNode node = headNode.getNext();
        while (node != null) {
            System.out.print(node.getElement() + ",");
            node = node.getNext();
        }
        System.out.println();
    }

    public class SNode<T> {

        private T element;

        private SNode next;

        public SNode(T element) {
            this.element = element;
        }

        public SNode(T element, SNode next) {
            this.element = element;
            this.next = next;
        }

        public SNode() {
            this.next = null;
        }

        public T getElement() {
            return element;
        }

        public void setElement(T element) {
            this.element = element;
        }

        public SNode getNext() {
            return next;
        }

        public void setNext(SNode next) {
            this.next = next;
        }
    }

    public static void main(String[] args) {
        LRUBaseLinkedList list = new LRUBaseLinkedList();
        Scanner sc = new Scanner(System.in);
        while (true) {
            list.add(sc.nextInt());
            list.printAll();
        }
    }
}

2.常見鏈表操作

         * 1) 單鏈表反轉
         * 2) 鏈表中環的檢測
         * 3) 兩個有序的鏈表合併
         * 4) 刪除鏈表倒數第n個結點
         * 5) 求鏈表的中間結點

package linkedlist;
	
public class LinkedListAlgo {
		/**
		 * day07
		 * 1) 單鏈表反轉
		 * 2) 鏈表中環的檢測
		 * 3) 兩個有序的鏈表合併
		 * 4) 刪除鏈表倒數第n個結點
		 * 5) 求鏈表的中間結點
		 *
		 * Author: Zheng
		 */
	  // 單鏈表反轉
	  public static Node reverse(Node list) {
	    Node headNode = null;

	    Node previousNode = null;
	    Node currentNode = list;
	    while (currentNode != null) {
	      Node nextNode = currentNode.next;
	      if (nextNode == null) {
	        headNode = currentNode;
	      }
	      currentNode.next = previousNode;
	      previousNode = currentNode;
	      currentNode = nextNode;
	    }

	    return headNode;
	  }

	  // 檢測環
	  public static boolean checkCircle(Node list) {
	    if (list == null) return false;

	    Node fast = list.next;
	    Node slow = list;

	    while (fast != null && fast.next != null) {
	      fast = fast.next.next;
	      slow = slow.next;

	      if (slow == fast) return true;
	    }

	    return false;
	  }

	  // 有序鏈表合併
	  public static Node mergeSortedLists(Node la, Node lb) {
	    if (la == null) return lb;
	    if (lb == null) return la;

	    Node p = la;
	    Node q = lb;
	    Node head;
	    if (p.data < q.data) {
	      head = p;
	      p = p.next;
	    } else {
	      head = q;
	      q = q.next;
	    }
	    Node r = head;

	    while (p != null && q != null) {
	      if (p.data < q.data) {
	        r.next = p;
	        p = p.next;
	      } else {
	        r.next = q;
	        q = q.next;
	      }
	      r = r.next;
	    }

	    if (p != null) {
	      r.next = p;
	    } else {
	      r.next = q;
	    }

	    return head;
	  }

	  // 刪除倒數第K個結點
	  public static Node deleteLastKth(Node list, int k) {
	    Node fast = list;
	    int i = 1;
	    while (fast != null && i < k) {
	      fast = fast.next;
	      ++i;
	    }

	    if (fast == null) return list;

	    Node slow = list;
	    Node prev = null;
	    while (fast.next != null) {
	      fast = fast.next;
	      prev = slow;
	      slow = slow.next;
	    }

	    if (prev == null) {
	      list = list.next;
	    } else {
	      prev.next = prev.next.next;
	    }
	    return list;
	  }

	  // 求中間結點
	  public static Node findMiddleNode(Node list) {
	    if (list == null) return null;

	    Node fast = list;
	    Node slow = list;

	    while (fast.next != null && fast.next.next != null) {
	      fast = fast.next.next;
	      slow = slow.next;
	    }

	    return slow;
	  }

	  public static void printAll(Node list) {
	    Node p = list;
	    while (p != null) {
	      System.out.print(p.data + " ");
	      p = p.next;
	    }
	    System.out.println();
	  }

	  public static Node createNode(int value) {
	    return new Node(value, null);
	  }

	  public static class Node {
	    private int data;
	    private Node next;

	    public Node(int data, Node next) {
	      this.data = data;
	      this.next = next;
	    }

	    public int getData() {
	      return data;
	    }
	  }

	
}

3.單鏈表結構常見操作及判斷字符串是否是迴文

package linkedlist;
/**
 * 1)單鏈表的插入、刪除、查找操作;
 * 2)鏈表中存儲的是int類型的數據;
 *
 * Author:Zheng
 */
public class SinglyLinkedList {
	private Node head = null;

    public Node findByValue(int value) {
        Node p = head;
        while (p != null && p.data != value) {
            p = p.next;
        }

        return p;
    }

    public Node findByIndex(int index) {
        Node p = head;
        int pos = 0;
        while (p != null && pos != index) {
            p = p.next;
            ++pos;
        }

        return p;
    }

    //無頭結點
    //表頭部插入
    //這種操作將於輸入的順序相反,逆序
    public void insertToHead(int value) {
        Node newNode = new Node(value, null);
        insertToHead(newNode);
    }

    public void insertToHead(Node newNode) {
        if (head == null) {
            head = newNode;
        } else {
            newNode.next = head;
            head = newNode;
        }
    }

    //順序插入
    //鏈表尾部插入
    public void insertTail(int value){

        Node newNode = new Node(value, null);
        //空鏈表,可以插入新節點作爲head,也可以不操作
        if (head == null){
            head = newNode;

        }else{
            Node q = head;
            while(q.next != null){
                q = q.next;
            }
            newNode.next = q.next;
            q.next = newNode;
        }
    }
    public void insertAfter(Node p, int value) {
        Node newNode = new Node(value, null);
        insertAfter(p, newNode);
    }

    public void insertAfter(Node p, Node newNode) {
        if (p == null) return;

        newNode.next = p.next;
        p.next = newNode;
    }

    public void insertBefore(Node p, int value) {
        Node newNode = new Node(value, null);
        insertBefore(p, newNode);
    }

    public void insertBefore(Node p, Node newNode) {
        if (p == null) return;
        if (head == p) {
            insertToHead(newNode);
            return;
        }

        Node q = head;
        while (q != null && q.next != p) {
            q = q.next;
        }

        if (q == null) {
            return;
        }

        newNode.next = p;
        q.next = newNode;

    }

    public void deleteByNode(Node p) {
        if (p == null || head == null) return;

        if (p == head) {
            head = head.next;
            return;
        }

        Node q = head;
        while (q != null && q.next != p) {
            q = q.next;
        }

        if (q == null) {
            return;
        }

        q.next = q.next.next;
    }

    public void deleteByValue(int value) {
        if (head == null) return;

        Node p = head;
        Node q = null;
        while (p != null && p.data != value) {
            q = p;
            p = p.next;
        }

        if (p == null) return;

        if (q == null) {
            head = head.next;
        } else {
            q.next = q.next.next;
        }

        // 可重複刪除指定value的代碼
        /*
           if (head != null && head.data == value) {
           head = head.next;
           }
           Node pNode = head;
           while (pNode != null) {
           if (pNode.next.data == data) {
           pNode.next = pNode.next.next;
           continue;
           }
           pNode = pNode.next;
           }
         */
    }

    public void printAll() {
        Node p = head;
        while (p != null) {
            System.out.print(p.data + " ");
            p = p.next;
        }
        System.out.println();
    }

    //判斷true or false
    public boolean TFResult(Node left, Node right){
        Node l = left;
        Node r = right;

        System.out.println("left_:"+l.data);
        System.out.println("right_:"+r.data);
        while(l != null && r != null){
           if (l.data == r.data){
               l = l.next;
               r = r.next;
               continue;
           }else{
               break;
           }

        }

        System.out.println("什麼結果");
        if (l==null && r==null){
           System.out.println("什麼結果");
           return true;
        }else{
           return false;
        }
    }
    // 判斷是否爲迴文 

    public boolean palindrome(){
       if (head == null){
           return false;
       }else{
           System.out.println("開始執行找到中間節點");
           Node p = head;
           Node q = head;
           if (p.next == null){
               System.out.println("只有一個元素");
               return true;
           }
           while( q.next != null && q.next.next != null){
               p = p.next;
               q = q.next.next;

           }

           System.out.println("中間節點" + p.data);
           System.out.println("開始執行奇數節點的迴文判斷");
           Node leftLink = null;
           Node rightLink = null;
           if(q.next == null){
               // p 一定爲整個鏈表的中點,且節點數目爲奇數
               rightLink = p.next;
               leftLink = inverseLinkList(p).next;
               System.out.println("左邊第一個節點"+leftLink.data);
               System.out.println("右邊第一個節點"+rightLink.data);

           }else{
               //p q 均爲中點
               rightLink = p.next;
               leftLink = inverseLinkList(p);
           }
           return TFResult(leftLink, rightLink);

       }
    }

    //帶結點的鏈表翻轉
    public Node inverseLinkList_head(Node p){
        // Head 爲新建的一個頭結點
        Node Head = new Node(9999,null);
        // p 爲原來整個鏈表的頭結點,現在Head指向 整個鏈表
        Head.next = p;
        /*
        帶頭結點的鏈表翻轉等價於
        從第二個元素開始重新頭插法建立鏈表
        */
        Node Cur = p.next;
        p.next = null;
        Node next = null;

        while(Cur != null){
            next = Cur.next;
            Cur.next = Head.next;
            Head.next = Cur;
            System.out.println("first " + Head.data);

            Cur = next;
        }

        // 返回左半部分的中點之前的那個節點
        // 從此處開始同步像兩邊比較
        return Head;

    }

    //無頭結點的鏈表翻轉
    public Node inverseLinkList(Node p){

        Node pre = null;
        Node r = head;
        System.out.println("z---" + r.data);
        Node next= null;
        while(r !=p){
            next = r.next;

            r.next = pre;
            pre = r;
            r = next;
        }

        r.next = pre;
        // 返回左半部分的中點之前的那個節點
        // 從此處開始同步像兩邊比較
        return r;

    }
    
    public static Node createNode(int value) {
        return new Node(value, null);
    }

    public static class Node {
        private int data;
        private Node next;

        public Node(int data, Node next) {
            this.data = data;
            this.next = next;
        }

        public int getData() {
            return data;
        }
    }
    public static void main(String[]args){

        SinglyLinkedList link = new SinglyLinkedList(); 
        System.out.println("hello");
        //int data[] = {1};
        //int data[] = {1,2};
        //int data[] = {1,2,3,1};
        //int data[] = {1,2,5};
        //int data[] = {1,2,2,1};
       // int data[] = {1,2,5,2,1};
        int data[] = {1,2,5,3,1};

        for(int i =0; i < data.length; i++){
            //link.insertToHead(data[i]);
            link.insertTail(data[i]);
        }
       // link.printAll();
       // Node p = link.inverseLinkList_head(link.head);
       // while(p != null){
       //     System.out.println("aa"+p.data);
       //     p = p.next;
       // }

        System.out.println("打印原始:");
        link.printAll();
        if (link.palindrome()){
            System.out.println("迴文");
        }else{
            System.out.println("不是迴文");
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章