線性表
線性表的基本概念
- 對於同一個線性表,其每一個數據元素的值雖然不同,但必須具有相同的數據類型;
- 數據元素之間具有一種線性的或“一對一”的邏輯關系。
- 第一個數據元素沒有前驅,這個數據元素被稱為開始節點;
- 最后一個數據元素沒有后繼,這個數據元素被稱為終端節點;
- 除了第一個和最后一個數據元素外,其他數據元素有且僅有一個前驅和一個后繼。
線性表的抽象數據類型描述
基本操作如下:
- 線性表的置空操作clear():將一個已經存在的線性表置為空表。
- 線性表判空操作isEmpty():判斷線性表是否為空,若為空,則返回true;否則,返回為false。
- 求線性表的長度操作length():求線性表中的數據元素的個數並返回其值。
- 取元素操作get(i):讀取並返回線性表中的第i個數據元素的值。其中i的取值范圍為0≤i≤length()-1。
- 插入操作insert(i,x):在線性表的第i個數據元素之前插入一個值為x的數據元素。其中i的取值范圍為0≤i≤length()。當i=0時,在表頭插入x;當i=length()時,在表尾插入x。
- 刪除操作remove(i):刪除並返回線性表中第i個數據元素。其中i的取值范圍為0≤i≤length()-1。
- 查找操作indexOf(x):返回線性表中首次出現的指定的數據元素的位序號,若線性表中不包含此數據元素,則返回-1。
線性表的抽線數據類型用Java接口描述如下:
1 /** 2 * 3 * @author Accper 4 * 5 */ 6 public interface IList { 7 // 線性表置空操作 8 public void clear(); 9 10 // 判斷線性表是否為空操作 11 public boolean isEmpty(); 12 13 // 獲取線性表中元素的長度操作 14 public int length(); 15 16 // 獲取指定位置上面的元素操作 17 public Object get(int i); 18 19 // 在指定位置上面插入元素的操作 20 public void insert(int i, Object x); 21 22 // 刪除指定位置上面的元素的操作 23 public void remove(int i); 24 25 // 查找指定元素的位置首次出現的位置操作 26 public int indexOf(Object x); 27 28 // 顯示線性表中的內容操作 29 public void display(); 30 }
線性表的順序存儲及實現
- 順序表的定義
- 所謂順序表就是順序存儲的線性表。順序存儲是用一組地址連續的存儲單元依次存放線性表中各個元素的存儲結構。
- 順序表的特點:
- 在線性表中邏輯上相鄰的數據元素,在物理存儲上也是相鄰的。
- 存儲密度高,但要預先分配“足夠應用”的存儲空間,這可能會造成存儲空間的浪費。
- 便於隨機存儲。
- 不便於插入和刪除操作,這是因為在順序表上進行的插入和刪除操作會引起大量數據元素的移動。
- 順序存儲結構類的描述
1 /** 2 * 3 * @author Accper 4 * 5 */ 6 public class SqList implements IList { 7 // 線性表存儲空間 8 private Object[] listElem; 9 // 線性表的當前長度 10 private int curLen; 11 12 // 順序表類的構造函數,構造一個存儲空間容量為maxSize的線性表 13 public SqList(int maxSize) { 14 // TODO Auto-generated constructor stub 15 curLen = 0; 16 listElem = new Object[maxSize]; 17 } 18 19 // 將一個已經存在的線性表置成空表 20 public void clear() { 21 // TODO Auto-generated method stub 22 // 置順序表的當前長度為0 23 curLen = 0; 24 } 25 26 // 判斷線性表中的數據元素的個數是否為0,若為0則返回true,否則返回false 27 public boolean isEmpty() { 28 // TODO Auto-generated method stub 29 return curLen == 0; 30 } 31 32 // 求線性表中的數據元素的個數並返回其值 33 public int length() { 34 // TODO Auto-generated method stub 35 // 返回順序表的當前長度 36 return curLen; 37 } 38 39 // 讀取到線性表中的第i個數據元素並由函數返回其值,其中i的取值范圍為0≤i≤length()-1,若i不在此范圍則拋出異常 40 public Object get(int i) { 41 // TODO Auto-generated method stub 42 if (i < 0 || i >= curLen) { 43 throw new RuntimeException("第" + i + "個元素不存在"); 44 } 45 return listElem[i]; 46 } 47 48 // 在線性表的第i個數據元素之前插入一個值位x的數據元素 49 public void insert(int i, Object x) { 50 // TODO Auto-generated method stub 51 // 判斷表是否滿了 52 if (curLen == listElem.length) { 53 throw new RuntimeException("存儲空間已經滿了,無法插入新的元素"); 54 } 55 // 插入的位置不合法 56 if (i < 0 || i > curLen) { 57 throw new RuntimeException("插入的位置不合法"); 58 } 59 // 必須要從最后一個元素開始依次逐個后移動,直到第i個數據元素移動完畢為止。 60 for (int j = curLen; j > i; j--) { 61 listElem[j] = listElem[j - 1]; 62 } 63 listElem[i] = x; 64 curLen++; 65 } 66 67 public void remove(int i) { 68 // TODO Auto-generated method stub 69 if (i < 0 || i > curLen - 1) { 70 throw new RuntimeException("刪除的位置不合法"); 71 } 72 for (int j = i; j < curLen; j++) { 73 listElem[j] = listElem[j+1]; 74 } 75 curLen--; 76 } 77 78 // 返回線性表中首次出現指定的數據元素的位序號,若線性表中不包含此數據元素,則返回-1 79 public int indexOf(Object x) { 80 // TODO Auto-generated method stub 81 for (int i = 0; i < curLen; i++) { 82 if (listElem[i].equals(x)) { 83 return i; 84 } 85 } 86 return -1; 87 } 88 89 // 輸出線性表中的數據元素 90 public void display() { 91 // TODO Auto-generated method stub 92 for (int i = 0; i < curLen; i++) { 93 System.out.print(listElem[i] + " "); 94 } 95 System.out.println(); 96 } 97 98 // 測試 99 public static void main(String[] args) { 100 SqList sqList = new SqList(10); 101 sqList.insert(0, "a"); 102 sqList.insert(1, "z"); 103 sqList.insert(2, "d"); 104 sqList.insert(3, "m"); 105 sqList.insert(4, "z"); 106 int order = sqList.indexOf("z"); 107 if (order!=-1) { 108 System.out.println("順序表中第一次出現的值為z的數據元素的位置為:"+order); 109 }else { 110 System.out.println("順序表中不包括z元素"); 111 } 112 } 113 }
線性表的鏈式存儲及實現
- 結點類的描述
1 /** 2 * 3 * @author Accper 4 * 5 */ 6 public class Node { 7 // 存放結點的值 8 private Object data; 9 // 后繼結點的引用 10 private Node next; 11 12 // 無參數時的構造函數 13 public Node() { 14 // TODO Auto-generated constructor stub 15 this(null, null); 16 } 17 18 // 帶有一個參數時的構造函數 19 public Node(Object data) { 20 this(data, null); 21 } 22 23 // 帶有兩個參數時的構造函數 24 public Node(Object data, Node next) { 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 }
單鏈表類的描述
1 /** 2 * 3 * @author Accper 4 * 5 */ 6 public class LinkList implements IList { 7 // 單鏈表的頭指針 8 private Node head; 9 10 // 單鏈表的構造函數 11 public LinkList() { 12 // TODO Auto-generated constructor stub 13 // 初始化頭結點 14 head = new Node(); 15 } 16 17 public LinkList(int n, boolean Order) { 18 // 初始化頭結點 19 this(); 20 if (Order) { 21 // 用尾插法順序建立單鏈表 22 create1(n); 23 } else { 24 // 用頭插法順序建立單鏈表 25 create2(n); 26 } 27 } 28 29 // 用頭插法順序建立單鏈表 30 private void create2(int n) { 31 // TODO Auto-generated method stub 32 Scanner sc = new Scanner(System.in); 33 for (int i = 0; i < n; i++) { 34 insert(0, sc.next()); 35 } 36 } 37 38 // 用尾插法順序建立單鏈表 39 private void create1(int n) { 40 // TODO Auto-generated method stub 41 Scanner sc = new Scanner(System.in); 42 for (int i = 0; i < n; i++) { 43 insert(length(), sc.next()); 44 } 45 } 46 47 // 將一個已經存在的帶頭結點的單鏈表置成空表 48 @Override 49 public void clear() { 50 // TODO Auto-generated method stub 51 head.setData(null); 52 head.setNext(null); 53 } 54 55 // 判斷帶頭結點的單鏈表是否為空 56 @Override 57 public boolean isEmpty() { 58 // TODO Auto-generated method stub 59 return head.getNext() == null; 60 } 61 62 // 求帶頭結點的單鏈表的長度 63 @Override 64 public int length() { 65 // TODO Auto-generated method stub 66 // 初始化,p指向頭結點,length為計數器 67 Node p = head.getNext(); 68 int length = 0; 69 // 從頭結點開始向后查找,直到p為空 70 while (p != null) { 71 // 指向后繼結點 72 p = p.getNext(); 73 // 長度加1 74 length++; 75 } 76 return length; 77 } 78 79 // 讀取帶頭結點的單鏈表中的第i個結點 80 @Override 81 public Object get(int i) { 82 // TODO Auto-generated method stub 83 Node p = head.getNext(); 84 int j = 0; 85 while (p != null && j < i) { 86 p = p.getNext(); 87 j++; 88 } 89 // i小於0或者大於表長減1 90 if (j > i || p == null) { 91 throw new RuntimeException("第" + i + "個元素不存在"); 92 } 93 return p.getData(); 94 } 95 96 // 在頭結點的單鏈表中的第i個結點之前插入一個值為x的新結點 97 @Override 98 public void insert(int i, Object x) { 99 // TODO Auto-generated method stub 100 Node p = head; 101 int j = -1; 102 // 尋找第i個結點的前驅 103 while (p != null && j < i - 1) { 104 p = p.getNext(); 105 j++; 106 } 107 if (j > i - 1 || p == null) { 108 throw new RuntimeException("插入位置不合法"); 109 } 110 Node s = new Node(x); 111 // 修改鏈,使新結點插入到單鏈表中 112 s.setNext(p.getNext()); 113 p.setNext(s); 114 } 115 116 // 刪除帶頭結點的單鏈表中的第i個結點 117 @Override 118 public void remove(int i) { 119 // TODO Auto-generated method stub 120 Node p = head; 121 int j = -1; 122 while (p.getNext() != null && j < i - 1) { 123 p = p.getNext(); 124 j++; 125 } 126 if (j > i - 1 || p.getNext() == null) { 127 throw new RuntimeException("刪除位置不合法"); 128 } 129 // 修改鏈指針,使待刪除結點從單鏈表中脫離 130 p.setNext(p.getNext().getNext()); 131 } 132 133 // 查找指定單鏈表中元素的位置,若在單鏈表中值發回該位置,如果不在單鏈表中則返回-1 134 @Override 135 public int indexOf(Object x) { 136 // TODO Auto-generated method stub 137 Node p = head.getNext(); 138 int j = 0; 139 while (p != null && p.getData().equals(x)) { 140 p = p.getNext(); 141 j++; 142 } 143 if (p == null) { 144 return -1; 145 } else { 146 return j; 147 } 148 } 149 150 // 輸出單鏈表中的所有結點 151 @Override 152 public void display() { 153 // TODO Auto-generated method stub 154 // 取出帶頭結點的單鏈表中的首結點 155 Node p = head.getNext(); 156 while (p != null) { 157 // 輸出結點的值 158 System.out.print(p.getData() + " "); 159 // 取下一個結點 160 p = p.getNext(); 161 } 162 System.out.println(); 163 } 164 165 // 測試 166 public static void main(String[] args) { 167 int n = 10; 168 LinkList L = new LinkList(); 169 for (int i = 0; i < n; i++) { 170 L.insert(i, i); 171 } 172 System.out.println("請輸入i的值:"); 173 int i = new Scanner(System.in).nextInt(); 174 if (0 < i && i <= n) { 175 System.out.println("第" + i + "個元素的前驅是:" + L.get(i - 1)); 176 } else { 177 System.out.println("第" + i + "個元素的直接前驅不存在"); 178 } 179 } 180 }