JAVA資料結構之連結串列
1、單連結串列的資料結構
單連結串列中的資料是以結點的形式存在,每一個結點是由資料元素(資料域)和下一個結點的儲存的位置(指標域)組成。單連結串列與陣列相比的最大差別是:單連結串列的資料元素存放在記憶體空間的地址是不連續的,而陣列的資料元素存放的地址在記憶體空間中是連續的。具體的資料模型用下圖大概描述一下。
2、單連結串列的優缺點
優點:
插入刪除速度快、記憶體利用率高,不會浪費記憶體、大小沒有固定,擴充很靈活
由於連結串列的節點在記憶體中可以存在任何地方、不要求連續,且每個節點中都儲存著下一節點的記憶體地址。如果需要新插入一個新節點(資料),只需要把此節點的記憶體地址指向下一節點,上一節點的記憶體地址指向本節點就OK了,其餘節點都不用發生改變,所以插入刪除速度快。不像陣列一樣增加、刪除資料後其他的元素的下標都得發生改變。
缺點:
不可以進行隨機查詢
這個由連結串列的資料結構決定的,查詢某個節點的資料都必須在head(頭節點)依次指向下一節點,直到找到我們需要的資料節點。這一點不像陣列一樣可以根據陣列下標直接進行查詢。
3、單連結串列的簡單實現
在這裡就使用程式碼簡單的實現下單連結串列的資料結構,並實現增刪改查。
新建一個節點類,用來儲存每個節點的資料
public class Node <T>{
//資料域
public T t;
//指標域
public Node next;
public Node(T t,Node next){
this.t = t;
this.next = next;
}
public Node(T t){
this(t,null);
}
}
新建連結串列類,宣告增刪改查方法
1、在連結串列頭部新增節點方法
public class LinkList<T> {
private Node head; //頭結點
private int size; //連結串列元素個數
//建構函式
public LinkList(){
this.head = null;
this.size = 0;
}
/**
* 往連結串列頭部插入值
* @param t
*/
public void addFirst(T t) {
Node node = new Node(t); //節點物件
node.next = this.head;
this.head = node;
this.size++;
}
/**
* java類的預設繼承方法,繼承於object類。
*/
public String toString() {
StringBuffer sb = new StringBuffer();
Node cur = this.head;
while(cur != null){
sb.append(cur.t+"=>");
cur = cur.next;
}
sb.append("NULL");
return sb.toString();
}
}
在連結串列的頭部新增節點,具體操作是把新節點的next指向當前頭結點,更新this.head為新增的節點,節點數量加一。具體如下圖:
測試方法:
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkList<String> linklist = new LinkList();
String[] strArray = new String[6];
strArray[0] = "one";
strArray[1] = "two";
strArray[2] = "three";
strArray[3] = "four";
strArray[4] = "five";
strArray[5] = "six";
for(String str : strArray) {
linklist.addFirst(str);
System.out.println(linklist);
}
}
執行main方法
2、在連結串列根據位置插入資料
具體程式碼如下:
/**
* 往連結串列中間插入值
* @param index
* @param t
*/
public void add(int index,T t) {
//當index值小於零或者大於連結串列長度時,丟擲異常
if (index <0 || index > this.size){
throw new IllegalArgumentException("index is error");
}
//當index為零的時候向連結串列頭部插入一個值
if (index == 0){
this.addFirst(t);
}
//獲取當前連結串列的頭元素(第一個值)
Node preNode = this.head;
//找到要插入節點的前一個節點
for(int i=0;i<index-1;i++) {
preNode = preNode.next;
}
Node cruNode = new Node(t);
//要插入的節點的下一個節點指向preNode節點的下一個節點
cruNode.next = preNode.next;
//preNode的下一個節點指向要插入節點node
preNode.next = cruNode;
this.size++;
}
原理圖形表達:
測試程式碼main如下:
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkList<String> linklist = new LinkList();
String[] strArray = new String[6];
strArray[0] = "one";
strArray[1] = "two";
strArray[2] = "three";
strArray[3] = "four";
strArray[4] = "five";
strArray[5] = "six";
for(String str : strArray) {
linklist.addFirst(str);
System.out.println(linklist);
}
linklist.add(3, "23");
System.out.println(linklist);
linklist.add(3, "45");
System.out.println(linklist);
}
測試結果如下:
3、查詢方法
//連結串列中是否包含某個元素
public boolean contains(T t){
Node cur = this.head;
while(cur != null){
if(cur.t.equals(t)){
return true;
}
else {
cur = cur.next;
}
}
return false;
}
根據方法傳入的值從連結串列的頭部進行遍歷,如果找到了return結果true,找不到就return結果false。
測試程式碼:
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkList<String> linklist = new LinkList();
String[] strArray = new String[6];
strArray[0] = "one";
strArray[1] = "two";
strArray[2] = "three";
strArray[3] = "four";
strArray[4] = "five";
strArray[5] = "six";
for(String str : strArray) {
linklist.addFirst(str);
System.out.println(linklist);
}
linklist.add(3, "23");
System.out.println(linklist);
linklist.add(3, "45");
System.out.println(linklist);
System.out.println(linklist.contains("four"));
System.out.println(linklist.contains("ten"));
}
演示結果:
4、刪除方法
public void remove(T t) {
if(this.head ==null) {
System.out.println("連結串列中無資料,不可進行刪除!!");
}else {
//如果要刪除的元素跟連結串列頭部的元素相同,就刪除頭部(把頭元素的指向的元素設為頭元素)
if(head.t.equals(t)) {
head = head.next;
this.size--;
}else {
//獲取當前節點為頭部節點
Node cur = this.head;
//一直迴圈遍歷連結串列到最後
while(cur.next != null) {
//當前元素的下一個元素為要刪除的值時,那就把當前元素下一個元素的下一個元素 設為 當前元素的下一個元素
if(cur.next.t.equals(t)) {
cur.next = cur.next.next;
}else {
cur = cur.next;
}
}
}
}
}
原理圖形表達:
測試程式碼:
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkList<String> linklist = new LinkList();
String[] strArray = new String[6];
strArray[0] = "one";
strArray[1] = "two";
strArray[2] = "three";
strArray[3] = "four";
strArray[4] = "five";
strArray[5] = "six";
for(String str : strArray) {
linklist.addFirst(str);
System.out.println(linklist);
}
linklist.add(3, "23");
System.out.println(linklist);
linklist.add(3, "45");
System.out.println(linklist);
System.out.println(linklist.contains("four"));
System.out.println(linklist.contains("ten"));
linklist.remove("45");
System.out.println(linklist);
}
測試的結果:
到這就簡單演示了單連結串列的資料結構,深入研究還是看一下java的LinkedList。
相關文章
- 資料結構之連結串列資料結構
- 資料結構之「連結串列」資料結構
- Java版-資料結構-連結串列Java資料結構
- 資料結構之單連結串列資料結構
- 資料結構之連結串列操作資料結構
- JavaScript資料結構 之 連結串列JavaScript資料結構
- 資料結構之連結串列【上】資料結構
- 資料結構之連結串列:206. 反轉連結串列資料結構
- 資料結構之迴圈連結串列資料結構
- 資料結構之雙向連結串列資料結構
- 資料結構實驗之連結串列二:逆序建立連結串列資料結構
- 資料結構實驗之連結串列九:雙向連結串列資料結構
- 資料結構-單連結串列、雙連結串列資料結構
- 資料結構 - 連結串列資料結構
- 連結串列-資料結構資料結構
- 資料結構—連結串列資料結構
- 資料結構--連結串列資料結構
- 資料結構-連結串列資料結構
- 資料結構實驗之連結串列三:連結串列的逆置資料結構
- 資料結構實驗之連結串列五:單連結串列的拆分資料結構
- 資料結構實驗之連結串列六:有序連結串列的建立資料結構
- 資料結構實驗之連結串列一:順序建立連結串列資料結構
- 資料結構之連結串列篇(單連結串列的常見操作)資料結構
- JavaScript資料結構之連結串列--設計JavaScript資料結構
- JavaScript資料結構之連結串列--介紹JavaScript資料結構
- Redis基礎資料結構之連結串列Redis資料結構
- 連結串列資料結構之js原型鏈資料結構JS原型
- 畫江湖之資料結構【第一話:連結串列】單向連結串列資料結構
- 畫江湖之資料結構【第一話:連結串列】雙向連結串列資料結構
- 畫江湖之資料結構 [第一話:連結串列] 單向連結串列資料結構
- 畫江湖之資料結構 [第一話:連結串列] 雙向連結串列資料結構
- 資料結構實驗之連結串列四:有序連結串列的歸併資料結構
- JavaScript資料結構--連結串列JavaScript資料結構
- php實現基本資料結構之連結串列PHP資料結構
- 【資料結構之連結串列】詳細圖文教你花樣玩連結串列資料結構
- 資料結構:跳躍連結串列資料結構
- 資料結構——雙向連結串列資料結構
- 資料結構04——單連結串列資料結構