线性表的链式存储

数据结构 —- 线性表


单链表

线性表的链式存储是用若干地址分散的存储单元存储数据元素,逻辑上相邻的数据元素在物理地址上不一定相邻,必须采用附加信息表示元素之间的顺序关系,因此存储一个数据元素的存储单元至少包含两部分–数据域和地址域

代码实现

package com.sshhsun.list;

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

    protected Node<T> head;

    public MSinglyLinkedList() {//默认构造方法,创建单节点,即data和next均为null
        this.head = new Node<T>();
    }

    //由指定的数组中的对象创建单链表,采用尾插入构造链表
    public MSinglyLinkedList(T[] element) {
        this();
        Node<T> rear = this.head;
        for (int i = 0; i < element.length; i++) {
            rear.next = new Node<T>(element[i], null); // 尾插入创建节点链入rear节点
            rear = rear.next; // rear指向新的莲尾节点
        }
    }

    @Override
    public boolean isEmpty() {

        return this.head.next == null;
    }

    @Override
    public int length() {
        int i = 0;
        Node<T> p = this.head.next;
        while (p != null) {
            p = p.next;
            i++;
        }
        return i;
    }

    @Override
    public String toString() {

        StringBuilder str = new StringBuilder("(");
        Node<T> p = this.head.next;
        while (p != null) {
            str.append(p.data.toString());
            if (p.next != null) {
                str.append(",");
            }
            p = p.next;
        }
        str.append(")");
        return str.toString();

    }

    @Override
    public T get(int i) { // 返回第i个元素,若i制定序号无效,则返回null
        if (i >= 0) {
            Node<T> p = this.head.next;
            for (int j = 0; p != null && j < i; j++) {
                p = p.next;
            }
            if (p != null) {
                return p.data;
            }
        }
        return null;
    }

    @Override
    public void set(int i, T x) {// 设置第i个元素为x,若i指定序号无效则抛出越界异常。
        if (x == null) {
            return;
        }
        if (i >= 0) {
            Node<T> p = this.head.next;
            for (int j = 0; p != null && j < i; j++) {
                p = p.next;
            }
            if (p != null) {
                p.data = x;
            }
        } else {
            throw new IndexOutOfBoundsException(i + "");
        }
    }

    @Override
    public void insert(int i, T x) {// 将x对象插在序号为i 节点前,O(n)
        if (x == null) {
            return;
        }
        Node<T> p = this.head;
        for (int j = 0; p.next != null && j < i; j++) {  // 循环停止时,p指向第i-1个节点或者最后一个节点。
            p = p.next;
        }

        //插入x作为p节点的后继节点,包括头插入,中间/尾插入
        p.next = new Node<T>(x, p.next); 
    }

    @Override//在单链表的组后添加对象
    public void append(T x) {
        insert(Integer.MAX_VALUE, x);
    }

    @Override
    public T remove(int i) { //删除序号为i的节点,若操作成功,则返回被删除对象,否则返回null 
        if (i>=0) {
            Node<T> p = this.head;
            for (int j = 0; p.next != null && j < i; j++) {  // 循环停止时,p指向第i-1个节点或者最后一个节点。
                p = p.next;
            }
            if (p.next!=null) {
                T old=p.next.data;
                p.next=p.next.next;
                return old;
            }
        }
        return null;
    }

    @Override
    public void removeAll() {
        this.head.next = null;
    }

    @Override
    public int search(T key) {

        return 0;
    }

}

单链表的应用 1

使用单链表进行求平均值

package com.sshhsun.list;

public class SinglyLinkedList_average {

    public static void main(String[] args) {
        MSinglyLinkedList<Integer> list = new MSinglyLinkedList<Integer>(
                random(10));
        System.out.println("list :" + list.toString() + "\n" + "i ="
                + list.length());
        System.out.println("average  is :" + average(list));
    }

    public static Integer[] random(int n) {
        Integer[] element = new Integer[n];
        for (int i = 0; i < n; i++) {
            element[i] = new Integer((int) (Math.random() * 100));
        }
        return element;
    }

    public static double average(MSinglyLinkedList<Integer> list) {
        if (list.isEmpty()) {
            throw new IllegalArgumentException("不能对空单链表计算平均值");
        }
        int sum = 0, i = 0, max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
        Node<Integer> p = list.head.next;
        while (p != null) {
            int value = p.data.intValue();
            sum += value;
            if (value > max) {
                max = value;
            }
            if (value < min) {
                min = value;
            }
            p = p.next;
            i++;
        }
        if (i == 1 || i == 2) {
            return (double) sum / i; //如果不超过两个数据,就不用去除最高分和最低分
        }
        return (double) (sum - min - max) / (i - 2);//超过两个数据,就去除最高分和最低分
    }

}

这里写图片描述


单链表的应用 2

用单链表求解约瑟夫环问题

package com.sshhsun.list;

//使用顺序表(或者单链表)解决约瑟夫问题
public class Josephus {

    public Josephus(int number, int start, int distance) {
        MSinglyLinkedList<String> list = new MSinglyLinkedList<String>(); // 使用单链表解决问题

        for (int i = 0; i < number; i++) {
            list.append((char) ('A' + i) + "");
        }
        System.out.println("约瑟夫环(" + number + "," + start + "," + distance
                + ")");
        System.out.println(list.toString());
        int i = start;
        while (list.length() > 1) {
            i = (i + distance - 1) % list.length(); // 计数按循环规律变化,顺序表可看作是环形结构
            System.out.print("删除" + list.remove(i).toString() + " ,");
            System.out.println(list.toString());
        }
        System.out.println("最后的人是" + list.get(0).toString());
    }

    public static void main(String[] args) {
        new Josephus(5, 0, 3);
    }

}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值