Java单向链表的实现

本篇博客将介绍以下内容:

-什么是java链表,它有什么特点?
-java链表基本功能的实现方法
-什么是泛型?泛型有什么用?

链表介绍

  • 链表是一种储存数据的结构。我们常用的数组的储存空间是连续的,而链表的储存空间是离散的、不连续的。链表的不连续的特点使得链表的使用比数组更加灵活,且不用在最开始定义其大小。

在这里插入图片描述

  • 从上图中我们可以看到,除头尾结点外,每一个节点都由数据域和指针域两部分组成。数据域用于存放需要的数据,指针域存放下一个节点的位置。当我们需要寻找链表上的某一个节点时,我们需要头节点位置以及目标节点的相对位置,然后从头节点开始逐个节点地向后寻找,直到找到目标节点。(因为单向链表中每个节点只知道下一个节点的位置,所以不能够跳过任何一个节点,只能逐个往后找)
  • 现在我们大致了解了链表的结构,如果要实现链表的功能,我们首先需要创建一个Node类,用于存放数据和存储下一个节点的位置。
	public class Node<E>{
    
    //这里的E是指泛型,后面有讲解
		//数据
		E data;
		//下一个节点
		Node<E>next;
		//要往节点中存入数据时调用此方法
		Node(E data){
    
    this.data=data;}
		//创建首个头节点时调用此方法
		Node(){
    
    }
	}

泛型
当我们想要往链表中存放数据,但 暂时还不知道需要放什么数据类型 时,可以用泛型来暂时代替我们将来可能要放置的类。所以说泛型可以指代任何类,具体指代什么类,在使用它的时候才需要去定义。比如说在上面的例子中,我们创建一个Node对象的时候就需要将泛型定义为我们需要用的类。Node<Integer> head()=new Node();就可以创建一个存放Integer的节点。泛型用大写字母表示,常用的字母有E(代表element)、K(代表key)和V(代表value)。

创建链表

  • 在链表创建之初,我们先要定义链表的头节点和尾节点,因为此时链表中还没有数据,头节点和尾节点均为空,且头节点和尾节点是同一个节点。然后我们还要定义链表的长度,初始值为0。
    链表创建之初头节点和尾节点是同一个节点
public class LinkList<E> {
    
    
	private Node<E> head,tail;//创建头尾节点
	private int size;
	
	public LinkList(){
    
    
		size=0;
		head=new Node<>();
		tail=head;
	}

链表提供的基本功能应该有:查询链表长度、获取链表某个位置的元素、往链表末尾添加元素、修改链表某个位置的元素、删除链表某个位置的元素、向指定位置插入一个元素。下面我们来逐一实现。

查询长度及元素

查询操作不需要对链表进行修改,相对来说比较简单。其中查询长度只需要返回我们链表的size值就可以了。

public int size(){
    
    
		return size;
	}

查询链表某个位置的元素,就像前面说到的我们只知道目前节点的下一个节点是什么,所以我们需要逐个逐个节点的往后寻找。

public E get(int index){
    
    
		if(index>=0&index<=size-1){
    
    //先判断链表是否为空或索引是否超出链表长度范围
			Node<E>temp=head.next;
			//因为头节点是不储存数据的,从头节点的后一个节点才开始储存数据
			//所以我们需要从头节点的后一个节点遍历链表
			for(int i=0;i<index;i++){
    
    
				temp=temp.next;
			}
			return temp.data;
		}else{
    
    
			System.out.println("索引超出表格范围!");
			return null;
		}
	}

添加元素

在这里插入图片描述

