線性表結構的Java實現


一、線性表的抽象數據類型表述

線性表的結構簡單,長度允許動態增長或搜索;可以對線性表中的任何數據元素進行訪問和查找;允許進行數據的插入和刪除操作;求線性表中的指定數據的前驅和后繼;合並線性表以及拆分線性表中。

Java JDK中有ArrayList和LinkedList兩個類很好的實現了順序存儲和鏈式存儲。因此學習數據結構的最好方式是去研究JDK源碼。

這里的代碼個人作為練習,為了便於理解,很多地方處理的並非十分嚴謹,僅供參考。轉載注明出處,技術討論 email: <yaoyao0777@Gmail.com>

 

 1 package org.yohhan.data_structure.api;
 2 
 3 /**
 4  * @author yohhan <yaoyao0777@Gmail.com>
 5  * @date create:2016年1月10日 下午4:05:35
 6  *
 7  *       線性表的抽象數據類型
 8  * 
 9  */
10 public interface MyList {
11     public void clear();
12 
13     public boolean isEmpty();
14 
15     public int length();
16 
17     public Object get(int i) throws Exception;
18 
19     public void insert(int i, Object obj) throws Exception;
20 
21     public void remove(int i) throws Exception;
22 
23     public int indexOf(Object obj);
24 
25     public void display();
26 }

 

 

 

 

 

二、線性表的順序存儲實現

1.順序表的定義:

順序存儲采用一組地址連續的存儲單元依次存儲線性表占用的各個數據元素的存儲結構。

2.順序表的特點:

1)邏輯上相鄰的數據元素,在物理存儲位置上也是相鄰的。

2)存儲密度高,事先需要分配足夠應用的存儲空間。

3)隨機存取,查詢速度快,直接訪問地址單元中的數據。時間復雜度 O(1)

4)插入刪除操作會引起大量的數據移動,時間復雜度O(n)

3.順序表的結構類描述:

 1 package org.yohhan.data_structure.linear;
 2 
 3 import org.yohhan.data_structure.api.MyList;
 4 
 5 /**
 6  * @author yohhan <yaoyao0777@Gmail.com>
 7  * @date create:2016年1月10日 下午4:09:15
 8  * 
 9  *       線性表的順序存儲實現
10  */
11 public class SqList implements MyList {
12 
13     private Object[] listElem; // 數組作為線性表的存儲空間
14     private int curLen; // 線性表的當前長度
15 
16     public SqList(int maxSize) {
17         curLen = 0;
18         listElem = new Object[maxSize];
19     }
20 
21     @Override
22     public void clear() {
23         curLen = 0;
24     }
25 
26     @Override
27     public boolean isEmpty() {
28         return curLen == 0;
29     }
30 
31     @Override
32     public int length() {
33         return curLen;
34     }
35 
36     @Override
37     public Object get(int i) throws Exception {
38         if (i < 0 || i > curLen - 1)
39             throw new Exception("元素不存在");
40         return listElem[i];
41     }
42 
43     @Override
44     public void insert(int i, Object obj) throws Exception {
45         if (curLen == listElem.length)
46             throw new Exception("存儲空間已滿");
47         if (i < 0 || i > curLen)
48             throw new Exception("插入位置不合法");
49         for (int j = curLen; j > i; j--)
50             listElem[j] = listElem[j - 1];
51         listElem[i] = obj;
52         ++curLen;
53     }
54 
55     @Override
56     public void remove(int i) throws Exception {
57         if (i < 0 || i > curLen - 1)
58             throw new Exception("刪除位置不合法");
59         for (int j = i; j < curLen; j++)
60             listElem[j] = listElem[j + 1];
61         --curLen;
62     }
63 
64     @Override
65     public int indexOf(Object obj) {
66         int j = 0;
67         while (j < curLen && !listElem[j].equals(obj))
68             j++;
69         if (j < curLen)
70             return j;
71         return -1;
72     }
73 
74     @Override
75     public void display() {
76         for (int j = 0; j < curLen; j++)
77             System.out.print(listElem[j] + ", ");
78     }
79 
80     @Override
81     public String toString() {
82         StringBuffer sb = new StringBuffer();
83         sb.append("[");
84         for (Object obj : listElem) {
85             if (null != obj)
86                 sb.append(obj.toString() + ", ");
87         }
88         sb.delete(sb.length() - 2, sb.length());
89         sb.append("]");
90         return sb.toString();
91     }
92 
93 }

 

