数据结构-线性表-链表的代码详解

继上篇文章对顺序表的介绍,这篇文章介绍链表,作为数据结构中最重要的一大模块,链表也是以后常用的

单链表是其中的核心,理解了单链表,其实链表的知识你也就掌握了。

代码附在最后!!!!    思路在程序注释。详解

一。

1.代码部分 一包    三类        节点类,链表类,测试类                  在学习过程中可以对着左侧行序号更改代码

2.节点类

3.链表类

4.测试类

5.运行结果:

二。代码附上

Node.java

package LinkList;
/*
 * 定义节点类,后续合成链表或者对链表进行操作
 * */
public class Node {
//节点储存的变量
    public int data;
    //指向下一个节点
    public Node next = null;
    public Node(int data) {
        this.data = data;
    }
}
 

LinkedList.java

package LinkList;

/*
 * 定义链表模板,将链表对象的增删改查等功能补充完整
 * 有时我们会在链表的头节点之前加一个固定的头节点表示开始,其可以用来存储附加信息等
 * 这次的demo我们没有使用这种头节点,所以实际实现链表以后,头节点就是真正的数据块节点
 * */
public class LinkedList {
//定义链表的头节点,因为链表刚建立是空,所以定义头节点为null
     Node head = null;
    
    
    //给链表添加节点,实质是寻找末尾节点,并将其指向新节点,使新节点的指向为null
    public void AddNode(int data) {
        Node newNode = new Node(data);
        //寻找并定义末尾节点
        //若head开始便是空的,则证明是空链表,直接让head指向新插入节点,程序结束
        if(head==null) {
            head = newNode;
            return;
        }
        //定义末尾节点temp
        Node temp = head;
        //循环使temp从头走到null,此时temp指向null的节点为末尾节点
        while(temp.next!=null) {
            temp = temp.next;
        }
        //将temp指向新插入的节点,如此便实现了链表节点的插入
        temp.next=newNode;
    }
    
    //删除链表节点,实质是将要删除节点的前节点的next指向删除节点的后节点,从而跳过该节点
    public void DeleteNode(int index) {
        //判断index是否合法,由此便需要求链表的长度length
        if(index<1||index>Length()) {
            try {
                throw new Exception("此位置不合法,无节点可删除");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //如果删除位置在头节点,故直接让head指向后节点便跳过,不需要执行太多逻辑
        if(index == 1) {
            head = head.next;
        }
        //如果删除位置不在头节点,则执行逻辑
        //定义两个节点,这两个节点遍历往后走,当后节点到达所要删除的节点的位置时
        //将前节点的next指向后节点的next,从而在链表结构中跳过index处的节点,实现删除
        Node preNode = head;
        Node bacNode = preNode.next;
        //定义i计数是否到达index-1处,因为当i到达index-1的前一处时
        //preNode到达了index-1,bacNode刚好到达index处,所以使preNode.next = bacNode.next刚好跳过index
        int i = 1;
        while(i<index-1) {
            preNode = preNode.next;
            bacNode = bacNode.next;
            i++;
        }
        //到达index处,进行跳过该节点
        preNode.next = bacNode.next;
    }
    
    //打印list值
    public void FindAll() {
        Node newNode = head;
        //此处是节点是否存在而不是节点指向是否为空
        while(newNode!=null) {
            System.out.println(newNode.data+"  ");
            newNode = newNode.next;
        }
    }
    
    //查询正数某处节点的值
    public void FindOne(int index) {
        //判断index是否合法
        if(index<1||index>Length()) {
            return;
        }
        
        Node newNode = head;
        for(int i=0;i<index-1;i++) {
            newNode = newNode.next;
        }
        System.out.println("正数所求的值为"+newNode.data);
        
    }
    
    //查询倒数某处节点的值
    public void FindBackOne(int index) {
        //判断index是否合法
        if(index<1||index>Length()) {
           return;
        }
        //定义前后两个节点,相距距离为index,当后节点指向为null的时候,前节点的data为所求的值
        Node preNode = head;
        Node backNode = preNode;
        for(int i=1;i<index;i++) {
            backNode = backNode.next;
        }
        
        while(backNode.next!=null) {
            preNode = preNode.next;
            backNode = backNode.next;
        }
        System.out.println("倒数所求值为"+preNode.data);
    }
    
    //求链表的长度
    public int Length() {
        int length = 0;
        //节点从头遍历,直到指向null
        //故定义一个节点使其为头节点
        Node newNode = head;
        //注意是节点不为空,而不是指向不为空
        while(newNode!=null) {
            length++;
            newNode = newNode.next;
        }
        return length;
    }
}
Test.java

package LinkList;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //创建链表
        LinkedList la = new LinkedList();
        //链表节点插入
        la.AddNode(11);
        la.AddNode(22);
        la.AddNode(33);
        la.AddNode(44);
        la.AddNode(55);
        //链表删除节点
        la.DeleteNode(2);
        
        //正向查找某一结点
        la.FindOne(4);
        //反向查找某一结点
        la.FindBackOne(4);
    
        
        //打印全部节点data
        la.FindAll();
    }

}