數據結構之線性表


線性表

線性表的基本概念

  • 對於同一個線性表,其每一個數據元素的值雖然不同,但必須具有相同的數據類型;
  • 數據元素之間具有一種線性的或“一對一”的邏輯關系。
    1. 第一個數據元素沒有前驅,這個數據元素被稱為開始節點;
    2. 最后一個數據元素沒有后繼,這個數據元素被稱為終端節點;
    3. 除了第一個和最后一個數據元素外,其他數據元素有且僅有一個前驅和一個后繼。

 

線性表的抽象數據類型描述

基本操作如下:

  1. 線性表的置空操作clear():將一個已經存在的線性表置為空表。
  2. 線性表判空操作isEmpty():判斷線性表是否為空,若為空,則返回true;否則,返回為false。
  3. 求線性表的長度操作length():求線性表中的數據元素的個數並返回其值。
  4. 取元素操作get(i):讀取並返回線性表中的第i個數據元素的值。其中i的取值范圍為0≤i≤length()-1。
  5. 插入操作insert(i,x):在線性表的第i個數據元素之前插入一個值為x的數據元素。其中i的取值范圍為0≤i≤length()。當i=0時,在表頭插入x;當i=length()時,在表尾插入x。
  6. 刪除操作remove(i):刪除並返回線性表中第i個數據元素。其中i的取值范圍為0≤i≤length()-1。
  7. 查找操作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. 順序存儲結構類的描述

 

  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. 結點類的描述
 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 }

 


免責聲明!

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



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