標籤:資料結構 單鏈表 linkedlist
線性表的鏈式儲存結構,也稱之為鏈式表,鏈表;鏈表的儲存單元可以連續也可以不連續。
鏈表中的節點包含資料域和指標域,資料域為儲存資料元素資訊的域,指標域為儲存直接後繼位置(一般稱為指標)的域。
注意一個頭結點和頭指標的區別:
頭指標:
- 指向鏈表的第一個節點的指標,若鏈表有頭結點,則是指向頭結點的指標;
- 頭指標具有標識作用,所以常用頭指標作為鏈表的名字;
- 不論鏈表是否為空白,頭指標都不為空白;
- 是鏈表的必要元素。
頭結點:
- 頭結點是為了操作的統一和方便而設立的,放在第一個元素節點的前面,其資料域一般無意義,也可以存放鏈表的長度;
- 頭結點不是鏈表的必要元素。
這裡先講講單鏈表吧,其他的後面再講。
無頭結點的鏈表
有頭結點的鏈表
空鏈表
我試著用Java寫了一個LinkedList的代碼,如下:
package com.phn.datestructure;/** * @author 潘海南 * @Email [email protected] * @TODO 鏈式表 * @date 2015年7月18日 */public class FOLinkedList<E> { // 單鏈表的頭結點 private FONode<E> header = null; // 單鏈表的長度 private int size; /** * @TODO 預設的無參建構函式 */ public FOLinkedList() { super(); this.header = new FONode<E>(); this.setSize(); } /** * @TODO 單鏈表添加元素 * @param e 資料元素類型 * @return true */ public boolean add(E e) { FONode<E> node = new FONode<E>(e); if (header.getE() == null) { header.setE(e); } else { FONode<E> lastNode = this.last(this.header); lastNode.addNext(node); } this.size++; return true; } /** * @TODO 單鏈表插入元素 * @param index 插入位置 * @param e 資料元素類型 * @return true */ public boolean insert(int index,E e) { FONode<E> node = new FONode<E>(e); FONode<E> preNode = this.get(index - 1); node.addNext(preNode.next); preNode.addNext(node); this.size++; return true; } /** * @TODO 單鏈表刪除元素 * @param index 將要刪除的元素的索引位置 * @return E 刪除的元素 */ public FONode<E> remove(int index){ FONode<E> preNode = this.get(index-1); FONode<E> node = preNode.next; preNode.addNext(preNode.next.next); node.addNext(null); this.size--; return node; } /** * @TODO 根據元素索引位置擷取元素 * @param index 元素的索引位置 * @return E 元素e */ public FONode<E> get(int index) { validateIndex(index); FONode<E> temp = this.header; int i = 0; while (i < index - 1) { if (temp != null) { temp = temp.next; i++; } else { throw new RuntimeException("節點空值錯誤"); } } return temp; } /** * @TODO 將單鏈表中索引位置為i的元素修改為元素e * @param index 元素的索引位置 * @param e 需要修改成的元素 * @return true 修改成功標誌 */ public boolean set(int index, E e){ validateIndex(index); FONode<E> oldNode = this.get(index); oldNode.setE(e); return true; } /** * @TODO 驗證所給索引位置是否合法 * @param index 給出的索引位置 */ private void validateIndex(int index) { if (index > this.size || index < 0) { throw new RuntimeException("索引錯誤:" + index); } } /** * @TODO 擷取單鏈表的最後一個節點 * @param header 單鏈表的頭結點 * @return node 單鏈表的最後一個節點 */ private FONode<E> last(FONode<E> header) { FONode<E> temp = header; while (true) { if (temp.next == null) { return temp; } temp = temp.next; } } @Override public String toString() { return "[" + this.NodesToString(this.header) + "]"; } /** * @TODO 設定單鏈表的長度 * @param header 單鏈表的頭結點 * @return 單鏈表的節點字串序列 */ private String NodesToString(FONode<E> header) { StringBuffer sb = new StringBuffer(); if (header != null) { sb.append(header.getE()); FONode<E> temp = new FONode<E>(); temp = header.next; while (temp != null) { sb.append(", " + temp.getE()); temp = temp.next; } } return sb.toString(); } /** * @TODO 設定單鏈表的長度 */ private void setSize() { this.size = 0; } /** * @TODO 擷取單鏈表的長度 * @return size 單鏈表的長度 */ public int size() { return this.size; }}
這裡也講講資料元素的插入和刪除操作;
插入操作示範如下:
代碼:
s->next = p->next;p->next = s;
這裡摘了《大話資料結構》的一段文字解釋:
刪除操作如:
一句代碼:
p->next = p->next->next;
結合上述代碼和圖例,可以看出單鏈表的刪除和插入操作都是由兩部分組成:
- 遍曆尋找到需要操作的位置的那個元素;
- 然後進行插入和刪除操作。
下面是摘自《大話資料結構》的分析:
單鏈表的整表建立
方法有頭插法和尾插法;
頭插法:相當於插隊的方法。如
相對於頭插法,尾插法更加合理一些。
單鏈表的整表刪除
下面是摘自《大話資料結構》的分析:
下面比較一下單鏈表和順序表:
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Java資料結構-線性表之單鏈表LinkedList