	public void add(E e){
    
    
		Node<E>node=new Node<>(e);//创建新节点存放元素
		tail.next=node;//把该节点放到原尾节点的最后
		tail=node;//把新节点定义为尾节点
		size++;//更新长度
	}

修改元素

修改元素和查询元素相似,只是修改元素多了一步修改指定位置的数据,且修改元素的方法不设返回值。

public void set(int index,E e){
    
    
		if(index>=0&index<=size-1){
    
    
			Node<E>temp=head.next;
			for(int i=0;i<index;i++){
    
    
				temp=temp.next;
			}
			temp.data=e;//将该节点的元素更新
		}else{
    
    
			System.out.println("索引超出表格范围!");
		}
	}

删除元素

删除元素是稍微复杂一些的操作,我们来看一下示意图
在这里插入图片描述

我们需要找到需要删除的节点的前一个节点和后一个节点,然后对这两个节点进行连结。

扫描二维码关注公众号,回复: 12614404 查看本文章
public void del(int index){
    
    
		if(index>0&index<=size-1){
    
    
			Node<E>temp1=head.next;//从头节点的后一个节点开始遍历
			Node<E>temp2,temp3;
			for(int i=0;i<index-1;i++){
    
    
				temp1=temp1.next;//找到需删除的节点的前一个节点
			}
			temp2=temp1.next;//temp2即为需要删除的节点
			temp3=temp2.next;//找到需要删除的节点的后一个节点
			temp1.next=temp3;//将节点1和节点3进行连结
			size--;//删除操作完成后记得更新链表长度
		}else{
    
    
			System.out.println("索引超出表格范围!");
		}
	}

插入元素

在这里插入图片描述

public void input(int index,E e){
    
    
		if(index>=0&index<=size-1){
    
    
			Node<E>temp=head.next;
			Node<E>temp2=new Node<>(e);//需要插入的新节点
			for(int i=0;i<index;i++){
    
    
				temp=temp.next;//找到需要插入的位置(新节点插入于该节点之后)
			}
			temp.next=temp2;
			temp2.next=temp.next;//此处的temp.next请看示意图
			size++;//插入操作完成后记得更新链表长度
		}else{
    
    
			System.out.println("索引超出表格范围!");
		}
	}

测试一下

	public static void main(String[]arguments){
    
    
		LinkList<Integer> linkList=new LinkList<>();//创建一个存放Integer的链表
		
		for(int i=0;i<10;i++){
    
    
			linkList.add(i);//往链表中加入10个元素
		}
		
		linkList.del(5);//删除链表中的第6个元素
		linkList.set(2,88);//将链表中第3个元素更改为88
		linkList.input(3,77);//在链表第4个元素的后面插入一个元素
		
		for(int i=0;i<linkList.size();i++){
    
    //将操作后的链表逐一输出
			System.out.println(linkList.get(i));
		}
	}

运行结果
在这里插入图片描述

完整代码

public class LinkList<E> {
    
    
	
	private Node<E> head,tail;
	private int size;
	
	public LinkList(){
    
    
		size=0;
		head=new Node<>();
		tail=head;
	}
	
	public int size(){
    
    
		return size;
	}
	
	public void add(E e){
    
    
		Node<E>node=new Node<>(e);
		tail.next=node;
		tail=node;
		size++;
	}
	
	public void del(int index){
    
    
		if(index>0&index<=size-1){
    
    
			Node<E>temp1=head.next;
			Node<E>temp2,temp3;
			for(int i=0;i<index-1;i++){
    
    
				temp1=temp1.next;
			}
			temp2=temp1.next;
			temp3=temp2.next;
			temp1.next=temp3;
			size--;
		}else{
    
    
			System.out.println("索引超出表格范围!");
		}
	}
	
	public E get(int index){
    
    
		if(index>=0&index<=size-1){
    
    
			Node<E>temp=head.next;
			for(int i=0;i<index;i++){
    
    
				temp=temp.next;
			}
			return temp.data;
		}else{
    
    
			System.out.println("索引超出表格范围!");
			return null;
		}
	}
	
	public void set(int index,E e){
    
    
		if(index>=0&index<=size-1){
    
    
			Node<E>temp=head.next;
			for(int i=0;i<index;i++){
    
    
				temp=temp.next;
			}
			temp.data=e;
		}else{
    
    
			System.out.println("索引超出表格范围!");
		}
	}
	
	public void input(int index,E e){
    
    
		if(index>=0&index<=size-1){
    
    
			Node<E>temp=head.next;
			Node<E>temp2=new Node<>(e);
			for(int i=0;i<index;i++){
    
    
				temp=temp.next;
			}
			temp2.next=temp.next;
			temp.next=temp2;
			size++;
		}else{
    
    
			System.out.println("索引超出表格范围!");
		}
	}
	
	class Node<E>{
    
    
		//数据
		E data;
		//下一个节点
		Node<E>next;
		
		Node(E data){
    
    
			this.data=data;
		}
		
		Node(){
    
    }
	}
	
	public static void main(String[]arguments){
    
    
		LinkList<Integer> linkList=new LinkList<>();
		
		for(int i=0;i<10;i++){
    
    
			linkList.add(i);
		}
		
		linkList.del(5);
		linkList.set(2,88);
		linkList.input(3,77);
		
		for(int i=0;i<linkList.size();i++){
    
    
			System.out.println(linkList.get(i));
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_44710412/article/details/113706528
今日推荐