Java---单链表的实现

为什么需要使用链表 ?
数组是我们常用的一种数据结构,它的使用是非常方便的,但是一旦数组的大小确定下来,就不能再次改变。所以数组队列就应运而生了 ,它可以不断的改变大小,但是它的使用需要一段连续的内存,如果我们的内存中没有一段连续的内存的话,就无法使用这种数据结构了。因此,链表就产生了,那么,链表有哪些特异功能呢?

链表的优点:

  • 链表的长度可以改变
  • 无需使用连续的内存来存放数据

什么是链表 ?
链表的存储原理如下图所示:
这里写图片描述
上面展示的是一个单链表的存储原理图,简单易懂,head为头节点,他不存放任何的数据,只是充当一个指向链表中真正存放数据的第一个节点的作用,而每个节点中都有一个next引用,指向下一个节点,就这样一节一节往下面记录,直到最后一个节点,其中的next指向null。

链表有很多种,比如单链表,双链表等等。我们就对单链表进行学习,其他的懂了原理其实是一样的。


在实现单链表之前,先简单的介绍一下什么是泛型。

泛型
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

由于我们不确定我们写的链表会被用来接收什么类型的数据,所以引入泛型,它可以接收一切的引用数据类型。常用的泛型有 E、K、V。


链表的实现

  • 定义一个接口,用来定义我们链表所需要实现的功能。链表包括基础的增、删、改、查的功能
public interface MyList<E> {
	
	//增加元素
	public void add(E e);
	//删除元素
	public void delete(int index);
	//修改元素
	public void change(int index,E e);
	//查找元素
	public E getdata(int index);
	//插入元素
	public void insert(int index,E e);
	//获取元素个数
	public int getSize();

}
  • 定义一个类实现接口,并重写其中的方法。
public class Link<E> implements MyList<E>{
	
	Node<E> head,tail;
	int size;
	
	public Link(){
		head = new Node<>();
		tail = head;
	}

	//添加数据
	@Override
	public void add(E e) {
		// TODO Auto-generated method stub
		//创建新节点
		Node<E> node = new Node<>(e);
		//尾节点指向新节点
		tail.next = node;
		//新节点成为尾节点
		tail = node;
		size++;
	}

	//删除节点的元素
	@Override
	public void delete(int index) {
		// TODO Auto-generated method stub
		if(index>0 && index<=size){
			Node<E> node = head;
			//推进到删除 的位置
			for(int i=0;i<index-1;i++){
				node = node.next;
			}
			Node<E> temp = node.next;
			node.next = temp.next;
			size--;
		}else {
			System.out.println("索引值有误,请重新输入!");
		}
	}

	//改变节点的数据
	@Override
	public void change(int index, E e) {
		// TODO Auto-generated method stub
		if(index>0 && index<=size){
			Node<E> node = head;
			//推进到修改的位置
			for(int i=0;i<index;i++){
				node = node.next;
			}
			node.data = e;
		}else {
			System.out.println("索引值有误,请重新输入!");
		}
		
	}
	
	//在指定位置插入数据
	@Override
	public void insert(int index, E e) {
		// TODO Auto-generated method stub
		if(index>0 && index<=size+1){
			Node<E> node = head;
			//推进到插入的位置
			for(int i=0;i<index-1;i++){
				node = node.next;
			}
			Node<E> temp = new Node<>(e);
			temp.next = node.next;
			node.next = temp;
			size++;
		}else {
			System.out.println("索引值有误,请重新输入!");
		}
		
	}

	//获取节点的 数据
	@Override
	public E getdata(int index) {
		// TODO Auto-generated method stub
		Node<E> node = head.next;
		for(int i=0;i<index;i++){
			node = node.next;
		}
		return node.data;
	}

	//得到元素的个数
	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return size;
	}

}

  • 节点类

节点类中需要定义2个属性:要存储的数据 data 和下一个节点 next

public class Node<E> {
	
	E data;
	
	Node<E> next;
	
	public Node(){}
	
	public Node(E data){
		this.data = data;
	}

}
  • 主类(main方法所在的类)
public class Main<E> {
	
	public static void main(String[] args){
		Link<String> link = new Link<>();
		link.add("a");
		link.add("b");
		link.add("c");
		link.add("d");
		link.add("e");
		link.add("f");
		System.out.println("原始数据:");
		for(int i=0;i<link.getSize();i++){
			System.out.println(link.getdata(i));
		}
		link.delete(3);
		System.out.println("删除3后:");
		for(int i=0;i<link.getSize();i++){
			System.out.println(link.getdata(i));
		}
		link.change(3, "change!");
		System.out.println("改变后:");
		for(int i=0;i<link.getSize();i++){
			System.out.println(link.getdata(i));
		}
		link.insert(8, "insert!");
		System.out.println("插入后:");
		for(int i=0;i<link.getSize();i++){
			System.out.println(link.getdata(i));
		}
		
	}

}

这就是一个简单的链表了,小伙伴赶快实现起来吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

steven_moyu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值