数据结构(一)单链表的实现-java
一、单链表的概念
![](https://img-blog.csdnimg.cn/20181220170406578.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2phdmFfeGlhb1doaXRl,size_16,color_FFFFFF,t_70)
上面展示的是一个单链表的存储原理图,简单易懂,head为头节点,他不存放任何的数据,只是充当一个指向链表中真正存放数据的第一个节点的作用,而每个节点中都有一个next引用,指向下一个节点,就这样一节一节往下面记录,直到最后一个节点,其中的next指向null。
链表有很多种,比如单链表,双链表等等。我们就对单链表进行学习,其他的懂了原理其实是一样的
二、用java实现单链表
2.1编写一个Node类里面包含两个属性1.data用于数据存放2.next存放下一节点的引用还有两个构造方法1.有参构造 2.无参构造
public static class Node {
public int data;
public Node next = null;
public Node(int data) {// 创建有数据的头节点使用
this.data = data;
}
public Node() {// 无参构造函数创建无数据的头节点使用
}
2.2简单编写一个菜单介绍相应的功能
public static void main(String[] args) {
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
System.out.println("链表的基本操作学习");
System.out.println("1.增加节点");
System.out.println("2.删除节点");
System.out.println("3.修改节点");
System.out.println("4.查找节点");
System.out.println("5.查看节点");
System.out.println("6.排序节点");
System.out.println("7.退出");
while (true) {
System.out.print("请输入你的选择:");
int sel = sc.nextInt();
switch (sel) {
case 1:
head1 = addLink(head);
break;
case 2:
head1 = delLink(head1);
break;
case 3:
head1 = modLink(head1);
break;
case 4:
finLink(head1);
break;
case 5:
seeLink(head1);
break;
case 6:
head1 = sorLink(head1);
break;
case 7:
exit();
}
}
}
2.3 增加节点操作
private static Node addLink(Node head) {
// TODO Auto-generated method stub
Node temp = head;// 创建一个临时节点
System.out.print("请输入你要增加节点的个数:");
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 0; i < n; i++) {
Node newnode = new Node();// 每次申请一个节点
if (newnode == null) {
System.out.println("申请存储空间失败");
} else {
System.out.print("请输入节点" + (i + 1) + ":");
newnode.data = sc.nextInt();
temp.next = newnode;
temp = newnode;
length++;// 成功创建一个节点给length++
}
}
System.out.println("节点输入完成");
return head;// 把头部返回
}
2.4删除节点操作
private static Node delLink(Node head) {
Node temp = head.next;
int count = 0;// 用来链表的遍历位置
Node p = null;// 临时节点
System.out.print("请输入你要删除节点的位置:");
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
int index = sc.nextInt();
if (index > length || index < 1) {
System.out.println("给定位置有问题,无法操作");
} else {
if (index == 1) {// 说明当前节点就是要删除的节点即第一个节点
head.next = temp.next;// 让head节点直接指向当前节点的下一个节点
length--;// 长度减一
} else if (index == length) {// 如果删除的是最后一个节点
while (temp.next != null) {
p = temp;
temp = temp.next;
}
p.next = null;// 循环正常结束让最后一个节点的前一个节点指向空
length--;
} else {
while (temp != null) {// 删除中间节点
count++;
if (count == index) {// 找到了
temp.next = temp.next.next;
length--;
break;
} else {
temp = temp.next;
}
}
}
}
return head;
}
删除节点可以根据节点的下标进行删除也可以根据节点值进行删除,这里我用的是节点下标进行删除,如果需要节点值进行删除的可以私聊我,提供代码!
2.5修改节点
private static Node modLink(Node head) {
// TODO Auto-generated method stub
System.out.println("请输入你要修改的节点的值");
Node temp = head.next;
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = 0;
Node p;// 定义一个临时节点p
// 开始去查找data值为这个数的节点
// if(temp.data==a) {//第一个节点的值和要修改节点的值相等直接修改
// System.out.print("请输入要修改的值:");
// b=sc.nextInt();
// temp.data=b;
// }
while (temp != null) {
p = temp; // 把当前节点保存下来
if (p.data == a) {
System.out.println("请输入你要修改的值");
b = sc.nextInt();
p.data = b;
return head;
} else {
temp = temp.next;
}
}
System.out.println("没有找到该值");
return head;
}
修改节点值也是两种方式一个是输入要修改的节点得到值找到这个节点对其值进行修改,还有一种方法也是根据下标值去找到该节点对其值修改,这里用的是根据节点值找到该节点进行修改的办法
2.6 查看节点
private static void seeLink(Node head) {
// TODO Auto-generated method stub
System.out.println("查看链表");
Node temp = head.next;
System.out.print("链表的数据是:");
while (temp != null) {
int a = temp.data;
System.out.print(a + " ");
temp = temp.next;
}
System.out.println();
System.out.println("数据查看完成");
}
就是对链表进行一个遍历
2.7查找结点
private static void finLink(Node head) {
// TODO Auto-generated method stub
System.out.print("请输入你要查找的值:");
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
Node temp = head.next;
int count = 0;// 用来记住目标节点的位置
while (temp != null) {
count++;
if (temp.data == a) {
System.out.println("节点位置在" + count);
return;
} else {
temp = temp.next;
}
}
System.out.println("该节点不存在");// 查完了没查到
}
查找节点也可以根据下标值进行查找和根据节点的值查找这里用的是节点的值查找的
2.8节点排序
private static Node sorLink(Node head) {
// TODO Auto-generated method stub
Node temp = head.next;
Node p = null;
int t = 0;// 创建一个临时变量
while (temp.next!= null) {
p = temp;//记录当前节点
if (p.data > temp.next.data) {
t=p.data;
p.data= temp.next.data;
temp.next.data= t;
temp = temp.next;
} else {
temp=temp.next;
}
}
System.out.println("排序完成");
return head;
}
排序分两种一种是是对内部的data排序,实际节点没变,变得是节点内的data这种排序简单,还有一种对节点交换进行排序,这里采用的是前一种。需要交流的欢迎留言
2.9退出程序
private static void exit() {
// TODO Auto-generated method stub
System.out.println("退出成功,欢迎下次使用");
System.exit(0);
}
这里就简单调用了系统函数System.exit(0)退出程序
三、运行结果展示
后面操作和这个演示操作过程一样就不一一展示了
三、总结
看到这里基本操作都实现了!这里提示几个易错点
1.创建节点因为函数都有static关键字修饰,所以类名一定要有static修饰,不然在创建节点的时候会报错
2.删除节点的时候因为头节点是head是没有任何数据的所以删除的第一个节点应该是head.next;在遍历的时候要先判断在进行节点的移动,不然最后一个节点判断不到,导致空指针
3.对节点进行排序时用到了排序算法不懂的要去看看相关算法