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