1. 程式人生 > >資料結構(二)--- 線性錶鏈表(單鏈表)java實現方式

資料結構(二)--- 線性錶鏈表(單鏈表)java實現方式

線性表的鏈式儲存結構:所有元素不考慮相鄰位置,哪有空位置就到那裡,而只是讓每個元素知道它下一個元素的位置在那裡,這樣,我們可以在第一個元素時,就知道第二個元素的位置(記憶體地址),而找到它;在第二個元素時,再找到第三個元素的位置,這樣所有的元素就可以通過遍歷而找到。
這裡寫圖片描述
連結串列中的第一個結點的儲存位置叫做頭指標,最後一個結點的指標為空
這裡寫圖片描述
在單鏈表的第一個結點前附設一個結點,稱為頭結點
這裡寫圖片描述
單鏈表的插入和刪除
這裡寫圖片描述
刪除操作:
插入元素e的結點為s,只需要將s插入到結點P 和p.next之間就行。
s.next=p.next p.next=s
這裡寫圖片描述
如果將p.next=s;再 s.next=p.next; 第一句p.next會覆蓋s的地址,就等於s.next=s,真正擁有ai+1資料元素的結點就沒上級了,要注意。不能寫反。
刪除操作:
這裡寫圖片描述


刪除ai元素時,只需要將ai+1指向ai-1就可以。
單鏈表LinkList

package likend;

/**
 * Created by yxf on 2018/3/24.
 * 線性表 單鏈表
 */
public class LinkList<T> {

    private Node header;//儲存頭結點
    private int size;  //連結串列長度

    public class Node<T> {
        private T data;   //資料
        private Node next; //指向下一個節點的引用
public Node() { } public Node(T data, Node next) { this.data = data; this.next = next; } } public LinkList() { } /** * 在頭結點插入 * 連結串列中第一個結點儲存位置叫做頭指標 頭節點只儲存頭指標 * 所以這是插入的是第一個節點 * * @param element * @return
*/
public boolean addHead(T element) { //如果第一個連結串列為空 if (header == null) { header = new Node(element, null); } else { Node newNode = new Node(element, null); Node temp = header; newNode.next = temp; //將新插入的節點的next指向頭節點的下一個節點 header = newNode; //將新插入的節點指向頭結點的下一個節點 連結串列就連結上了 } size++; return true; } /** * 在尾部插入 * * @param element * @return */ public boolean add(T element) { //如果第一個連結串列為空 if (header == null) { header = new Node(element, null); } /*else { int length = getSize(); Node currentNode = getNodeByIndex(length-1); Node newNode = new Node(element, null); currentNode.next = newNode; }*/ else { Node currentNode = header; while (currentNode.next != null) { currentNode = currentNode.next; //找到新增結點的上一個結點 } Node newNode = new Node(element, null); currentNode.next = newNode; } size++; return true; } /** * 獲取指定位置結點 * * @param index * @return */ public Node getNodeByIndex(int index) { if (index < 0 || index > size) { throw new IndexOutOfBoundsException("獲取位置超過連結串列長度範圍"); } Node current = header; //從連結串列第一個遍歷 因為頭結點是指標 for (int i = 0; i <= size && current != null; i++, current = current.next) { if (i == index) return current; } return null; } /** * 獲取指定索引處的元素 * * @param index * @return */ public T getElement(int index) { return (T) getNodeByIndex(index).data; } public int getIndex(T element) { Node current = header; for (int i = 0; i < size && current != null; i++, current = current.next) { if (current.data.equals(element)) return i; } return -1; } /** * 在指定位置插入元素 * * @param index * @param element * @return */ public boolean insert(int index, T element) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("插入位置超出連結串列範圍"); /* //如果第一個連結串列為空 if (header == null) { add(element); } else { if (index == 0) { addHead(element); } else { //獲取插入位置的前一個結點 Node preNode = getNodeByIndex(index - 1); preNode.next = new Node(element, preNode.next); size++; } }*/ if (index == 0) { addHead(element); } else { Node preNode = header; for (int i = 0; i < index - 1; i++) { preNode = preNode.next; //獲得插入結點的前驅結點 } Node newNode = new Node(element, null); newNode.next = preNode.next; preNode.next = newNode; size++; } return true; } /** * 刪除元素 * * @param index * @return */ public T delete(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("刪除位置超出連結串列範圍"); /* Node delNode = null; //刪除的是第一個節點 if (index == 0) { delNode = header; header = header.next; } else { Node preNode = getNodeByIndex(index - 1); //獲取刪除結點的上一個結點 delNode = preNode.next; //獲取要刪除的結點 preNode.next = delNode.next; //將要刪除結點的下一個結點賦值給刪除結點的上一個結點 }*/ Node currentNode = header; if (index == 0) { header = header.next; currentNode.next=null; } else { Node currentNodeBefore = null; for (int i = 0; i < index; i++) { currentNodeBefore = currentNode; //前置結點 currentNode = currentNode.next; //要刪除的當前結點 } currentNodeBefore.next = currentNode.next; } size--; return (T) currentNode.data; } /** * 獲取指定元素的前驅 * * @param currentElem * @return */ public T priorElement(T currentElem) { int index = getIndex(currentElem); if (index == -1) return null; else { if (index == 0) { return null; } else { return (T) getNodeByIndex(index - 1).data; } } } /** * 獲取指定元素的後驅 * * @param currentElem * @return */ public T nextElement(T currentElem) { int index = getIndex(currentElem); if (index == -1) return null; else { if (index == size - 1) { return null; } else { return (T) getNodeByIndex(index + 1).data; } } } //刪除最後一個元素 public T remove() { return delete(size - 1); } /** * 獲取連結串列大小 * * @return */ public int getSize() { return size; } //檢查連結串列是否為空 public boolean isEmpty() { return size == 0; } public void clear() { header = null; size = 0; } @Override public String toString() { if (isEmpty()) return "[]"; else { StringBuilder sb = new StringBuilder("["); for (Node current = header; current != null; current = current.next) sb.append(current.data + "->").toString(); int len = sb.length(); return sb.delete(len - 2, len).append("]").toString(); } } }

測試 LinkListTest

package likend;

/**
 * Created by yxf on 2018/3/25.
 */
public class LinkListTest {

    public static void main(String[] args) {
        LinkList ls = new LinkList();

        ls.add(2);
        ls.add(4);
        ls.add(5);
        ls.addHead(1);
        System.out.println("新增元素後的連結串列為: "+ls);
        ls.insert(3,3);
        System.out.println("在連結串列位置3插入元素: "+ls);
        ls.delete(3);
        System.out.println("在連結串列位置3刪除元素: "+ls);
        ls.remove();
        System.out.println("刪除連結串列中的一個元素: "+ls);
        System.out.println("獲得連結串列位置為2處的元素:   "+ ls.getElement(2));
        System.out.println("獲取元素2的前驅元素:    "+ls.priorElement(2));
        System.out.println("獲取元素2的後驅元素:    "+ls.nextElement(2));
        ls.clear();
        System.out.println(ls);
    }
}

測試結果

新增元素後的連結串列為: [1->2->4->5]
在連結串列位置3插入元素: [1->2->4->3->5]
在連結串列位置3刪除元素: [1->2->4->5]
刪除連結串列中的一個元素: [1->2->4]
獲得連結串列位置為2處的元素:   4
獲取元素2的前驅元素:    1
獲取元素2的後驅元素:    4
[]

Process finished with exit code 0