链表是用指针将多个节点联系在一起,通过头节点和尾节点还有节点数量,可以对链表进行一系列的操作。是线性表的链式存储实现。
1.链表是多个不连续的地址组成在一起根据指针链接在一起的,由多个节点组成,每个节点包括元素域和指针域
2.元素域存储节点数组,指针域存储下一节点指针
3.我们对链表的操作都是间接的通过链表头节点操作来实现的
4.一个链表中有多个节点,一个节点包括元素域,和下一节点指针域
5.最左边的节点是头节点,但是添加节点是从右到左添加,新添加的节点会被作为头节点
6.链表是由不定数量的节点连接(通过相互之间的引用)起来的,由于这种关系,在链表里我们只定义了头节点和节点数量。节点是由存储的对象及对下一个“节点”的引用封装而成。
7.在添加节点到链表中时,首先添加的节点后置后,新添加的节点作为头节点引用前一个添加的节点。
//先创建一个节点类
1 package linkedList; 2 //节点类 3 public class Node<E> { 4 protected Object data = null; //数据域 5 protected Node<E> next = null; //指针域 6 7 //初始化数据域 8 public Node(E e, Node<E> next) { 9 this.data = e; //初始化数据域 10 this.next = next; //初始化指针域 11 } 12 13 //显示节点,获取当前实体对象,数据域 14 public Object getData(){ 15 return this.data; 16 } 17 18 //获取下一个实体,指针域 19 public Node<E> getNext(){ 20 return this.next; 21 } 22 23 @Override 24 public String toString() { 25 return "Node [data=" + data + ", next=" + next + "]"; 26 } 27 28 }
//然后创建我们的链表类,将节点作为链表的属性
1 package linkedList; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * 1.链表是多个不连续的地址组成在一起根据指针链接在一起的,由多个节点组成,每个节点包括元素域和指针域 8 * 2.元素域存储节点数组,指针域存储下一节点指针 9 * 3.我们对链表的操作都是间接的通过链表头节点操作来实现的 10 * 4.一个链表中有多个节点,一个节点包括元素域,和下一节点指针域 11 * 5.最左边的节点是头节点,但是添加节点是从右到左添加,新添加的节点会被作为头节点 12 * 6.链表是由不定数量的节点连接(通过相互之间的引用)起来的,由于这种关系,在链表里我们只定义了头节点和节点数量。节点是由存储的对象及对下一个“节点”的引用封装而成。 13 * 7.在添加节点到链表中时,首先添加的节点后置后,新添加的节点作为头节点引用前一个添加的节点。 14 * @author LH-PC 15 * 16 */ 17 public class LinkedList<E> implements java.io.Serializable{ 18 private static final long serialVersionUID = 1L; 19 20 private Node<E> head; //头节点 21 private int size; //节点数量,即链表长度 22 23 24 //添加头节点 在添加链表节点时,首先添加的节点(头节点)后置,新添加的节点变成头节点,并且执向前一个头节点 25 public void addNode(E e){ 26 //判断链表中有无该对象:从头节点开始遍历,匹配有无此对象 27 //如果有头节点,则添加新的节点为头节点,新的头节点指向上一个头节点 28 if(head != null){ 29 System.out.println("链表中已经存在头节点, 正在添加新的头节点:" + e); 30 System.out.println("添加成功! 此头节点指向->" + head.data); 31 this.head = new Node<E>(e, head); //将新添加的节点作为头节点,指针域指向上一个头节点 32 size ++; //节点数量++ 33 34 }else { 35 //如果没有头节点,则添加新的对象作为头节点,第一个头节点指向null 36 System.out.println("链表中不存在头节点,正在添加头节点:" + e); 37 this.head = new Node<E>(e, null); 38 System.out.println("添加成功!头节点指向->" + null); 39 size ++; //节点数量++ 40 } 41 } 42 43 //在指定位置插入节点 44 public int insert(int index, E e){ 45 Node<E> temp = this.head; 46 int i = 0; 47 if(index < i || i > this.size){ 48 System.err.println("索引大于链表长度或者小于0:" + index); 49 return -1; 50 } 51 52 if(index == 0){ 53 //如果index == 0,插入到头节点之后 54 this.head.next = new Node<E>(e, head.next); //将头节点指向新节点,将新节点指向原来头节点的下一个节点 55 size ++; //节点数量加1 56 return 1; 57 } 58 59 //遍历链表 60 while(temp != null){ 61 //运动到了指定位置 62 if(index == i){ 63 temp.next = new Node<E>(e, temp.next); //将插入进来的指针域指向当前节点,将当前节点的上一个节点指针域指向当前节点 64 size ++; //节点长度加1 65 break; 66 } 67 temp = temp.next; //向下一个节点运动 68 i ++; 69 } 70 71 return 1; 72 } 73 74 //删除头节点 75 public void deleteByHead(){ 76 //1.找到头节点。this.head 77 //2.更新头节点。将当前链表头节点设置为删除头节点的指针域 78 //3.链表节点数量-1 79 System.out.println("正在删除头节点:" + this.head.getData()); 80 this.head = this.head.next; //更新头节点为下一节点 81 size --; //节点数量-1 82 System.out.println("删除成功"); 83 84 } 85 86 //删除指定位置的节点 87 public void deleteByIndex(int index){ 88 //找到指定位置的前一个节点,将前一个节点指向后面两个节点。中间的节点就将被删除了。 89 Node<E> temp = this.head; 90 int i = 0; 91 if(index < i || index > this.size){ 92 System.err.println("索引不能小于0或大于链表长度:" + index); 93 return; 94 } 95 96 //如果索引为0,表示删除头节点 97 if( index == 0){ 98 this.deleteByHead(); //调用删除头节点方法 99 return; 100 } 101 102 //遍历链表 103 while(temp != null){ 104 //找到目标节点的上一个节点 105 if(index-1 == i){ 106 System.out.println("正在删除节点:" + this.head.next.getData()); 107 temp.next = temp.next.next; 108 System.out.println("删除成功"); 109 size --; //节点数减1 110 return; 111 } 112 temp = temp.next; //继续遍历 113 i ++; 114 } 115 116 } 117 118 //更新指定位置的节点 119 public void updateByIndex(int index, E e){ 120 if(index < 0 || index > this.size){ 121 System.err.println("索引小于0或者大于链表长度:" + index); 122 } 123 124 // if(index == 0){ 125 // this.updateByHead(e); //如果index==0,更新头节点 126 // } 127 128 //遍历链表 129 int i = 0; 130 Node<E> temp = this.head; 131 while(temp != null){ 132 if(index == i){ 133 temp.data = e; 134 break; 135 } 136 temp = temp.next; 137 i ++; 138 } 139 140 } 141 142 //更新头节点 143 public void updateByHead(E e){ 144 this.head.data = e; //为头节点重新赋值 145 } 146 147 //打印链表中的所有数据 从头节点一直到尾节点。 (1).head (2).head.next (3).head.next.next (n).head.next.n.n 148 public void display(){ 149 Node<E> temp = this.head; 150 //从头节点开始遍历到为尾节点 151 while(temp != null){ 152 System.out.println(temp.getData()); 153 temp = temp.next; //指向下一节点。 154 } 155 } 156 157 //返回链表list 158 public List<Node<E>> findAll(){ 159 List<Node<E>> list = new ArrayList<Node<E>>(); 160 Node<E> temp = this.head; 161 while(temp != null){ 162 list.add(temp); 163 temp = temp.next; 164 } 165 return list; 166 } 167 168 //查找指定位置结点 169 public Node<E> findByIndex(int index){ 170 Node<E> temp = this.head; 171 int i = 0; 172 173 //参数校验,返回null 174 if(index < i || index > this.size){ 175 System.err.println("参数大于链表长度或者小于0:" + index); 176 return null; 177 } 178 179 //如果index == 0,返回头节点 180 if(index == 0){ 181 return this.head; //如果下标为1,直接返回头节点 182 } 183 184 //遍历链表进行匹配 185 while(temp != null){ 186 if(i == index){ 187 return temp; //匹配节点 188 } 189 temp = temp.next; //继续遍历 190 i ++; 191 } 192 return null; 193 } 194 195 //获得链表节点数量 196 public int getSize(){ 197 return this.size; 198 } 199 200 //获取当前头节点 201 public Node<E> getHead(){ 202 return this.head; 203 } 204 205 //测试我的链表 206 public static void main(String[] args) { 207 LinkedList<Integer> linkedList = new LinkedList<Integer>(); 208 209 //添加节点 210 linkedList.addNode(1); 211 linkedList.addNode(2); 212 linkedList.addNode(3); 213 linkedList.addNode(4); 214 linkedList.addNode(5); 215 linkedList.addNode(6); 216 217 linkedList.insert(6, 9); 218 linkedList.updateByIndex(6, 9); 219 linkedList.display(); 220 221 } 222 223 }