本文根據《大話數據結構》一書,實現了Java版的單鏈表。html
每一個結點中只包含一個指針域的鏈表,稱爲單鏈表。java
單鏈表的結構如圖所示:node
單鏈表與順序存儲結構的對比:數據結構
實現程序:dom
package LinkList; /** * 說明: * 1.《大話數據結構》中沒有線性表的長度,但提到能夠存儲於頭節點的數據域中。 * 本程序的線性表長度存放於count變量中,線性表長度能夠使程序比較方便。 * 2.程序中,第i個位置表明第i個結點,頭結點屬於第0個結點 * 3.由於鏈表爲泛型,整表建立採用整型(隨機整數作元素),因此有出現一些類型轉換 * 4.Java程序的方法通常以小寫開頭,但爲和書上一致,程序中方法採用了大寫開頭。 * * 注意點: * 1.count在增刪元素時要加一或減一千萬別忘了 * 2.清空線性表要每一個元素都null * * @author Yongh * */ public class LinkList<E> { private Node<E> head; //頭結點 private int count; //線性表長度(《大話》存儲於head.data中) /** * 結點 */ private class Node<E>{ E data; Node<E> next; public Node(E data,Node<E> next){ this.data=data; this.next=next; } } /** * 線性表的初始化 */ public LinkList(){ head=new Node<E>(null, null); //不是head=null; count=0; } /** * 判斷線性表是否爲空 */ public boolean IsEmpty() { if(count==0) { System.out.println("表爲空!"); return true; }else { System.out.println("表不爲空!"); return false; } //return count==0; } /** * 清空線性表(本身編寫的) */ public void ClearList() { Node<E> node; while(count!=0) { node=head.next; head.next=node.next; node=null; count--; } System.out.println("線性表已清空!"); } /** * 清空線性表(書中改寫) */ public void ClearList2() { Node<E> q,p; q=head.next; while(q!=null) { p=q.next; q=null; q=p; count--; } head.next=null; System.out.println("線性表已清空!"); } /** * 獲取第i個結點(包括第0個結點,頭結點) * 獲取結點值只須要GetNode(i).data便可,再也不寫方法了 */ public Node<E> GetNode(int i) { if(i<0||i>count) { throw new RuntimeException("元素位置錯誤!"); }else if (i==0) { return head; }else { Node<E> node=head.next; for(int k=1;k<i;k++) { node=node.next; } return node; } } /** * 獲取第i個結點的數據(包括頭結點) */ public E GetData(int i) { return GetNode(i).data; } /** * 查找元素,0表明查找失敗 */ public int LocateElem(E e) { Node<E> node; node=head.next; if(node.data==e) return 1; for(int k=1;k<count;k++) { node=node.next; if(node.data==e) return k+1; } System.out.println("查找失敗!"); return 0; } /** * 第i個位置插入新的元素 */ public void ListInsert(int i,E e) { if(i<1||i>count+1) { throw new RuntimeException("插入位置錯誤!"); }else { Node<E> newNode=new Node<E>(e,null); newNode.next=GetNode(i-1).next; //由於GetNode()方法中包含了獲取頭結點,因此不需單獨判斷了 GetNode(i-1).next=newNode; count++; System.out.println("插入成功!"); } } /** * 刪除第i個位置元素,並返回其值 */ public E ListDelete(int i) { if(i<1||i>count) throw new RuntimeException("刪除位置錯誤!"); Node<E> node=GetNode(i); E e=node.data; GetNode(i-1).next=node.next; node=null; count--; System.out.println("刪除成功!"); return e; } /** * 獲取線性表長度 */ public int ListLength() { return count; } /** * 整表建立,頭插法 */ public LinkList<Integer> CreateListHead(int n){ LinkList<Integer> list1=new LinkList<Integer>(); Node<Integer> node,lastNode; for(int i=0;i<n;i++) { int data=(int)(Math.random()*100); //生成100之內的隨機數 node=new Node<Integer>(data, null); node.next=(LinkList<E>.Node<Integer>) list1.head.next; list1.head.next=(LinkList<Integer>.Node<Integer>) node; list1.count++; } return list1; } /** * 整表建立,尾插法 */ public LinkList<Integer> CreateListTail(int n){ LinkList<Integer> list2=new LinkList<Integer>(); Node<Integer> node,lastNode; lastNode=(LinkList<E>.Node<Integer>) list2.head; for(int i=0;i<n;i++) { int data=(int)(Math.random()*100); //生成100之內的隨機數 node=new Node<Integer>(data, null); lastNode.next=node; lastNode=node; list2.count++; } return list2; } }
測試代碼:ide
基本數據類型和引用類型各寫了一個測試代碼。post
package LinkList; /** * 基本數據類型測試 */ public class LinkListTest1 { public static void main(String[] args) { LinkList<Integer> nums = new LinkList<Integer>(); nums.IsEmpty(); System.out.println("——————————插入1到5,並讀取內容——————————"); for (int i = 1; i <= 5; i++) nums.ListInsert(i, 2*i); nums.IsEmpty(); int num; for (int i = 1; i <= 5; i++) { num = nums.GetData(i); System.out.println("第" + i + "個位置的值爲:" + num); } System.out.println("——————————查找0、二、10是否在表中——————————"); System.out.print("0的位置:"); System.out.println(nums.LocateElem(0)); System.out.print("2的位置:"); System.out.println(nums.LocateElem(2)); System.out.print("10的位置:"); System.out.println(nums.LocateElem(10)); System.out.println("——————————刪除二、10——————————"); num = nums.ListDelete(1); System.out.println("已刪除:" + num); num = nums.ListDelete(4); System.out.println("已刪除:" + num); System.out.println("當前表長:" + nums.ListLength()); for (int i = 1; i <= nums.ListLength(); i++) { num = nums.GetData(i); System.out.println("第" + i + "個位置的值爲:" + num); } nums.ClearList(); nums.IsEmpty(); } }
表爲空! ——————————插入1到5,並讀取內容—————————— 插入成功! 插入成功! 插入成功! 插入成功! 插入成功! 表不爲空! 第1個位置的值爲:2 第2個位置的值爲:4 第3個位置的值爲:6 第4個位置的值爲:8 第5個位置的值爲:10 ——————————查找0、2、10是否在表中—————————— 0的位置:查找失敗! 0 2的位置:1 10的位置:5 ——————————刪除二、10—————————— 刪除成功! 已刪除:2 刪除成功! 已刪除:10 當前表長:3 第1個位置的值爲:4 第2個位置的值爲:6 第3個位置的值爲:8 線性表已清空! 表爲空!
package LinkList; public class LinkListTest2 { public static void main(String[] args) { LinkList<Student> students =new LinkList<Student>(); students .IsEmpty(); System.out.println("——————————插入1到5,並讀取內容——————————"); Student[] stus= {new Student("小A",11),new Student("小B",12),new Student("小C",13), new Student("小D",14),new Student("小E",151)}; for(int i=1;i<=5;i++) students.ListInsert(i, stus[i-1]); students .IsEmpty(); Student stu; for(int i=1;i<=5;i++) { stu=students .GetData(i); System.out.println("第"+i+"個位置爲:"+stu.name); } System.out.println("——————————查找小A、小E、小龍是否在表中——————————"); System.out.print("小A的位置:"); stu=stus[0]; System.out.println(students .LocateElem(stu)); System.out.print("小E的位置:"); stu=stus[4]; System.out.println(students .LocateElem(stu)); System.out.print("小龍的位置:"); stu=new Student("小龍",11); System.out.println(students .LocateElem(stu)); System.out.println("——————————刪除小E、小B——————————"); stu=students .ListDelete(2); System.out.println("已刪除:"+stu.name); stu=students .ListDelete(4); System.out.println("已刪除:"+stu.name); System.out.println("當前表長:"+students .ListLength()); for(int i=1;i<=students .ListLength();i++) { stu=students .GetData(i); System.out.println("第"+i+"個位置爲:"+stu.name); } students .ClearList(); students .IsEmpty(); } } class Student{ public Student(String name, int age) { this.name=name; this.age=age; } String name; int age; }
表爲空! ——————————插入1到5,並讀取內容—————————— 插入成功! 插入成功! 插入成功! 插入成功! 插入成功! 表不爲空! 第1個位置爲:小A 第2個位置爲:小B 第3個位置爲:小C 第4個位置爲:小D 第5個位置爲:小E ——————————查找小A、小E、小龍是否在表中—————————— 小A的位置:1 小E的位置:5 小龍的位置:查找失敗! 0 ——————————刪除小E、小B—————————— 刪除成功! 已刪除:小B 刪除成功! 已刪除:小E 當前表長:3 第1個位置爲:小A 第2個位置爲:小C 第3個位置爲:小D 線性表已清空! 表爲空!