手写识别底层原理_LinkedList底层原理和手写单链表
2.1 單鏈表技能點
· 認識單鏈表
o 特點
數據元素的存儲對應的是不連續的存儲空間,每個存儲結點對應一個需要存儲的數據元素。
每個結點是由數據域和指針域組成。 元素之間的邏輯關系通過存儲節點之間的鏈接關系反映出來。邏輯上相鄰的節點物理上不必相鄰。
o 缺點:
1. 比順序存儲結構的存儲密度小 (每個節點都由數據域和指針域組成,
所以相同空間內假設全存滿的話順序比鏈式存儲更多)。
2. 按照索引查找結點時鏈式存儲要比順序存儲慢(每個節點地址不連續、無規律,導致按照索引查詢效率低下。
o 優點:
1. 插入、刪除靈活 (不必移動節點,只要改變節點中的指針,但是需要先定位到元素上)。
2. 有元素才會分配結點空間,不會有閑置的結點。
· 添加節點
· 刪除節點
· 帶頭節點的單鏈表
在使用單鏈表實現線性表的時候,為了使程序更加簡潔,我們通常在單鏈表的最前面添加一個啞元結點,也稱為頭結點。
在頭結點中不存儲任何實質的數據對象,其 next 域指向線性表中 0 號元素所在的結點,
可以對空表、非空表的情況以及對首元結點進行統一處理,編程更方便,常用頭結點。
一個不帶頭結點和帶頭結點的單鏈表實現線性表的結構圖如圖所示。
2.2 手寫單鏈表
? 定義單鏈表節點
【示例5】定義單鏈表節點
public class Node {Object data;//存儲是數據Node next;//指向下個節點的指針public Node() {super();}public Node(Object data) {super();this.data = data;}public Node(Object data, Node next) {super();this.data = data;this.next = next;}//省略setter和getter方法public String toString() {return "Node [data=" + data + ", next=" + next + "]";} }? 手寫單鏈表
【示例6】手寫單鏈表
public class SingleLinkedList implements List { //頭節點 啞巴節點 不存儲數據 為了方便編程private Node head = new Node(); private int size = 0;//節點的個數 public int size() { return size;}public Object get(int i) { //i從0開始 //判斷i的值是否合理if(i<0 || i>=size){throw new IndexOutOfBoundsException("索引越界"+i);}//順藤摸瓜,從第一個節點開始查找Node p = head.next;//p初始指向第一個節點(不是頭節點)for(int j=0;j<i;j++){//p指向下個節點p=p.next;}//return p.data;//返回的不是第i個節點,而是第i個節點的datareturn p;//返回的是第i個節點,而不是第i個節點的data}public boolean isEmpty() {return size==0;}public void add(int i, Object e) {//i值合理性判斷if(i<0 || i>size){throw new IndexOutOfBoundsException("索引越界"+i);} //先找到前一個(如果當前索引是0,前一個就是head)Node p = head;if(i!=0){p = (Node)this.get(i-1);}//創建一個新節點,給data賦值Node newNode = new Node(e); //指定新節點的下一個節點newNode.next = p.next; //指定前一個節點的下個節點是當前新節點p.next = newNode; //數量+1size++;}public void add(Object e) {this.add(size, e); }public Object remove(int i) {//i值合理性判斷if(i<0 || i>=size){throw new IndexOutOfBoundsException("索引越界"+i);}//先找到前一個(如果當前索引是0,前一個就是head)Node p = head;if(i!=0){p = (Node)this.get(i-1);} //指向要刪除的節點Node currNode = p.next; //完成刪除操作p.next = currNode.next;currNode.next = null;currNode = null;//提示將要刪除的節點變成垃圾 //數量-1size--;return null;}public String toString() {StringBuilder builder = new StringBuilder("[");Node p = head.next;//p初始指向第一個節點(不是頭節點)for(int j=0;j<size;j++){builder.append(p.data+" ");//p指向下個節點p=p.next;}builder.append("]");return builder.toString();} }單鏈表添加刪除查詢原理
? 測試單鏈表
【示例7】測試單鏈表
public class TestList {public static void main(String[] args) {java.util.ArrayList list2;//創建線性順序表List list = new SingleLinkedList();//向末尾添加元素list.add("11111");list.add("aaaaa");list.add("bbbbb");list.add("33333");list.add("22222");list.add(3, "AAAAA");list.remove(2);//進行各種操作驗證添加System.out.println(list.size());System.out.println(list.isEmpty());System.out.println(list.contains("44444"));System.out.println(list.indexOf("22222"));System.out.println(list.toString());} }2.3 手寫LinkedList
· LinkedList底層原理
2 LinkedList底層是一個雙向鏈表;添加、刪除元素效率高;按照索引查詢效率低??梢詢蓚€方向查詢
2 每個節點都包含了對前一個和后一個元素的引用
2 LinkedList同時實現了List、Deque、Queue接口,所以可以當做線性表、隊列、雙端隊列、棧使用
2 LinkedList 是非同步的(線程不安全)
2 不存在LinkedList容量不足的問題
· 定義LinkedList節點
【示例8】定義LinkedList節點
public class LinkedList implements List {/*** 靜態內部類 代表LinkedList的每個節點*/private static class Node<E> {E item;Node<E> next;Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}@Overridepublic String toString() {return "Node{" +"item=" + item +", next=" + next +'}';}} }· 手寫LinkedList
【示例9】手寫LinkedList
public class LinkedList implements List {transient int size = 0;transient Node first;transient Node last;public int size() {return size;}public Object get(int i) {return node(i).item;}public boolean isEmpty() {return size ==0;}public void add(int index, Object element) {if (index == size)linkLast(element);elselinkBefore(element, node(index));}Node node(int index) {if (index < (size >> 1)) {Node x = first;for (int i = 0; i < index; i++)x = x.next;return x;} else {Node x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}}void linkBefore(Object e, Node succ) {final Node pred = succ.prev;final Node newNode = new Node<>(pred, e, succ);succ.prev = newNode;if (pred == null)first = newNode;elsepred.next = newNode;size++;}public void add(Object e) {linkLast(e);}public void linkLast(Object e) {final Node l = last;final Node newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;}public String toString() {return first.toString();} }下面是LinkedList的add(Object)方法的實現過程
· 測試LinkedList
【示例10】測試LinkedList
public class TestList {public static void main(String[] args) {//創建線性順序表List list = new LinkedList();//向末尾添加元素list.add("11111");list.add("aaaaa");list.add("bbbbb");list.add("33333");list.add("22222");list.add(3, "AAAAA");//進行各種操作驗證添加System.out.println(list.size());System.out.println(list.isEmpty());//System.out.println(list.toString());System.out.println(list.get(0));} }本節作業
1. 單鏈表和雙鏈表的特點;為什么給鏈表添加一個頭結點
2. 實現單鏈表的刪除方法:刪除單鏈表的第i個節點
public Object remove(int i) {
}
3. 實現LinkedList的在末尾元素節點的方法
public void linkLast(Object e) {
}
總結
以上是生活随笔為你收集整理的手写识别底层原理_LinkedList底层原理和手写单链表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql数据通讯方式_c# 与 Mys
- 下一篇: android 模糊度处理_图像处理评价