三、線性表的鏈式存儲實現

1.單鏈表的定義:

采用鏈式存儲方式存儲的線性表,鏈表中每一個結點中包含存放數據元素值的數據域和存放邏輯上相鄰結點的指針域。(示例中的結點只包含一個指針域,稱為單鏈表(Single Linked List))

(圖片摘自網上)

單鏈表通過指向后繼結點的指針將結點串聯成一條鏈。

以線性表中的第一個數據元素的存儲地址作為線性表的起始地址,稱為線性表的頭指針。通過頭指針(head)來唯一標識一個鏈表。

單鏈表中的最后一個節點沒有后繼,指針域為空指針(null),稱為尾結點。

示例中采用一個“虛頭結點”數據域不存放具體值,指針域中的指針指向單鏈表的第一個結點(首結點)。即當頭結點中的指針域為空時,鏈表為空

 

 

 

 

2.鏈式存儲的特點:

1)不需要預先分配存儲空間,動態分配存儲空間,存儲密度較低、

2) 無法隨機查詢,需要從頭遍歷來查找元素。時間復雜度O(n)

3)便於進行數據的插入和刪除。時間復雜度O(1)

 

3.線性表的單鏈表實現:

結點類結構:

 1 package org.yohhan.data_structure.node;
 2 
 3 /**
 4  * @author yohhan <yaoyao0777@Gmail.com>
 5  * @date create:2016年1月10日 下午4:39:15
 6  * 
 7  *       鏈表的結點類描述
 8  * 
 9  */
10 public class Node {
11 
12     private Object data;
13     private Node next;
14 
15     public Node() {
16         this(null, null);
17     }
18 
19     public Node(Object data) {
20         this(data, null);
21     }
22 
23     public Node(Object data, Node next) {
24         super();
25         this.data = data;
26         this.next = next;
27     }
28 
29     public Object getData() {
30         return data;
31     }
32 
33     public void setData(Object data) {
34         this.data = data;
35     }
36 
37     public Node getNext() {
38         return next;
39     }
40 
41     public void setNext(Node next) {
42         this.next = next;
43     }
44 
45 }

 

