Java中链表_②实现单链表的增、删、改、查
在上一篇博客中介绍了单链表的基础思想
接下来将要实现的是更详细的链表的增、删、改、查
1、增加数据
在上一篇博客主要用到的就是增添数据所以这里不再作过多的解释
public void add(Object date){
Node node = new Node(date);
if(root == null){//判断是否第一个节点
root = node;
}else{
Node temp = root;
while(temp.next != null){//寻找链表最后一个节点
temp = temp.next;
}
temp.next = node;//将地址值传个链表最后一个节点
}
size++;//计数存储元素个数的变量
}
2、删除数据
在单链表中,数据的删除并不是直接将该数据从JVM中删除,而是使其失去引用,而后被垃圾回收机制清理
具体的操作方式为:
根据提供的索引找到要删除的数据所在的节点;
将该节点下一个节点的地址覆盖在之前存储该节点的上一个节点的变量出
public void removeByIndex(int index){
if(index == 0){//判断是否索引的第一个节点
root = root.next;
}else{
Node temp = root;
//根据提供的索引找到要删除的数据所在的节点
for (int i = 1; i < index; i++) {
temp = temp.next;
}
//将该节点下一个节点的地址覆盖在之前存储该节点的上一个节点的变量处
temp.next = temp.next.next;
}
size--;//记录元素的变量自减1
}
3、修改数据
修改数据比较方便,只要找到索引对应的节点,然后根据提供的数据覆盖原有的数据即可
public void revisionByIndex(int index, Object date){
Node temp = root;
//根据索引查找节点
for(int i = 0; i < index; i++){
temp = temp.next;//向下寻找,直达找到索引处的节点
}
temp.date = date;
}
4、查找数据
链表中的索引并不严格,可以按照自的需要决定0、1或其它数据开始
要查找链表中的数据需要先找到对应的节点,然后获取节点中的数据(查找的操作和修改有类似之处)
public Object find(int index){
Node temp = root;
for(int i = 0; i < index; i++){
temp = temp.next;//向下寻找,直达找到索引处的节点
}
return temp.date;
}
5、测试代码
首先是节点类的代码
public class Node {
Object date;
Node next;
public Node(Object date){
this.date = date;
}
@Override
public String toString() {
return "Node [date=" + date + ", next=" + next + "]";
}
}
然后是链表主体类的代码
public class LinkList {//链表
private int size;//用于计数容器中元素的个数
public int getSize() {//提供get方法获取容器中元素个数
return size;
}
private Node root;
//增加元素
public void add(Object date){
Node node = new Node(date);//实例化一个节点对象并传入数据
if(root == null){//当没有第一个节点时
root = node;//当前节点成为第一个节点
}else{
Node temp = root;
while(temp.next != null){//寻找链表最后一个节点
temp = temp.next;
}
temp.next = node;//将地址值传个链表最后一个节点
}
size++;
}
//按照索引删除元素
public void removeByIndex(int index){
if(index > size-1 || index < 0){
throw new ArrayIndexOutOfBoundsException("删除了不存在的索引位置");
}//如果输入的索引不在范围内,手动抛出异常
if(index == 0){//如果要删除的是第一个元素
root = root.next;
}else{
Node temp = root;
for (int i = 1; i < index; i++) {//遍历容器中的元素,直到索引值为(传入索引值-1)时停止遍历
temp = temp.next;
}
temp.next = temp.next.next;//将索引对应节点的下一个节点的地址赋值给索引对应节点的上一个节点的next变量
}
size--;//删除完毕元素减1
}
//按照元素删除元素
public boolean removeByValue(Object date){
Node temp = root;
for (int i = 0; i < size; i++) {//遍历容器中的元素
if( date.equals(temp.date) ){//如果找到与传入元素相同的元素时
removeByIndex(i);//将当前i值当做索引传入removeByIndex(Object date)方法中删除元素
return true;//删除成功返回ture
}else{
temp = temp.next;//如果没有找到则继续遍历容器元素
}
}
return false;//直到变量完所有元素都没有找到与传入元素相同的元素则返回false
}
//修改元素
public void revisionByIndex(int index, Object date){
if(index > size-1 || index < 0){
throw new ArrayIndexOutOfBoundsException("修改了不存在的索引位置");
}//如果要修改元素的索引值不在范围内,手动抛出异常
Node temp = root;
for(int i = 0; i < index; i++){//遍历容器元素直到传入的索引位置跳出循环
temp = temp.next;
}
temp.date = date;//将传入的数据替换掉当前的数据
}
//查找元素
public Object find(int index){
if(index > size-1 || index < 0){
throw new ArrayIndexOutOfBoundsException("查找了不存在的索引位置");
}//如果要修改元素的索引值不在范围内,手动抛出异常
Node temp = root;
for(int i = 0; i < index; i++){//遍历容器元素直到传入的索引位置处跳出循环
temp = temp.next;
}
return temp.date;//将当前节点中的数据当做返回值返回
}
//覆写toString方法
@Override
public String toString() {
return "LinkList [root=" + root + "]";
}
}
定义一个含有主方法的测试类Test类测试上面的单链表代码
public class Test {
public static void main(String[] args) {
LinkList l1 = new LinkList();
//增加数据
l1.add(1);
l1.add(2);
l1.add(3);
System.out.println(l1);
//删除数据
l1.removeByIndex(0);//更加索引删除数据
//l1.removeByValue(3);//根据元素删除数据
System.out.println(l1);
//修改数据
l1.revisionByIndex(0, 123456);
System.out.println(l1);
//查找数据
System.out.println(l1.find(0));
}
}
运行的结果为
LinkList [root=Node [date=1, next=Node [date=2, next=Node [date=3, next=null]]]]
LinkList [root=Node [date=2, next=Node [date=3, next=null]]]
LinkList [root=Node [date=123456, next=Node [date=3, next=null]]]
123456