鏈表習題精講01

問題一

  • 如何使用一個高效的存儲結構來改進雙向鏈表
  • 答:使用LinkedList,即異或鏈表,此數據結構的ADT如下
public class LinkdedNode{
   int data;
   LinkedNode pridiff;
}

本結構的神奇之處在於它改進了雙向列表,不需要再額外的有一個空間,用來單獨存儲前置節點和後置節點的位置
在這裏插入圖片描述

  • 具體證明過程如下
    對於任意的鏈表
    在這裏插入圖片描述

  • 存在:
    A的next = NULL XOR B
    B的next = A XOR C
    C的next = B XOR D
    證明方法如下,
    已知:在這裏插入圖片描述
    固存在當我們想要移動 B節點的時候
    如果想要向前移動
    則有(A XOR C)XOR C = A
    如果想要向後移動
    則有 (A XOR C)XOR A = C

  • 疑問:我B要想要向前移動,如何獲取C的值呢?

  • 答:這裏需要做一步異或,因爲我們已經移動到了B因此我們一定知道B的前繼節點的地址,因此纔可以知道下一個C的地址

java代碼實現:
暫無,困於兩地址的異或操作

問題二:找到鏈表的倒數第n個節點

package day04;


/**
 * @author 海綿寶寶
 * @create 2019- 10- 20 17:14
 **/
public class list {
    public static class ListNode{
        private int data;
        //設置私有成員變量 Data
        private ListNode next;
        //設置私有嚇一跳的指針
        public ListNode(int data){
            this.data = data;
        }
        public void setData(int data){
            this.data = data;
        }
        public int getData(){
            return this.data;
        }
        public void setNext(ListNode next){
            this.next = next;
        }
        public ListNode getNext(){
            return this.next;
        }
        //以上爲簡單的增刪更新

        int ListLength(){
            int length = 0;
            ListNode currentNode = this;
            while (currentNode!=null){
                currentNode=currentNode.getNext();
                length++;
            }
            return  length;
        }

        ListNode InsertInLinkedList(ListNode headNode,ListNode nodeToInsert,int position){
            if (headNode == null){
                return nodeToInsert;
            }
            if (position==1){
                headNode.setNext(nodeToInsert);
                return headNode;
            }
            else
            {
                ListNode previousNode = headNode;
                int count =0;
                while (count<=position-1){
                    previousNode=previousNode.getNext();
                    count++;
                }
                ListNode currenNode = previousNode.getNext();
                nodeToInsert.setNext(currenNode);
                previousNode.setNext(nodeToInsert);

            }
            return headNode;
        }

        ListNode addlist(int data,ListNode headNode){
            ListNode listNode = new ListNode(data);
            headNode = headNode.InsertInLinkedList(headNode, listNode, listNode.ListLength());
            return headNode;
        }

        ListNode deletelist(ListNode headNode){
            return null;
        }//JAVA中會自動實現這一部分
        ListNode DeleteNodeFromLinkedList(ListNode headNode,int position){
            if (headNode==null)return null;
            if (position<1||position>headNode.ListLength()){
                System.out.println("error,The location you entered is out limit.");
            }
            if (position==1){
                ListNode currentlist = headNode.getNext();
                headNode=null;
                return currentlist;
            }
            else{
                ListNode previousnode = headNode;
                int count = 1;
                while (count<position){
                    previousnode = previousnode.getNext();
                    count++;
                }
                ListNode currentNode = previousnode.getNext();
                previousnode.setNext(currentNode.getNext());
                currentNode = null;

            }
            return headNode;
        }
        public void add(int data){
            ListNode currentNode = new ListNode(data);
            ListNode node = this;
            while (node.getNext()!=null){
                node = node.getNext();
            }
            node.setNext(currentNode);
        }
    }

        public static void PrintList(ListNode headNode){
            while (headNode!=null){
                System.out.print(headNode.getData()+" ");
                headNode= headNode.getNext();
            }
            System.out.println();
        }
    public static void main(String[] args) {
        ListNode listNode = new ListNode(-1);
//        listNode.setData(3);
        for (int i = 0; i < 19; i++) {
            listNode.add(i);
        }
        
        
        
        
        //PrintList(listNode);
    }
}

爲了方便各位讀者學習,因此直接給出相關的已經實現好的數據結構和部分方法供大家學習

方法一:

//method01
    //a stupid method不是很想實現它...
        public static ListNode Found_n_method_01(ListNode node, int position){
            while (node!=null){
                ListNode temp = node;
                int count = 0;
                while (temp!=null){
                    count++;
                    temp = temp.getNext();
                }
                if (count==position){
                    return node;
                }

                    node = node.getNext();
            }
            System.out.println("not found");
            return null;
        }

答題思路就是,我不斷去看從我這個節點到最後的長度是不是N,如果是的話,我們就直接return這個值。
此方法的時間複雜度爲O(n^2),空間複雜度爲O(1)
a stupid method

方法二

   //Method02
        //a normal method
        public static ListNode Found_n_method_02(ListNode node, int position){
            if (position>node.ListLength()) {
                System.out.println("not found");
                return null;
            }
            int limit = node.ListLength() - position;
            for (int i = 0; i < limit; i++) {
                node = node.getNext();
            }
            return node;
        }

答題思路就是,我們首先遍歷一遍整個列表,得到長度,之後在進行移動
此方法的時間複雜度爲O(n),空間複雜度爲O(1)
這是一種比較簡單的做法,但是·,我們能不呢個再次優化他呢

方法三—雙指針

在java中其實並沒有指針的概念,這裏只是簡單的借用一下指針的概念方便大家理解

//Method03
        //a great method
        public static ListNode Found_n_method_03(ListNode node, int position){
                ListNode fTemp = node;
                ListNode sTemp = node;
                while (position>1){
                    sTemp = sTemp.getNext();
                    position--;
                }
                while (sTemp.getNext()!=null){
                    sTemp=sTemp.getNext();
                    fTemp=fTemp.getNext();
                }
            return fTemp;

        }

具體思路就是,我首先使用一個指針指向頭部,另一個指針和它相差n-1個位置,這樣就可以保證,當最後一個指針的getNext()==null之後,頭部指針和相差n-1個位置

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