數據結構Java實現01----線性表與順序表
一、線性結構:
如果一個數據元素序列滿足:
(1)除第一個和最後一個數據元素外,每個數據元素只有一個前驅數據元素和一個後繼數據元素;
(2)第一個數據元素沒有前驅數據元素;
(3)最後一個數據元素沒有後繼數據元素。
則稱這樣的數據結構為線性結構。
二、線性表抽象數據類型:
1、線性表抽象數據類型的概念:
線性表抽象數據類型主要包括兩個方面:既數據集合和該數據集合上的操作集合。
數據集合:
可以表示為a0,a1,a2,...an-1,每個數據元素的數據類型可以是任意的類型。
操作集合包括如下:
1.插入
2.查找
3.刪除
4.判斷是否為空
5.求元素個數
2、設計線性表抽象數據類型的Java接口:
代碼如下:
1 package com.myutil.list; 2 3 public interface List { 4 //插入元素 5 public void insert(int index,Object obj) throws Exception; 6 //重載插入方法 7 public void insert(Object obj) throws Exception; 8 //獲取指定位置的元素 9 public Object get(int index) throws Exception; 10 //刪除元素 11 publicvoid delete(int index) throws Exception; 12 //獲得線性表長度 13 public int size(); 14 //判斷線性表是否為空 15 public boolean isEmpty(); 16 }
然後我們讓子類去實現這個接口就行了。
三、順序表:(在物理存儲結構上連續,大小固定)
1、順序表的概念:
計算機有兩種基本的存儲結構(物理存儲結構):順序結構、離散結構。使用順序結構實現的線性表稱為順序表。如下圖所示:
Java內存中,棧內存和堆內存占了很大一部分空間:棧內存的存儲是順序結構,堆內存的存儲是離散結構。
2、設計順序表類:
我們在上面第二段的List接口基礎之上,設計一個順序表:
(1)List.java:(線性表,和上面的第二段中代碼一樣)
1 package com.myutil.list; 2 3 public interface List { 4 //插入元素 5 public void insert(int index,Object obj) throws Exception; 6 //重載插入方法 7 public void insert(Object obj) throws Exception; 8 //獲取指定位置的元素 9 public Object get(int index) throws Exception; 10 //刪除元素 11 public void delete(int index) throws Exception; 12 //獲得線性表長度 13 public int size(); 14 //判斷線性表是否為空 15 public boolean isEmpty(); 16 }
(2)SequentailList.java:(核心代碼)
1 package com.myutil.list; 2 3 //SequentialList:順序表 4 5 public class SequentialList implements List { 6 7 //默認的順序表的最大長度 8 private final int defaultSize = 10; 9 //最大長度 10 private int maxSize; 11 //當前長度 12 private int size; 13 //對象數組 14 Object[] listArray; 15 16 17 public SequentialList() { 18 init(defaultSize); 19 } 20 21 public SequentialList(int size) { 22 init(size); 23 } 24 25 //順序表的初始化方法(建立順序表) 26 private void init(int size) { 27 maxSize = size; 28 this.size = 0; 29 listArray = new Object[size]; 30 } 31 32 @Override 33 public void insert(int index, Object obj) throws Exception { 34 //如果當前線性表已滿,那就不允許插入數據 35 if (size == maxSize) { 36 throw new Exception("順序表已滿,無法插入!"); 37 } 38 //插入位置編號是否合法 39 if (index < 0 || index > size) { 40 throw new Exception("參數錯誤!"); 41 } 42 //移動元素 43 for (int j = size - 1; j >= index; j--) { 44 listArray[j + 1] = listArray[j]; 45 } 46 47 listArray[index] = obj; //不管當前線性表的size是否為零,這句話都能正常執行,即都能正常插入 48 size++; 49 } 50 51 @Override 52 public void insert(Object obj) throws Exception { 53 insert(size, obj); 54 } 55 56 @Override 57 public Object get(int index) throws Exception { 58 if (index < 0 || index >= size) { 59 throw new Exception("參數錯誤!"); 60 } 61 return listArray[index]; 62 } 63 64 @Override 65 public void delete(int index) throws Exception { 66 if (isEmpty()) { 67 throw new Exception("順序表為空,無法刪除!"); 68 } 69 if (index < 0 || index > size - 1) { 70 throw new Exception("參數錯誤!"); 71 } 72 //移動元素 73 for (int j = index; j < size - 1; j++) { 74 listArray[j] = listArray[j + 1]; 75 } 76 size--; 77 } 78 79 @Override 80 public int size() { 81 return size; 82 } 83 84 85 @Override 86 public boolean isEmpty() { 87 return size == 0; 88 } 89 }
我們來看一下第54行的插入操作insert()方法:如果需要在index位置插入一個數據,那麽index後面的元素就要整體往後移動一位。這裏面需要特別註意的是:
插入操作:移動元素時,要從後往前操作,不能從前往後操作,不然元素會被覆蓋的。
刪除元素:移動元素時,要從前往後操作。
(3)測試類:
1 package com.myutil.list; 2 3 public class Test { 4 5 public static void main(String[] args) { 6 7 SequentialList list = new SequentialList(20); 8 9 try { 10 list.insert(0, 100); 11 list.insert(0, 50); 12 list.insert(1, 20); 13 list.insert(60); 14 15 for (int i = 0; i < list.size(); i++) { 16 System.out.println("第" + i + "個數為" + list.get(i)); 17 } 18 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 } 23 }
我們要註意插入的規則是什麽,不然會覺得這個順序表打印輸出的順序很奇怪。
運行效果:
第0個數為50
第1個數為20
第2個數為100
第3個數為60
3、順序表效率分析:
- 順序表插入和刪除一個元素的時間復雜度為O(n)。
- 順序表支持隨機訪問,順序表讀取一個元素的時間復雜度為O(1)。因為我們是可以通過下標直接訪問的,所以時間復雜度是固定的,和問題規模無關。
4、順序表的優缺點:
- 順序表的優點是:支持隨機訪問;空間利用率高(連續分配,不存在空間浪費)。
- 順序表的缺點是:大小固定(一開始就要固定順序表的最大長度);插入和刪除元素需要移動大量的數據。
5、順序表的應用:
設計一個順序表,可以保存100個學生的資料,保存以下三個學生的資料,並打印輸出。
代碼實現:
(1)List.java:
和上面的代碼保持不變
(2)SequentailList.java:
和上面的代碼保持不變
(3)Students.java:學生類
1 package com.myutil.list.use; 2 3 //學生類 4 public class Students { 5 6 private String id;// 學號 7 private String name;// 姓名 8 private String gender;// 性別 9 private int age;// 年齡 10 11 public Students() { 12 13 } 14 15 public Students(String sid, String name, String gender, int age) { 16 this.id = sid; 17 this.name = name; 18 this.gender = gender; 19 this.age = age; 20 } 21 22 23 public String getId() { 24 return id; 25 } 26 27 public void setId(String id) { 28 this.id = id; 29 } 30 31 public String getName() { 32 return name; 33 } 34 35 public void setName(String name) { 36 this.name = name; 37 } 38 39 public String getGender() { 40 return gender; 41 } 42 43 public void setGender(String gender) { 44 this.gender = gender; 45 } 46 47 public int getAge() { 48 return age; 49 } 50 51 public void setAge(int age) { 52 this.age = age; 53 } 54 55 public String toString() { 56 return "學號:" + this.getId() + " 姓名:" + this.getName() + " 性別:" + this.getGender() + " 年齡:" + this.getAge(); 57 } 58 59 }
(4)Test.java:
1 package com.myutil.list.use; 2 3 import com.myutil.list.SequentialList; 4 5 public class Test { 6 7 /** 8 * @param args 9 */ 10 public static void main(String[] args) { 11 SequentialList list = new SequentialList(100); 12 13 try { 14 list.insert(list.size(), new Students("S0001", "張三", "男", 18)); //第一個參數list.size代表的是:我每次都是在順序表的最後一個位置(當前線性表的長度的位置)進行插入操作。這一行裏,size是等於0 15 list.insert(new Students("S0002", "李四", "男", 19)); 16 list.insert(list.size(), new Students("S0003", "王五", "女", 21)); 17 list.insert(new Students("S0004","趙六","女",20)); 18 19 for (int i = 0; i < list.size(); i++) { 20 System.out.println(list.get(i)); 21 } 22 23 } catch (Exception ex) { 24 ex.printStackTrace(); 25 } 26 } 27 28 }
註意第11行的註釋:第一個參數list.size代表的是:我每次都是在順序表的最後一個位置(當前線性表的長度的位置)進行插入操作;這樣的話,遍歷時才是按照張三、李四、王五的順序進行輸出的。
運行效果:
學號:S0001 姓名:張三 性別:男 年齡:18 學號:S0002 姓名:李四 性別:男 年齡:19 學號:S0003 姓名:王五 性別:女 年齡:21 學號:S0004 姓名:趙六 性別:女 年齡:20
本文參考博客:http://www.cnblogs.com/smyhvae/p/4758808.html,並加入自己的一點改動,後續還會有優化改動,例如加入泛型等。。。。。。
數據結構Java實現01----線性表與順序表