链表实例操作

利用链表可以生成空链表,插入数据元素,删除数据元素,获取数据元素,重置数据元素。

1.首先声明一个线性表接口

package ch03;

public interface LList<T> {
    boolean isEmpty();
    int length();
    T get(int i);
    void set(int i,T x);
    void insert(int i,T x);
    void append(T x);
    T remove(int i);
    void removeAll();

}

2.定义结点类Node<T>,包括数据域和地址域两个成员变量,构造方法实例化结点,重写toString()方法获取结点的字符串描述。

package ch03;

public class Node<T> {// 单链表结点类,T指定结点的元素类型
    // 成员变量
    public T data; // 数据域,保存数据元素
    public Node<T> next; // 地址域,引用后继结点
    //构造方法

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    // 无参数的构造方法
    public Node() {
        this(null,null);
    }
    // 重写toString()方法
    public String toString() {
        return this.data.toString();
    }
}

3.定义带头结点的单链表类SinglyList<T>类:

package ch03;

public class SinglyList <T> implements LList<T>{

    private Node<T> head;//头指针,指向单链表的头结点
    // 构造方法,创建空单链表

    public SinglyList() {
        this.head=new Node<T>();// 创建头结点,data和next均为null
    }

    // 构造方法,创建单链表,数据元素由values数组提供
    public SinglyList(T[] values) {
        this(); // 创建空单链表
        Node<T> rear = this.head; // rear指向单链表最后一个结点
        for (int i = 0; i < values.length; i++) { // 将values中的每个元素依次链接到单链表表尾
            Node<T> p = new Node<T>(values[i], null); // 生成一个新结点p
            rear.next = p; // 将新结点p链接到单链表表尾
            rear = p; // rear指向单链表表尾
        }
    }
    // 判断顺序表是否为空,若空返回true,否则返回false
    @Override
    public boolean isEmpty() {
        if (head.next==null){
            return true;
        }
        return false;
    }
    // 返回顺序表长度
    @Override
    public int length() {
        int len=0;//单链表节点个数,即长度
        Node<T> p = head.next; // p指向单链表第一个结点
        while (p!=null){// 从第一个结点开始,直到表尾为止,即遍历单链表
            len++;// 长度加1
            p=p.next;// p指向下一个结点
        }
        return len;
    }
    // 返回顺序表中第i个元素,若i指定序号无效则返回null
    @Override
    public T get(int i) {
        int j=0;//记录单链表结点个数
        Node<T> p=head.next;// p指向单链表第一个结点
        while (p!=null && j<i){// 遍历单链表,寻找第i个结点(p指向)
            j++;//计数变量j+1
            p=p.next;//p指向下一个节点

        }
        return (i>=0 && p!=null)? p.data:null;
    }

    // 设置顺序表中第i个元素为x(x为null除外),若i指定序号无效则抛出序号越界异常
    @Override
    public void set(int i, T x) {
        if (x == null) {
            throw new NullPointerException("插入的元素值不允许为空");
        }
        int j=0;//记录单链表结点个数
        Node<T> p = head.next; // p指向单链表第一个结点
        while (p != null && j < i) { // 遍历单链表,寻找第i个结点(p指向)
            j++; // 计数变量j加1
            p = p.next; // p指向下一个结点
        }
        if (i>=0 && p!=null){
            p.data=x; // 设置顺序表中第i个元素为x
        }else {
            throw new IndexOutOfBoundsException("无第" + i + "个元素");
        }
    }

    // 插入x作为第i元素,不能插入null
    @Override
    public void insert(int i, T x) {
        if (x==null){
            throw new NullPointerException("插入的元素不能为空");
        }
        // 下标容错
        if (i < 0) {
            i = 0;
        }
        if (i > length()) {
            i = length();
        }
        // 寻找第i-1个结点
        int j = 0; // 记录单链表结点个数
        Node<T> p = head; // p指向单链表的头结点
        while (p.next != null && j < i) { // 遍历单链表,寻找第i-1个结点(p指向)
            j++; // 计数变量j加1
            p = p.next; // p指向下一个结点
        }
        // 插入结点
        Node<T> q=new Node<>(x,p.next);// 生成新结点q,且新结点q的地址域指向第i个结点
        p.next=q;//p结点的地址域指向新结点q
    }

