鏈表的應用--java
問題一
- 如何使用一個高效的存儲結構來改進雙向鏈表
- 答:使用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個位置