数据结构-链表结构
鏈表結構
鏈表結構的定義
什么是鏈表
鏈表結構是由多個節點構成的,每個節點都包含著兩部分:
- 數據部分:
- 保存該節點的實際數據
- 指針部分:
- 指向上一個節點或者下一個節點
鏈表分類
- 單向鏈表
- 雙向鏈表
- 雙向循環鏈表
鏈表的特點
- 節點在存儲器中的位置是任意的,即邏輯上相鄰的數據元素在物理上不一定相鄰。
- 訪問時只能通過頭或者尾指針進入鏈表,并通過每個節點的指針域向后或向前掃描其余節點,所以尋找第一個結點和最后一個結點所花費的時間不等。
鏈表的優缺點:
優點:
- 數據元素的個數可以自由擴充,插入,刪除,等操作不必移動數據,只需修改鏈表指針,修改效率較高;
缺點:
- 必須采用循環存取,即存取數據元素時,只能按元素的順序來進行訪問,訪問節點效率較低;
單向鏈表
單向鏈表定義
特是鏈表的方向是單向的,對鏈表的訪問要通過頭指針從頭節點開始順序的讀取
實現單項鏈表
MyList
public interface MyList<E> {//添加節點數據void add(E element);//獲取節點數據E get (int index);//獲取鏈表長度int size();//根據指針移除節點E remove(int index);}MyLinkedList
public class MyLinkedList<E> implements MyList<E>{private Node head; //存放鏈表的頭節點private int size;//記錄鏈表長度/*** 向鏈表中添加節點* @param element*/@Overridepublic void add(E element) {//創建節點Node<E> node = new Node<>(element,null);//找到尾節點Node tial = getTail();//節點的連接if (tial == null){this.head = node;}else {tial.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*/@Overridepublic E get(int index) {//校驗index的合法性this.pointerIndex(index);//根據位置獲取對應的節點數據Node<E> node = getNode(index);//將節點中的元素返回return node.item;}/*** 根據index進行校驗*/private void pointerIndex(int index){if (!(index >= 0 && index < this.size)){int a = this.size-1;throw new IndexOutOfBoundsException("你輸入的指針為:"+ index +"指針最大為:"+a);}}/*** 根據指針獲取節點*/private Node getNode(int index){Node<E> node = this.head;for (int i = 0 ; i < index;i++){node = node.next;}return node;}/*** 獲取鏈表長度(個數)* @return*/@Overridepublic int size() {return this.size;}/*** 根據指針移除對應的節點* @param index* @return*/@Overridepublic E remove(int index) {//校驗index的合法性this.pointerIndex(index);//根據index指針找到該節點對象數據Node<E> node = this.getNode(index);//獲取該節點對象中的元素E item = node.item;//向該節點對象中單向鏈表刪除//判斷當前刪除的節點是否為頭節點if (this.head == node){this.head = node.next;//如果是刪除頭節點,頭節點的下一個節點,賦值給了頭節點}else {Node<E> node1 = this.head;//拿頭節點for (int i = 0 ; i<index - 1 ; i++){node1=node1.next;}node1.next = node.next;//將節點的下一個節點賦值給該節點}node.next = null;this.size -- ;//刪除成功長度減一return item;//返回元素}/*** 定義單向鏈表中的節點對象* @param <E>*/class Node<E>{private E item;//儲存的元素private Node next;//儲存下一個節點對象的地址public Node() {}Node(E item , Node next){this.item = item;this.next = next;}}}測試
public static void main(String[] args) {MyLinkedList myLinkedList = new MyLinkedList();myLinkedList.add(12);myLinkedList.add(13);myLinkedList.add(14);myLinkedList.add(15);myLinkedList.add(16);System.out.println("根據指針找到值"+myLinkedList.get(4));System.out.println("刪除的節點"+myLinkedList.remove(0));System.out.println(myLinkedList);System.out.println(myLinkedList.size());for (int i=0;i<myLinkedList.size(); i++){System.out.print(myLinkedList.get(i)+",");}}雙向循環鏈表
雙向循環鏈表的定義
雙向循環鏈表,也是鏈表的的一種,它的每個數據節點中都有兩個指針,分別指向前驅和后繼。
MyList
public interface MyList<E> {//添加節點數據void add(E element);//獲取節點數據E get (int index);//獲取鏈表長度int size();//根據指針移除節點E remove(int index);//從頭添加元素void addFirst(E element);//從尾添加元素void addLast(E element); }MyDoubleLinkedList
public class MyDoubleLinkedList<E> implements MyList<E> {private int size;//記錄元素的個數private Node head ;// 記錄頭節點private Node tail;//記錄尾節點/*** 向雙向鏈表中添加元素數據* @param element*/@Overridepublic void add(E element) {this.linkLast(element);}/*** 將節點對象添加到雙向鏈表的尾部* @param element*/private void linkLast(E element){//獲取尾節點Node t = this.tail;Node<E> node = new Node<>(t,element,null);//將新節點定義為尾節點this.tail = node;if (t == null){//當t等于空的時候說明這個鏈表是個空鏈表this.head=node;//將向的元素數據賦值到頭節點}else{t.next=node;//否則將新元素賦值到尾節點之后}this.size++;//添加成功長度自增加一}/*** 根據指針獲取對應的元素數據* @param index* @return*/@Overridepublic E get(int index) {//對index做合法性校驗this.rangeCheck(index);Node<E> node = this.getNode(index);return node.item;}/*** 判斷當前index的合法性*/private void rangeCheck(int index){if(!(index >=0 && index < this.size)){int a = this.size-1;throw new IndexOutOfBoundsException("您輸入的索引為:"+index+"它的指針長度為:"+a);}}/*** 根據位置獲取指定的節點對象* @param index* @return*/private Node getNode(int index){//判斷當前輸入的指針距離頭或者尾哪個節點近//如果輸入的指針大,從尾部開始找,//如果輸入的指針小,從頭部開始找if (index < (this.size >> 1)){Node node = this.head;//遍歷指針for(int i =0; i < index;i++){//拿到指針處的下一個節點對象賦值nodenode=node.next;}return node;}else {Node node = this.tail;//從尾節點找指針for (int i = this.size-1; i>index; i--){node = node.prev;}return node;}}/*** 獲取元素的長度(個數)* @return*/@Overridepublic int size() {return this.size;}/*** 根據指定指針刪除元素* @param index* @return*/@Overridepublic E remove(int index) {//對index指針進行合法性校驗this.rangeCheck(index);//根據index進行獲取節點對象,判斷從頭刪還是從尾部刪除Node<E> node = this.getNode(index);//獲取index指針處的節點元素數據E item = node.item;//判斷當前節點是否尾頭節點if (node.prev == null){this.head = node.next;}else {//完成當前節點的直接前驅節點和當前節點的直接后繼節點,掛接node.prev.next = node.next;}//當前節點斷掉與它直接前驅點的連接node.prev = null;//當前節點斷掉與他直接后繼節點的連接node.next =null;node.item =null;//長度自減一this.size--;//返回被刪除的節點元素數據return item;}//從頭開始添加元素@Overridepublic void addFirst(E element) {this.linkFirst(element);}//從尾部添加元素@Overridepublic void addLast(E element) {this.linkLast(element);}//在鏈表的頭添加元素private void linkFirst(E element){//獲取頭節點對象Node head = this.head;Node node = new Node(null,element,head);//將新節點定義為頭節點this.head = node;//判斷當前鏈表中是否有節點,如果沒有該節則是頭節點也是尾節點if(this.head == null){this.tail = node;}else {this.head.prev = node;}this.size++;//記錄鏈表長度}/*** 創建節點類* @param <E>*/class Node<E> {private E item;//記錄元素private Node<E> next; // 下一個節點對象private Node<E> prev; // 上一個節點對象Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}} }測試
public class MyLinkedMain {public static void main(String[] args) {MyDoubleLinkedList linkedList = new MyDoubleLinkedList();linkedList.add(12);linkedList.add(13);linkedList.add(14);linkedList.add(15);linkedList.add(16);System.out.println(linkedList.get(3));//3是指針,從尾部開始找System.out.println(linkedList.get(4));//4是指針,從尾部開始找System.out.println(linkedList.get(1));//1是指針,從頭部開始找System.out.println(linkedList.size());//獲取linkedList長度System.out.println("刪除前的指針1處的數據"+linkedList.get(1));System.out.println(linkedList.remove(1));System.out.println("刪除后的指針1處的數據"+linkedList.get(1));System.out.println("刪除前的指針0處的數據"+linkedList.get(4));System.out.println(linkedList.remove(4));try {System.out.println("刪除后的指針0處的數據"+linkedList.get(4));}catch (Exception e) {e.printStackTrace();}finally {System.out.println("刪除后的鏈表長度"+linkedList.size());//獲取linkedList長度}} }總結
- 上一篇: Linux内核(八) PHY状态机以及网
- 下一篇: java数据结构-链表详解