    @Override
    public void append(T x) {
        insert(Integer.MAX_VALUE, x); // 调用insert方法实现
    }
    // 删除第i个元素,若删除成功返回被删除数据元素,否则返回null
    @Override
    public T remove(int i) {
        // 寻找第i-1个结点
        int j = 0; // 记录单链表结点个数
        Node<T> p = head; // p指向单链表的头结点
        while (p.next != null && j < i) { // 遍历单链表,寻找第i-1个结点(p指向)
            j++; // 计数变量j加1
            p = p.next; // p指向下一个结点
        }
        if (i >= 0 && p.next != null) { // 找到了第i个结点,并使 p指向第i-1个结点
            T elem = p.next.data; // 获取第i个结点的数据元素
            p.next = p.next.next; // 删除第i个结点
            return elem; // 返回第i个结点的数据
        }
        return null; // 没找到第i个结点,不能删除
    }

    // 删除顺序表中所用元素
    @Override
    public void removeAll() {
        this.head.next=null;
    }

    // 返回顺序表中所有元素的描述字符串,形式为"(,)",覆盖Object类的toString()方法
    public String toString() {
        String str = "";
        Node<T> p = head.next; // p指向单链表第一个结点
        if (p!=null) {
            str = "(";
            while (p != null) { // 从第一个结点开始,直到表尾为止,即遍历单链表
                str += p.data.toString() + ",";
                p = p.next; // p指向下一个结点
            }
            str = str.substring(0, str.length() - 1);
            str += ")";
        } else {// 空表
            str = "( )";
        }
        return str;
    }
}

4.定义测试类,实现如下功能:通过输出的菜单项,进行功能选择并执行相应操作。

 

package ch03;

import java.util.Scanner;

public class ExSinglyList {
    static Scanner r = new Scanner(System.in);
    public static void main(String[] args) {
        SinglyList<Integer> list = null;
        int i;
        int elem;
        while (true) {
            int choice=menu();
            switch(choice){
                case 1:
                    list=new SinglyList<Integer>();
                    System.out.print("生成单链表:");
                    System.out.println(list.toString());
                    break;
                case 2:
                    System.out.print("插入的数据元素:");
                    elem=r.nextInt();
                    System.out.print("插入数据元素的位置(0-"+list.length()+"):");
                    i=r.nextInt();
                    list.insert(i, elem);
                    System.out.println("插入数据元素后单链表:"+list.toString());
                    break;
                case 3:
                    System.out.print("删除第几个数据元素?(0-"+(list.length()-1)+"):");
                    i=r.nextInt();
                    elem=list.remove(i);
                    System.out.println("被删除的数据元素:"+elem);
                    System.out.println("删除数据元素后单链表:"+list.toString());
                    break;
                case 4:
                    System.out.print("获取第几个数据元素?(0-"+(list.length()-1)+"):");
                    i=r.nextInt();
                    elem=list.get(i);
                    System.out.println("单链表的数据元素:"+list.toString());
                    System.out.println("第"+i+"个数据元素:"+elem);
                    break;
                case 5:
                    System.out.print("修改第几个数据元素?(0-"+(list.length()-1)+"):");
                    i=r.nextInt();
                    System.out.print("修改为的数据元素:");
                    elem=r.nextInt();
                    list.set(i, elem);
                    System.out.println("修改数据元素后单链表:"+list.toString());
                    break;
                case 6:
                    System.exit(0);
            }
        }
    }

    // 生成菜单并选择相应操作
    public static int menu() {
        int c = 0;
        do {
            System.out.println("\n*************************");
            System.out.println("       1.生成空单链表");
            System.out.println("       2.插入数据元素");
            System.out.println("       3.删除数据元素");
            System.out.println("       4.获取数据元素");
            System.out.println("       5.重置数据元素");
            System.out.println("       6.谢谢使用系统");
            System.out.println("*************************");
            System.out.print("请选择(输入数字1~6):");
            c = r.nextInt();
            r.nextLine();
        } while (c < 1 || c > 6);
        return c;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小石学编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值