1. 程式人生 > >數據結構Java實現01----線性表與順序表

數據結構Java實現01----線性表與順序表

mage itl 順序表的初始化 測試 for html blank 一個數 exc

一、線性結構

如果一個數據元素序列滿足:

(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     public
void 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----線性表與順序表