單鏈表類的描述:

  1 package org.yohhan.data_structure.linear;
  2 
  3 import org.yohhan.data_structure.api.MyList;
  4 import org.yohhan.data_structure.node.Node;
  5 
  6 /**
  7  * @author yohhan <yaoyao0777@Gmail.com>
  8  * @date create:2016年1月10日 下午4:51:58
  9  * 
 10  *       帶頭結點的單鏈表實現
 11  * 
 12  */
 13 public class LinkList implements MyList {
 14 
 15     private Node head;
 16 
 17     public LinkList() {
 18         head = new Node();
 19     }
 20 
 21     public LinkList(int n, boolean order) throws Exception {
 22         this();
 23         if (order)
 24             createFromTail(n);
 25         else
 26             createFromHead(n);
 27     }
 28 
 29     private void createFromTail(int n) throws Exception {
 30         // 可在此添加輸入流,傳入數據
 31 
 32         for (int j = 0; j < n; j++)
 33             insert(length(), j + 1);
 34     }
 35 
 36     private void createFromHead(int n) throws Exception {
 37         // 可在此添加輸入流,傳入數據
 38 
 39         for (int j = 0; j < n; j++)
 40             insert(0, j + 1);
 41     }
 42 
 43     @Override
 44     public void clear() {
 45         head.setData(null);
 46         head.setNext(null);
 47     }
 48 
 49     @Override
 50     public boolean isEmpty() {
 51         return head.getNext() == null;
 52     }
 53 
 54     @Override
 55     public int length() {
 56         Node node = head.getNext();
 57         int length = 0;
 58         while (node != null) {
 59             node = node.getNext();
 60             ++length;
 61         }
 62         return length;
 63     }
 64 
 65     /**
 66      * 按位序號查找算法
 67      */
 68     @Override
 69     public Object get(int i) throws Exception {
 70         Node node = head.getNext();
 71         int j = 0;
 72         while (node != null && j < i) {
 73             node = node.getNext();
 74             ++j;
 75         }
 76         if (j > i || node == null)
 77             throw new Exception("元素不存在");
 78         return node.getData();
 79     }
 80 
 81     /**
 82      * 在index前插入新結點
 83      */
 84     @Override
 85     public void insert(int i, Object obj) throws Exception {
 86         Node node = head;
 87         int j = -1;
 88         while (node != null && j < i - 1) {
 89             node = node.getNext();
 90             ++j;
 91         }
 92         if (j > i - 1 || node == null)
 93             throw new Exception("插入位置不合法");
 94         Node newNode = new Node(obj);
 95         newNode.setNext(node.getNext());
 96         node.setNext(newNode);
 97     }
 98 
 99     @Override
100     public void remove(int i) throws Exception {
101         Node node = head;
102         int j = -1;
103         while (node.getNext() != null && j < i - 1) { // 鏈表不能為空
104             node = node.getNext();
105             ++j;
106         }
107         if (j > i - 1 || node == null)
108             throw new Exception("刪除位置不合法");
109         node.setNext(node.getNext().getNext());
110     }
111 
112     /**
113      * 按值查找算法
114      */
115     @Override
116     public int indexOf(Object obj) {
117         Node node = head.getNext();
118         int j = 0;
119         while (node != null && !node.getData().equals(obj)) {
120             node = node.getNext();
121             ++j;
122         }
123         if (node != null)
124             return j;
125         return -1;
126     }
127 
128     @Override
129     public void display() {
130         Node node = head.getNext();
131         while (node != null) {
132             System.out.print(node.getData() + "");
133             node = node.getNext();
134         }
135         System.out.println();
136     }
137 
138     @Override
139     public String toString() {
140         StringBuffer sb = new StringBuffer();
141         sb.append("[");
142         Node node = head.getNext();
143         while (node != null) {
144             sb.append(node.getData().toString() + ", ");
145             node = node.getNext();
146         }
147         sb.delete(sb.length() - 2, sb.length());
148         sb.append("]");
149         return sb.toString();
150     }
151 
152 }

 

 

附:線性表的單元測試類:

 1 package org.yohhan.data_structure.test;
 2 
 3 import static org.junit.Assert.*;
 4 import org.junit.Test;
 5 import org.yohhan.data_structure.linear.LinkList;
 6 import org.yohhan.data_structure.linear.SqList;
 7 
 8 /**
 9  * @author yohhan <yaoyao0777@Gmail.com>
10  * @date create:2016年1月10日 下午4:25:12
11  * 
12  *       線性表單元測試類
13  *
14  */
15 public class LinearTest {
16 
17     @Test
18     public void sqListTest() throws Exception {
19         SqList sqList = new SqList(10);
20         for (int i = 0; i < 5; i++)
21             sqList.insert(i, i + 1);
22         System.out.println(sqList);
23         assertTrue(sqList.toString().equals("[1, 2, 3, 4, 5]"));
24         assertTrue(sqList.length() == 5);
25         assertTrue(sqList.indexOf(2) == 1);
26         assertTrue(sqList.get(0).equals(1));
27         sqList.remove(1);
28         assertTrue(sqList.length() == 4);
29         assertTrue(sqList.indexOf(1) == 0);
30     }
31 
32     @Test
33     public void linkListTest() throws Exception {
34         LinkList linkList = new LinkList(5, true);
35         System.out.println(linkList);
36         assertTrue(new LinkList(5, false).toString().equals("[5, 4, 3, 2, 1]"));
37         assertTrue(linkList.toString().equals("[1, 2, 3, 4, 5]"));
38         assertTrue(linkList.length() == 5);
39         assertTrue(linkList.indexOf(2) == 1);
40         assertTrue(linkList.get(0).equals(1));
41         linkList.remove(1);
42         assertTrue(linkList.length() == 4);
43         assertTrue(linkList.indexOf(1) == 0);
44 
45     }
46 
47 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM