数据结构(单向链表的增删改查)
单向链表 定义:单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始;链表是使用指针进行构造的列表;又称为结点列表,因为链表是由一个个结点组装起来的;其中每个结点都有引用指向列表中的下一个结点;
结构图:
文章图片
上图可以看出结构了,即每一个节点的Next变量,都指向了下一个节点,而最后一个节点指向了null
数据结构:
package LinkListTest;
public class LinkList {
private Integer date;
private LinkList next;
public Integer getDate() {
return date;
}
public void setDate(Integer date) {
this.date = date;
}
public LinkList getNext() {
return next;
}
public void setNext(LinkList next) {
this.next = next;
}
@Override
public String toString() {
return "LinkList [date=" + date + ", next=" + next + "]";
}}
其中第一个是链表存储的值(用Integer类型可以直接判断该该值是否为null,如果是int类型,由由于int类型是基本类型,不能这样判断),而第二个和链表类型一样的变量next是只想下一个节点的引用
单向链表的增删改查(包含有序、无序、重复和不重复)
package linklisttest;
public class NodeTest {
public static Node node = new Node();
//全局变量链表头节点
public static void main(String[] args) {
// TODO 自动生成的方法存根
int[] arr = {4,5,9,6,3,1,7};
for(int i = 0;
i < arr.length;
i++)
{
//add(arr[i]);
ADD(arr[i]);
}
System.out.println(node);
//del(4);
//Del(1);
//Del(7);
del(8);
search(8);
update(8,9);
System.out.println(node);
}
//有序链表的插入,按从小到大的顺序排列
public static void ADD(int date)
{
if(node.getDate() == null) //判断头节点有没有进行赋值
{
node.setDate(date);
return ;
}
else if(node.getDate() > date) //如果要插入的数据比头节点的小,则直接变成表头
{
Node newNode = new Node();
newNode.setDate(date);
newNode.setNext(node);
node = newNode;
return ;
}
Node temp = node.getNext();
Node newNode = new Node();
//要插入的节点
Node pre = node;
while(temp != null)
{
if(date < temp.getDate()) //若两数相等,则直接默认后来插入的date较大
{
newNode.setDate(date);
newNode.setNext(temp);
pre.setNext(newNode);
return ;
}
pre = temp;
temp = temp.getNext();
}
newNode.setDate(date);
pre.setNext(newNode);
}
//无序链表的插入(头插法)
public static void add(int date)
{
if(node.getDate() == null) //判断头节点有没有进行赋值
{
node.setDate(date);
return ;
}
Node temp = new Node();
temp.setDate(date);
//设置新节点的数
temp.setNext(node);
//设置新节点的下一个个点就是头节点,
node = temp;
//将新插入的节点作为新节点,实现头插法
}
//链表的插入(尾插法)
public static void Add(int date)
{
if(node.getDate() == null) //判断头节点有没有赋值
{
node.setDate(date);
return ;
}
Node pre = node;
for(Node temp = node.getNext();
temp != null;
temp = temp.getNext())
{
//局部变量temp是pre节点的下一个节点,当pre的下一个节点即temp为空时,
//循环结束,此时pre节点就是链表的最后一个节点
pre = temp;
}
Node temp = new Node();
pre.setNext(temp);
temp.setDate(date);
//将新节点插入到最后一个节点的后面,实现尾插法
}
//链表的删除 未声明前驱结点
public static void del(int date)
{
if(node.getDate() == null) //链表为空
System.out.println("链表中不存在数:" + date);
else
{
if(node.getDate() == date) //如果头节点就是要删除的数
{
node = node.getNext();
//直接将头节点等于头节点的下一个节点,实现删除
}
else
{
Node temp = node;
while(temp.getNext() != null)
{
if(temp.getNext().getDate() == date) //temp.getNext()就是要删除的节点
{
if(temp.getNext().getNext() == null) //判断删除的节点是不是最后一个节点
{
//要删除节点是最后一个节点,直接将被删除节点的前一个节点的Next设置为空,实现删除
temp.setNext(null);
return ;
}
else //如果不是
{
//将要删除节点的前一个节点指向被删除节点的后一个节点,实现删除
temp.setNext(temp.getNext().getNext());
//continue ;
//有重复节点时,用continue
return ;
//无重复节点时,用return
}
}
else if(temp.getNext().getNext() == null || temp.getNext().getNext().getDate() > date)//如果是无序链表,这里可以删除
{ //当前数小于date,下一个或者为空,或者下一个数比date大,因为时有序的,说明链表里面没有该数
System.out.println("链表中不存在数:" + date);
return;
}
temp = temp.getNext();
}
//表明已经便利完了链表也没有要删除的值,直接结束
System.out.println("链表中不存在数:" + date);
}
}
}
//链表的删除 声明前驱节点
public static void Del(int date)
{
if(node.getDate() == null) //链表为空
System.out.println("链表中不存在数:" + date);
else
{
if(node.getDate() == date) //如果头节点就是要删除的数
{
node = node.getNext();
//直接将头节点等于头节点的下一个节点,实现删除
}
else
{
/*以上代码和为声明前驱节点的方法代码一样*/
Node pre = node;
Node temp = node.getNext();
while(temp != null)
{
if(temp.getDate() == date) //已经找到节点
{
pre.setNext(temp.getNext());
//将节点的前驱节点的next设置为被删除节点的下一个节点
return ;
//已删除,直接结束方法,不用再执行,如果将return 则是有重复节点的算法
}
else if(temp.getNext() == null || temp.getNext().getDate() > date)//如果是无序链表,这里可以删除
{ //当前数小于date,下一个或者为空,或者下一个数比date大,因为时有序的,说明链表里面没有该数
System.out.println("链表中不存在数:" + date);
return;
}
pre = temp;
temp = temp.getNext();
}
//表明已经便利完了链表也没有要删除的值,直接结束
System.out.println("链表中不存在数:" + date);
}
}
}
//链表的查询
public static void search(int date)
{
Node temp = node;
if(temp.getNext() == null) //链表为空
{
System.out.println("链表为空");
return ;
}
while(temp != null)
{
if(temp.getDate() == date)
{
System.out.println("链表存在数:" + date);
return ;
}
else if(temp.getNext() == null || temp.getNext().getDate() > date)
{
System.out.println("链表不存在数:" + date);
return ;
}
temp = temp.getNext();
}
System.out.println("链表中不存在数:" + date);
}
//链表的修改
public static void update(int oldDate,int newDate)
{
Node temp = node;
if(temp.getNext() == null) //链表为空
{
System.out.println("链表为空");
return ;
}
while(temp != null)
{
if(temp.getDate() == oldDate)
{
temp.setDate(newDate);
return ;
//如果去掉return 则为有重复数据的算法
}
else if(temp.getNext() == null || temp.getNext().getDate() > oldDate)
{
System.out.println("****链表不存在数:" + oldDate);
return ;
}
temp = temp.getNext();
}
System.out.println("链表中不存在数:" + oldDate);
}
}
双向链表 【数据结构(单向链表的增删改查)】定义:双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个引用,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
推荐阅读
- leetcode|leetcode 92. 反转链表 II
- 《数据结构与算法之美》——队列
- 笔记|C语言数据结构——二叉树的顺序存储和二叉树的遍历
- Java深入了解数据结构之栈与队列的详解
- Java集合框架|Java集合框架 数据结构
- 数据结构与算法|【算法】力扣第 266场周赛
- 数据结构和算法|LeetCode 的正确使用方式
- LeetCode|LeetCode 876. 链表的中间结点
- 一个好的算法应该如何评测(数据结构学习1)
- XS-Java数据结构和算法目录总纲【2020-10-24~2021-2-12】