經典案例-連結串列操作的幾大經典例子 單鏈表反轉 環的檢測 求中間節點 有序連結串列合併等
阿新 • • 發佈:2018-12-14
這篇博文 主要總結連結串列在應用時的幾個重要案例。學習之前,最好能夠掌握連結串列相關的一些基礎知識,以及連結串列中資料的插入、刪除操作如何實現等等,這些網上資料很多,這裡沒有做過多介紹,不熟悉的同學可以看程式碼之前簡單瞭解一下。
1.單鏈表反轉 連結串列中環的檢測 求中間節點 刪除連結串列中第n個結點 刪除連結串列中倒數第n個節點
import java.util.Scanner; /** * @author xjh 2018.10.10 * */ class Node{ //節點類 int data; Node next; Node(int data){ this.data=data; } } public class SingleLinkedeList { public static void main(String[] args) { // TODO Auto-generated method stub Scanner in=new Scanner(System.in); String t=in.nextLine(); //首先用String接收控制檯輸入的所有數字 char[] s=t.toCharArray(); //轉換為char型 Node[] node=new Node[s.length]; for(int i=0;i<s.length;i++){ node[i]=new Node(s[i]-'0'); //得到int型 存入單鏈表節點中 } for(int i=0;i<s.length;i++){ if(i==s.length-1){ //最後一個節點,指標指向空 node[i].next=null; //null為單鏈表 node[0]則為迴圈連結串列 } else node[i].next=node[i+1]; } printAll(node[0]); //首先輸出原有的連結串列順序 這裡如果時迴圈連結串列的話 則不能執行這條語句 因為會進入死迴圈 // printAll(reverse(node[0])); //輸出單鏈表反轉後的連結串列順序 System.out.println("It's CircleLinkedList ? "+CheckCircle(node[0])); System.out.println("middleNode "+middleNode(node[0]).data); int delete=3; //刪除第n個節點 // printAll(deleteNode(node[0],delete)); printAll(deleteNodeToEnd(node[0],delete)); } public static void printAll(Node head){ Node t=head; while(t!=null){ System.out.print(t.data+" "); t=t.next; } System.out.println(); } /** * 單鏈表反轉 * @param p * @return head */ public static Node reverse(Node p){ Node head=null; Node previousNode=null; //先前節點指標 Node currentNode=p; while(currentNode!=null){ //非空連結串列 Node nextNode=currentNode.next; if(nextNode==null){ //以到達最後一個節點 head=currentNode; } currentNode.next=previousNode; //指向前面一個節點(頭節點則指向null) previousNode=currentNode; currentNode=nextNode; //currentNode指向原來連結串列的下一個節點 } return head; } /** * 檢測來連結串列是否有環(迴圈連結串列) * @param p * @return */ public static boolean CheckCircle(Node p){ if(p==null) return false; Node a=p; Node b=p; while(a!=null&&a.next!=null){ //這裡利用快慢兩個指標 主要為了讓考慮如果連結串列長度特別大時,單一指標節點往後遍歷時間複雜度高 a=a.next.next; b=b.next; if(a==b) return true; } return false; } /** * 求連結串列中間節點(注意這裡的求解方法只用在單鏈表中,不適合在迴圈連結串列) * @param p * @return */ public static Node middleNode(Node p){ if(p==null) return null; Node a=p; Node b=p; while(a!=null&&a.next!=null){ //這裡利用快慢兩個指標 主要為了讓考慮如果連結串列長度特別大時,單一指標節點往後遍歷時間複雜度高 a=a.next.next; b=b.next; } return b; //b就是連結串列中間節點 } /** * 刪除連結串列中第n個結點 * @param p * @return */ public static Node deleteNode(Node p,int delete){ Node n=p; while(n!=null&&--delete>1){ n=n.next; } if(n==null) //連結串列中一共沒有n個節點,無法實現刪除操作 return p; n.next=n.next.next; //刪除指定的元素 return p; } /** * 刪除連結串列中倒數第n個節點 * 思路:首先利用一個指標p1找到第n個節點,然後另外一個指標p2從頭節點出發 兩個指標往後遍歷,p1到達尾節點時 p2剛好為倒數第n個節點 * @param p * @param delete * @return */ public static Node deleteNodeToEnd(Node p,int delete){ Node p1=p; int i=1; while(p1!=null&&i<delete){ p1=p1.next; ++i; } if(p1==null) //連結串列一共沒有n個節點,無法實現刪除操作 return p; Node p2=p; Node pre=null; while(p1.next!=null){ //往後遍歷連結串列節點 p1=p1.next; pre=p2; p2=p2.next; }//迴圈結束時 p1為尾節點,p2為倒數第n個節點 pre為倒數第n+1個節點 pre.next=pre.next.next; return p; } }
2.兩個有序連結串列的合併
import java.util.Scanner; /** * 兩個有序單鏈表的合併 * @author xjh 2018.10.10 * */ public class SingleLinkedeList2 { public static void main(String[] args) { // TODO Auto-generated method stub //首先構建兩個升序單鏈表a b int[] t1={1,3,5,7,9}; Node[] a=new Node[t1.length]; for(int i=0;i<t1.length;i++){ a[i]=new Node(t1[i]); //得到int型 存入單鏈表節點中 } for(int i=0;i<t1.length;i++){ if(i==t1.length-1){ //最後一個節點,指標指向空 a[i].next=null; //null為單鏈表 node[0]則為迴圈連結串列 } else a[i].next=a[i+1]; } int[] t2={2,4,6,8,10}; Node[]b=new Node[t2.length]; for(int i=0;i<t2.length;i++){ b[i]=new Node(t2[i]); //得到int型 存入單鏈表節點中 } for(int i=0;i<t2.length;i++){ if(i==t2.length-1){ //最後一個節點,指標指向空 b[i].next=null; //null為單鏈表 node[0]則為迴圈連結串列 } else b[i].next=b[i+1]; } printAll(MergeSort(a[0],b[0])); } public static void printAll(Node head){ Node t=head; while(t!=null){ System.out.print(t.data+" "); t=t.next; } System.out.println(); } /** * 合併兩個有序連結串列 * @param a * @param b * @return */ public static Node MergeSort(Node a,Node b){ if(a==null) return b; if(b==null) return a; Node p=a; Node q=b; Node head; //首先確定合併連結串列的頭節點 if(p.data<q.data){ head=p; p=p.next; }else{ head=q; q=q.next; } Node r=head; //兩個連結串列節點的元素依次進行比較,r指標有序連線 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; } //當某個連結串列遍歷提前結束時,r直接連線另一個為遍歷完的有序連結串列 if(p!=null){ r.next=p; }else{ r.next=q; } return head; } }