【資料結構】單向連結串列——用Java手寫一個單向連結串列
阿新 • • 發佈:2021-02-05
技術標籤:資料結構連結串列資料結構java演算法單向連結串列
目錄
前言
單向連結串列比順序結構的線性表最大的好處就是不用保證存放的位置,它只需要用指標去指向下一個元素就能搞定。
單鏈表圖解
圖畫的比較粗糙,簡單的講解一下:
上面四個長方形,每個長方形都是一個節點。在長方形中,一種包含兩個東西,一個是當前節點的元素,一個是指向下一節點的地址。這個下一個節點的地址指向了下一個節點中的元素。以此類推。
在最左邊的叫做頭節點,同樣,最後面的叫尾節點。
所以,我們所有的操作都是根據節點來進行操作。
程式碼
這些程式碼都有很詳細的註釋,我就不做過多的解釋了,你直接複製程式碼到本地idea執行一遍就全部知道了。
package com.zxy.lianbiao;
/**
* @Author Zxy
* @Date 2021/2/3 21:25
* @Version 1.0
*/
/**
* 基於單向連結串列實現元素的存取
*
* @param <E>
*/
public class MySinglyLinkedList<E> implements MyList<E> {
/**
* 定義單向連結串列中的節點物件
*/
class Node<E> {
private E item; // 儲存元素
private Node next; // 儲存下一個節點物件
public Node(E item, Node next) {
this.item = item;
this.next = next;
}
}
private Node head; // 存放連結串列中的頭節點
private int size; // 記錄元素的個數
/**
* 向連結串列中新增元素
*
* @param element
*/
@Override
public void add(E element) {
// 建立節點
Node<E> node = new Node<>(element, null);
// 找到尾節點
Node tail = getTail();
// 節點的掛接
if (tail == null) { // 如果沒有尾節點,那意思就是頭節點都不存在
// 沒有頭節點,那麼就把建立的節點給頭節點
this.head = node;
} else {
tail.next = node;
}
// 記錄元素的個數
this.size++;
}
/**
* 找尾節點
*/
private Node getTail() {
// 判斷頭節點是否存在
if (this.head == null) {
return null;
}
// 查詢尾節點
Node node = this.head;
while (true) {
if (node.next == null) {
break;
}
node = node.next; // 移動指標指向下一個
}
return node;
}
/**
* 根據元素的位置獲取元素
*
* @param index
* @return
*/
@Override
public E get(int index) {
// 校驗index的合法性
this.checkIndex(index);
// 根據位置獲取指定節點
Node<E> node = this.getNode(index);
// 將該節點中的元素返回
return node.item;
}
/**
* 對index進行校驗
*/
private void checkIndex(int index) {
// 0<=index<size
if (!(index >= 0 && index < this.size)) {
throw new IndexOutOfBoundsException("Index: " + index + " this.size: " + this.size);
}
}
/**
* 根據位置獲取節點
*/
private Node<E> getNode(int index) {
Node<E> node = this.head;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
/**
* 獲取元素的個數
*
* @return
*/
@Override
public int size() {
return this.size;
}
/**
* 根據元素位置刪除元素
*
* @param index
* @return
*/
@Override
public E remove(int index) {
// 校驗index合法性
this.checkIndex(index);
// 根據位置找到節點物件
Node<E> node = getNode(index);
// 獲取該節點物件中的元素
E item = node.item;
// 將該節點物件從單向連結串列中移除
// 判斷當前刪除的節點是否為頭節點
if (this.head == node) {
this.head = node.next;
} else {
Node<E> temp = this.head;
for (int i = 0; i < index - 1; i++) {
temp = temp.next; // 此時的temp就是要刪除的那個節點的前一個節點
}
temp.next = node.next; // 將當前節點的前一個節點指向當前節點的後一個節點
}
// 然後將當前節點的下一個節點指向null
node.next = null;
// 記錄元素個數
this.size--;
// 將該元素返回
return item;
}
/**
* 插入節點思路:如果當前共有三個節點分別是1,2,3,在1和2的中間插入4,原本的指向是1->2 現改變成1->4 4->2 先獲取到指定位置的node,再獲取到前一個位置的node和下一個位置的node
*/
public void insert(int index, E element) {
// 先根據要插入的位置拿到這個位置的節點物件
Node<E> item = getNode(index);
// 根據插入的元素新建一個節點
Node<E> eNode = new Node<>(element, null);
// 如果是頭節點,那麼就找不到前一個,直接把這個賦值給head
if (index == 0){
// index==0代表是替換掉頭節點
this.head = eNode;
eNode.next = item;
this.size++;
}else {
// 根據當前的節點物件去找到前一個節點物件和後一個節點物件
Node<E> before = this.head; // 根據頭節點去找
for (int i = 0; i < index - 1; i++) {
before = before.next; // 此時的before就是當前節點的前一個節點
}
before.next = eNode;
eNode.next = item;
this.size++;
}
}
public static void main(String[] args) {
MySinglyLinkedList<String> list = new MySinglyLinkedList<>();
System.out.println("新增節點開始------------------------");
list.add((String) "a");
list.add((String) "b");
list.add((String) "c");
list.add((String) "d");
System.out.println("新增節點完成-------------------------\n");
System.out.println("插入指定的元素");
list.insert(0,"f");
for (int i = 0; i < list.size; i++) {
System.out.println(list.get(i));
}
}
}
實現的介面都是自己手寫,就程式碼塊中定義的一些方法而已,你也可以不去實現這些介面自己去寫方法名也一樣。