链表
1.描述:链表是一种链式存储有序列表
2.存储方式:链式存储,以节点方式存储,每个节点包含数据域及指向下一个节点的引用
3.内存分布:存储的每个节点在内存中并不连续
4.种类:
1).单向链表:节点中仅包含指向下一个节点的引用
2).双向链表:节点中包含指向下一个节点的引用及指向上一个节点的引用
单向链表
单向链表DEMO
/**
* @Auther: LiXuHui
* @Date: 2019/7/17/017 13:50
* @Description:
*/
@Getter
@Setter
public class LinkList<T>
{
/**
* 头节点
*/
private Node<T> head;
/**
* 尾节点
*/
private Node<T> last;
/**
* @param value 被插入元素
* @return void
* @desc : 插入元素到头部
* 1.生成节点
* 2.如头节点不存在,则将头节点尾节点均指向当前生成节点,结束
* 3.生成节点的next引用指向当前头节点
* 4.头节点指向当前生成节点
* @author lxh
* @date 2021/5/22 0022 16:35
**/
public void insertHead(T value)
{
Node<T> node = new Node<T>(value);
if (head == null)
{
head = node;
last = node;
}
else
{
node.setNext(head);
}
head = node;
}
/**
* @param value 被插入元素
* @return void
* @desc : 插入元素到尾部
* 1.生成节点
* 2.如头节点不存在,则将头节点尾节点均指向当前生成节点
* 3.当前尾节点的next引用指向当前生成节点
* 4.尾节点指向当前生成节点
* @author lxh
* @date 2021/5/22 0022 16:35
**/
public void insertLast(T value)
{
Node<T> node = new Node<T>(value);
if (head == null)
{
head = node;
last = node;
}
else
{
last.setNext(node);
}
last = node;
}
/**
* @param value 被插入元素
* @return void
* @desc : 按照下标插入元素
* 1.生成节点
* 2.1.如预插入下标=0,则直接插入元素到头部即可,结束
* 2.2.如预插入下标!=0,则找到该下标的上一个位置,如未找到则找到最后一个节点,将其作为前置节点
* 3.将生成节点的next指向前置节点的next
* 4.将前置节点的next指向生成节点
* 5.判断生成节点的next是否未空,为空则将作为尾节点
* @author lxh
* @date 2021/5/22 0022 16:35
**/
public void insert(T value, int pos)
{
if (pos == 0)
{
insertHead(value);
}
else
{
Node node = new Node(value);
Node currentNode = head;
for (int i = 1; i < pos && currentNode.getNext() != null; i++)
{
currentNode = currentNode.getNext();
}
node.setNext(currentNode.getNext());
currentNode.setNext(node);
if (node.getNext() == null)
{
last = node;
}
}
}
/**
* @param value 被查找目标元素
* @return void
* @desc : 删查找指定元素
* 依次便利next判断其data进行查找
* @author lxh
* @date 2021/5/22 0022 16:38
**/
public Node find(T value)
{
Node<T> currentNode = head;
while (currentNode != null)
{
if (value == currentNode.getData())
{
return currentNode;
}
currentNode = currentNode.getNext();
}
return null;
}
/**
* @param value 被删除目标元素
* @return void
* @desc : 删除指定元素
* 1.判断如删除的元素为首节点,则将首节点指向当前首节点的next引用,结束
* 2.找到预删除节点及前一个节点未前置节点
* 3.将前置节点的next引用指向预删除节点的next
* 4.如此时前置节点next引用为null,即删除了尾节点,则将前置节点作为尾节点
* @author lxh
* @date 2021/5/22 0022 16:38
**/
public void delete(T value)
{
Node currentNode = head;
if (currentNode.data == value)
{
head = head.getNext();
return;
}
while (currentNode.getNext() != null)
{
if (currentNode.getNext().getData() == value)
{
Node delNode = currentNode.getNext();
currentNode.setNext(delNode.getNext());
if (null == currentNode.getNext())
{
last = currentNode;
}
return;
}
currentNode = currentNode.getNext();
}
}
/**
* @return void
* @desc : 便利展示链表元素
* @author lxh
* @date 2021/5/22 0022 16:37
**/
public void disploy()
{
Node currentNode = head;
while (currentNode != null)
{
System.out.print(currentNode.getData() + " ");
currentNode = currentNode.getNext();
}
System.out.println();
}
/**
* @Auther: LiXuHui
* @Date: 2019/7/17/017 13:49
* @Description:
*/
@Getter
@Setter
public static class Node<T>
{
/**
* 数据存储模型
*/
private T data;
/**
* 下一节点引用
*/
private Node<T> next;
public Node(T data)
{
this.data = data;
}
}
public static void main(String[] args)
{
System.out.println("---------------------");
Random random = new Random();
LinkList linkList = new LinkList<Integer>();
for (int i = 0; i < 5; i++)
{
Integer value = random.nextInt(50);
System.out.println("尾部加入元素: " + value);
linkList.insertLast(value);
}
System.out.println("---------------------");
for (int i = 0; i < 5; i++)
{
Integer value = random.nextInt(50);
System.out.println("头部加入元素: " + value);
linkList.insertHead(value);
}
System.out.println("---------------------");
System.out.println("链表元素为");
linkList.disploy();
System.out.println("---------------------");
linkList.insert(99, 13);
linkList.insert(100, 3);
System.out.println("依照下标[3]加入元素[99][100],链表元素为");
linkList.disploy();
System.out.println("---------------------");
System.out.println("删除指定元素[99],链表元素为");
linkList.delete(99);
linkList.disploy();
System.out.println("-----------------------");
System.out.println("查询指定元素100 :" + linkList.find(100).getData());
System.out.println("-----------------------");
}
}
结果
---------------------
尾部加入元素: 29
尾部加入元素: 12
尾部加入元素: 34
尾部加入元素: 17
尾部加入元素: 7
---------------------
头部加入元素: 49
头部加入元素: 42
头部加入元素: 18
头部加入元素: 46
头部加入元素: 18
---------------------
链表元素为
18 46 18 42 49 29 12 34 17 7
---------------------
依照下标[3]加入元素[99][100],链表元素为
18 46 18 100 42 49 29 12 34 17 7 99
---------------------
删除指定元素[99],链表元素为
18 46 18 100 42 49 29 12 34 17 7
-----------------------
查询指定元素100 :100
-----------------------
双向链表
双向链表DEMO
/**
* @Auther: LiXuHui
* @Date: 2019/7/17/017 13:50
* @Description:
*/
@Getter
@Setter
public class DoubleLinkList<T>
{
/**
* 头节点
*/
private Node<T> head;
/**
* 尾节点
*/
private Node<T> last;
/**
* @param value 被插入元素
* @return void
* @desc : 插入元素到头部
* 1.生成节点
* 2.如头节点不存在,则将头节点尾节点均指向当前生成节点,结束
* 3.生成节点的next引用指向当前头节点,当前头节点pre引用指向生成节点
* 4.头节点指向当前生成节点
* @author 李旭辉
* @date 2021/5/22 0022 16:35
**/
public void insertHead(T value)
{
Node<T> node = new Node<T>(value);
if (head == null)
{
head = node;
last = node;
}
else
{
node.setNext(head);
head.setPre(node);
}
head = node;
}
/**
* @param value 被插入元素
* @return void
* @desc : 插入元素到尾部
* 1.生成节点
* 2.如头节点不存在,则将头节点尾节点均指向当前生成节点
* 3.当前尾节点的next引用指向当前生成节点,生成节点pre指向当前尾节点
* 4.尾节点指向当前生成节点
* @author 李旭辉
* @date 2021/5/22 0022 16:35
**/
public void insertLast(T value)
{
Node<T> node = new Node<T>(value);
if (head == null)
{
head = node;
last = node;
}
else
{
last.setNext(node);
node.setPre(last);
}
last = node;
}
/**
* @param value 被插入元素
* @return void
* @desc : 按照下标插入元素
* 1.生成节点
* 2.1.如预插入下标=0,则直接插入元素到头部即可,结束
* 2.2.如预插入下标!=0,则找到该下标的上一个位置,如未找到则找到最后一个节点,将其作为前置节点
* 4.取前置节点的next作为后置节点
* 4.1若后置节点为空则说明前置节点是最后一个节点,将前置节点的next指向生成节点,并将生成节点作为尾节点
* 4.2若后置节点为空则说明前置节点非最后一个节点,将前置节点的next指向生成节点,后置节点的pre指向生成节点
* 5.将生成节点的next指向后置节点,生成节点的pre指向前置节点
* @author 李旭辉
* @date 2021/5/22 0022 16:35
**/
public void insert(T value, int pos)
{
if (pos == 0)
{
insertHead(value);
}
else
{
Node node = new Node(value);
Node currentNode = head;
for (int i = 1; i < pos && currentNode.getNext() != null; i++)
{
currentNode = currentNode.getNext();
}
Node nextNode = currentNode.getNext();
node.setPre(currentNode);
currentNode.setNext(node);
node.setNext(nextNode);
if (nextNode == null)
{
last = node;
}
else
{
nextNode.setPre(node);
}
}
}
/**
* @param value 被查找目标元素
* @return void
* @desc : 双向查找指定元素
* 依次便利next判断其data进行查找
* @author 李旭辉
* @date 2021/5/22 0022 16:38
**/
public Node find(T value)
{
Node<T> preNode = head;
Node<T> lastNode = last;
while (preNode != lastNode)
{
if (value == preNode.getData())
{
return preNode;
}
if (value == lastNode.getData())
{
return lastNode;
}
preNode = preNode.getNext();
lastNode = lastNode.getPre();
}
return null;
}
/**
* @param value 被删除目标元素
* @return void
* @desc : 删除指定元素
* 1.找到该节点
* 2.判断该节点pre前节点及next后节点
* 2.1若前置节点为空,说明该节点为首节点,删除该节点需将后置节点作为首节点,并将后置节点的pre置为空
* 2.1若后置节点为空,说明该节点为尾节点,删除该节点需将前置节点作为尾节点,并将前置节点的next置为空
* 2.3若均不为空,则将前节点的next指向后节点,后节点的pre指向前节点(越过待删除节点)
* @author 李旭辉
* @date 2021/5/22 0022 16:38
**/
public void delete(T value)
{
Node deleteNode = find(value);
if (deleteNode == null)
{
return;
}
Node pre = deleteNode.getPre();
Node next = deleteNode.getNext();
if (pre == null)
{
next.setPre(null);
head = next;
}
else if (next == null)
{
pre.setNext(null);
last = pre;
}
else
{
pre.setNext(next);
next.setPre(pre);
}
}
/**
* @return void
* @desc : 便利展示链表元素
* @author 李旭辉
* @date 2021/5/22 0022 16:37
**/
public void disploy()
{
Node currentNode = head;
while (currentNode != null)
{
System.out.print(currentNode.getData() + " ");
currentNode = currentNode.getNext();
}
System.out.println();
}
/**
* @Auther: LiXuHui
* @Date: 2019/7/17/017 13:49
* @Description:
*/
@Getter
@Setter
public static class Node<T>
{
/**
* 数据存储模型
*/
private T data;
/**
* 下一节点引用
*/
private Node<T> next;
/**
* 上一节点引用
*/
private Node<T> pre;
public Node(T data)
{
this.data = data;
}
}
public static void main(String[] args)
{
DoubleLinkList linkList = new DoubleLinkList<Integer>();
System.out.println("---------------------");
for (int i = 0; i < 5; i++)
{
int value = new Random().nextInt(50);
System.out.println("尾部加入元素: " + value);
linkList.insertLast(value);
}
System.out.println("---------------------");
for (int i = 0; i < 5; i++)
{
int value = new Random().nextInt(50);
System.out.println("头部加入元素: " + value);
linkList.insertHead(value);
}
System.out.println("---------------------");
System.out.println("链表元素为");
linkList.disploy();
System.out.println("---------------------");
linkList.insert(99, 3);
linkList.insert(100, 3);
System.out.println("依照下标[3]加入元素[99][100],链表元素为");
linkList.disploy();
System.out.println("---------------------");
System.out.println("删除指定元素[99],链表元素为");
linkList.delete(99);
linkList.disploy();
System.out.println("-----------------------");
System.out.println("查询指定元素100 :" + linkList.find(100).getData());
System.out.println("-----------------------");
}
}
结果
---------------------
尾部加入元素: 9
尾部加入元素: 44
尾部加入元素: 45
尾部加入元素: 11
尾部加入元素: 7
---------------------
头部加入元素: 41
头部加入元素: 21
头部加入元素: 36
头部加入元素: 6
头部加入元素: 5
---------------------
链表元素为
5 6 36 21 41 9 44 45 11 7
---------------------
依照下标[3]加入元素[99][100],链表元素为
5 6 36 100 99 21 41 9 44 45 11 7
---------------------
删除指定元素[99],链表元素为
5 6 36 100 21 41 9 44 45 11 7
-----------------------
查询指定元素100 :100
-----------------------