單鏈表:
概念:
1、由於線性表的順序存儲在插入與刪除時需要移動大量元素,適用於不經常改變元素的情況,那么當我們需要經常操作元素時該怎么辦,這就有了接下來的線性表的鏈式存儲結構
2、單鏈表在內存的存儲位置不一定是一段連續的位置,它可以存放在內存中任何地方
3、單鏈表中除了用於存放數據的數據域外,還有存放指針的指針域,指針域的作用是指向鏈表的下一個節點(因為鏈表的元素在內存中的存放時任意位置的,所以需要指向下一個節點)
4、單鏈表第一個節點存儲的位置叫做頭指針,整個單鏈表的存取都是從頭指針開始,單鏈表的最后一個節點是指針指向空(NULL)
單鏈表的操作:
1 package com.alibaba.test03; 2 3 import org.junit.jupiter.api.Test; 4 5 6 /** 7 * 1. 單鏈表的具體實現及操作 8 * @author wydream 9 * 10 */ 11 12 public class SingLeLinkedList { 13 14 private int size;//鏈表節點的個數 15 private Node head;//頭結點 16 17 public SingLeLinkedList() { 18 size=0; 19 head=null; 20 } 21 22 //鏈表中的每個節點類 23 private class Node{ 24 private Object data;//每個節點的數據 25 private Node next;//每個節點指向下一個節點的連接 26 27 public Node(Object data){ 28 this.data=data; 29 } 30 } 31 32 //在表頭添加元素 33 public Object addHead(Object obj) { 34 Node newHead=new Node(obj); 35 36 if(size==0) { 37 head=newHead; 38 }else { 39 newHead.next=head; 40 head=newHead; 41 } 42 size++; 43 return obj; 44 } 45 46 //在鏈表頭刪除元素 47 public Object deleteHead() { 48 Object obj=head.data; 49 head=head.next; 50 size--; 51 return obj; 52 } 53 54 //查找指定元素,找到了返回元素Node,找不到返回Null 55 public Node find(Object obj) { 56 Node current=head; 57 int tempSize=size; 58 while(tempSize>0) { 59 if(obj.equals(current.data)) { 60 return current; 61 }else { 62 current=current.next; 63 } 64 tempSize--; 65 } 66 return null; 67 } 68 69 70 //刪除指定的元素,刪除成功則返回true 71 public boolean delete(Object value) { 72 73 if(size==0) { 74 return false; 75 } 76 77 Node current=head; 78 Node previous=head; 79 while(current.data!=value) { 80 if(current.next==null) { 81 return false; 82 }else { 83 previous=current; 84 current=current.next; 85 } 86 } 87 88 //如果刪除的是第一個節點 89 if(current==head) { 90 head=current.next; 91 size--; 92 }else {//刪除的不是第一個節點 93 previous.next=current.next; 94 size--; 95 } 96 return true; 97 } 98 99 //判斷鏈表是否為空 100 public boolean isEmpty() { 101 return size==0; 102 } 103 104 //顯示節點信息 105 public void display() { 106 if(size>0) { 107 Node node=head; 108 int tempSize=size; 109 if(tempSize==1) {//當前鏈表只有一個節點 110 System.out.println("["+node.data+"]"); 111 return; 112 } 113 while(tempSize>0) { 114 if(node.equals(head)) { 115 System.out.print("["+node.data+"->"); 116 }else if(node.next==null){ 117 System.out.print(node.data+"]"); 118 }else { 119 System.out.print(node.data+"->"); 120 } 121 node=node.next; 122 tempSize--; 123 } 124 System.out.println(); 125 }else {//如果鏈表一個節點都沒有,直接打印 126 System.out.print("[]"); 127 } 128 } 129 130 @Test 131 public void test() { 132 SingLeLinkedList s=new SingLeLinkedList(); 133 s.addHead("1"); 134 s.addHead("2"); 135 s.addHead("3"); 136 s.addHead("4"); 137 s.deleteHead(); 138 s.display(); 139 } 140 141 142 143 144 }
有序鏈表:
概念:
- 前面的鏈表實現插入數據都是無序的,在有些應用中需要鏈表中的數據有序,這稱為有序鏈表。
- 在有序鏈表中,數據是按照關鍵值有序排列的。一般在大多數需要使用有序數組的場合也可以使用有序鏈表。有序鏈表優於有序數組的地方是插入的速度(因為元素不需要移動),另外鏈表可以擴展到全部有效的使用內存,而數組只能局限於一個固定的大小中。
有序鏈表的實現:
1 /** 2 * 3 * @author wydream 4 * 5 */ 6 7 public class OrderLinkedList { 8 9 private Node head; 10 11 private class Node{ 12 private int data; 13 private Node next; 14 15 public Node(int data) { 16 this.data=data; 17 } 18 } 19 20 public OrderLinkedList() { 21 head=null; 22 } 23 24 //插入節點,並按從小到大的順序排列 25 public void insert(int value) { 26 Node node=new Node(value); 27 Node pre=null; 28 Node current=head; 29 while(current!=null&&value>current.data) { 30 pre=current; 31 current=current.next; 32 } 33 if(pre==null) { 34 head=node; 35 head.next=current; 36 }else { 37 pre.next=node; 38 node.next=current; 39 } 40 } 41 42 //刪除頭節點 43 public void deleteHead() { 44 head=head.next; 45 } 46 47 public void display() { 48 Node current=head; 49 while(current!=null) { 50 System.out.println(current.data+" "); 51 current=current.next; 52 } 53 System.out.println(""); 54 } 55 56 57 58 }
雙向鏈表:
概念:
我們知道單向鏈表只能從一個方向遍歷,那么雙向鏈表它可以從兩個方向遍歷。
雙向鏈表的實現:
1 import org.junit.jupiter.api.Test; 2 3 /** 4 * 雙向鏈表的實現 5 * @author wydream 6 * 7 */ 8 9 public class TwoWayLinkedList { 10 11 private Node head;//鏈表頭 12 private Node tail;//鏈表尾 13 private int size;//鏈表長度 14 15 16 private class Node{ 17 private Object data; 18 private Node next; 19 private Node prev; 20 21 public Node(Object obj){ 22 this.data=obj; 23 } 24 25 } 26 27 public TwoWayLinkedList(){ 28 size=0; 29 head=null; 30 tail=null; 31 } 32 33 //在表頭添加新節點 34 public void addHead(Object obj) { 35 Node node=new Node(obj); 36 //如果鏈表長度為零,則添加的這個元素就是頭節點和尾節點 37 if(size==0) { 38 head=node; 39 tail=node; 40 }else { 41 head.prev=node; 42 node.next=head; 43 head=node; 44 } 45 46 size++; 47 } 48 49 //在鏈表尾添加新節點 50 public void addEnd(Object obj) { 51 Node newNode=new Node(obj); 52 if(size==0) { 53 head=newNode; 54 tail=newNode; 55 }else { 56 tail.next=newNode; 57 newNode.prev=tail; 58 tail=newNode; 59 } 60 size++; 61 } 62 63 //刪除鏈表頭 64 public Node deleteHead() { 65 Node temp=head; 66 if(size!=0) { 67 head=head.next; 68 head.prev=null; 69 size--; 70 } 71 return temp; 72 } 73 74 75 //刪除鏈表尾 76 public void deleteEnd() { 77 Node end=tail; 78 if(size!=0) { 79 tail=tail.prev; 80 tail.next=null; 81 size--; 82 } 83 } 84 85 86 //獲取鏈表節點個數 87 public int getLength() { 88 return size; 89 } 90 91 //判斷鏈表是否為空 92 public boolean isEmpty() { 93 if(size>0) { 94 return true; 95 } 96 return false; 97 } 98 99 //顯示節點信息 100 public void display() { 101 if(size>0) { 102 Node node=head; 103 int tempSize=size; 104 if(tempSize==1) { 105 System.out.println("["+node.data+"]"); 106 return; 107 } 108 while(tempSize>0) { 109 if(node.equals(head)) { 110 System.out.print("["+node.data+"->"); 111 }else if(node.equals(tail)) { 112 System.out.print(node.data+"]"); 113 }else { 114 System.out.print(node.data+"->"); 115 } 116 node=node.next; 117 tempSize--; 118 } 119 System.out.println(); 120 }else { 121 System.out.println("[]"); 122 } 123 124 } 125 126 @Test 127 public void test() { 128 TwoWayLinkedList tl=new TwoWayLinkedList(); 129 tl.addEnd("1"); 130 tl.addEnd("2"); 131 tl.addEnd("3"); 132 tl.addEnd("4"); 133 tl.deleteHead(); 134 tl.deleteEnd(); 135 tl.display(); 136 } 137 138 139 }