数据结构线性表之链表(详解)

1、什么是线性表

首先,线性表是一种数据结构,是一种数据在逻辑上是连续的结构。
其次,线性表在计算机内部可以用顺序结构和链式结构存储数据。
顺序结构可以采用数组的方式完成,而本文主要描述的就是链式的线性表

2、什么是链表

链表是一个十分抽象的名词,但是开发者可以将其和火车结合进行理解,每一节车厢就是一个节点,而车厢与车厢之间的连接就是节点和节点之间的连接,但是在程序世界并不存在车厢与车厢那种的实际连接,因为程序世界的构成是内存,学过C/C++的开发者都知道,内存与内存的关系就是指针指向,那么就很好理解了。

接下来就一一展示一下

3、单链表

一、图解

在这里插入图片描述

单链表是一种最基础的链式线性结构,可以有头节点也可以没有头节点。
有头节点就是第一个节点中没有任何数据,但是指针指向下一个节点。
没有头节点就是第一个节点就直接存储数据

二、代码

1、链表类

package text;

public class Link {
    private Node head;
	//节点类使用内部类来声明实现
    private class Node{
        private int data;
        private Node next;

        public Node(int data,Node next){
            this.data = data;
            this.next = next;
        }
    }
    //省略了get/set方法
    }
}

2、单链表声明方法

一、添加节点
    public void addNode(int data){
        if(this.head == null){//如果头节点是null,则直接存入数据
            this.head = new Node(data,null);
            return;
        }
        Node current = this.head; //得到头节点,方便遍历链表
        while(current.next != null){
            current = current.next;
        }
        //遍历到最后一个节点之后就将新添加的数据加入到链表中
        current.next = new Node(data,null);
    }
二、删除节点
 public void deleteNode(int index){
        int nodeIndex = 1;
        //两个指针一前一后进行遍历数组,方便删除元素
        Node before = this.head.next, after = this.head;
        while(before.next != null && nodeIndex != index){
            nodeIndex++;//每遍历当到一个节点就使计数器加一,直到自增到符合条件就停止
            after = before;
            before = before.next;
        }
        //找到符合条件的下标后就删除
        if(nodeIndex == index){
        //当前节点的next就指向下一个节点的next,就能断开before的链接
            after.next = before.next;
        }
  }
三、修改节点数据
public int repairElement(int index,int data){
       int nodeIndex = 0;
        Node temp = this.head;
        while(temp != null){
        //遍历节点找到合适的节点进行修改
            if(nodeIndex == index){
                temp.data = data;
                return 1;
            }
            nodeIndex++;
            temp = temp.next;
        }
    return -1;
}
4、查找指定的节点
 public int searchElement(int index){
        int nodeIndex = 0;
        Node temp = this.head;
        while(temp != null){
            nodeIndex++;
            if(nodeIndex == index){
                return temp.data;
            }
            temp = temp.next;
        }
        return -1;
    }

4、环形链表

一、图解

在这里插入图片描述

环形链表就是单链表的一种变化。
单链表的尾节点的next是指向null的。
环形链表的尾节点是指向头节点的。

二、代码

因为我写的环形链表类和单链表类大致相同,所以环形链表的代码就只展示与单链表代码的不同之处

1、添加节点

public void addNode(int data){
      if(this.head == null){ //判断头节点是否为空,为空则直接在头节点存入数据
          this.head = new Node(data, null);
          return;
      }
      Node current = this.head;
      while(current.next != null && !current.next.equals(head)){
          current = current.next;
      }
      //初始化要新添加的节点,data为要存入的数据,this.head表示该节点指向头节点
      Node temp  = new Node(data,this.head);
      current.next = temp;//尾节点的next指向新的节点
}

5、双向节点

一、图解

在这里插入图片描述

二、代码

1、链表代码


public class Link {
    private Node head; //代表头节点
    private Node foot;//代表尾节点

    private class Node{
        private int data;
        private Node before; //指向前一个节点的指针
        private Node next; //指向后一个的指针

        public Node(int data,Node before,Node next){
            this.data = data;
            this.before = before;
            this.next = next;
        }
    }
}

2、方法代码

一、添加节点
public void addNode(int data){
        if(this.head == null){
        //如果头节点为空,则将数据存入第一个节点,并且上一个节点和下一个节点都为null
            this.head = new Node(data,null,null);
            return;
        }
        Node temp = this.head;
        while(temp.next!= null){
            temp = temp.next;
        }
        //遍历到最后一个节点后就将新的数据添加到新的节点中,
        temp.next = new Node(data,temp,null);//before指针指向前一个节点,next指向Null
        foot = temp.next;
 }
2、删除节点

在这里插入图片描述

public void deleteNode(int index){
        int nodeIndex = 1;
        Node before = this.head.next, after = this.head;
        //两个指针一前一后遍历数组,便于删除
        while(before != null && nodeIndex != index){
            after = before;
            before =  before.next;
            nodeIndex++;
        }
        if(nodeIndex == index){
        //将后一个节点的next指向前一个节点的next就完成了before节点的断链,就删除了
            after.next = before.next;
        //将前一个节点的前一个节点的before指向after;
            before.next.before = after;
        }
    }
3、遍历链表
一、从头部开始遍历
public void showElementByHead(){
        Node temp = this.head;
        while(temp != null){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(temp.data);
            temp = temp.next;
        }
    }
二、从尾节点开始遍历
public void showElementByFoot(){
        Node temp = this.foot;
        while(temp != null){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(temp.data);
            temp = temp.before;
        }
 }

总结

线性表是最基本的数据结构, 而链表是线性表中最重要的结构,也是日常中用的最多的线性结构,其实,线性表就是一开始理解的时候有点难度,理解好了之后就可以千变万化的写代码,
这还是扯一下数据结构和算法的核心——理解,很多同学都问过我“代码要背吗?”,要吗??是不要的,
只有真正理解,才能将一个代码写得出神入化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值