数据结构 ---- 线性表

线性表的存储结构分为 顺序结构存储 和 链式结构存储

线性表是最常用,最简单的一种数据结构,简而言之,线性表是N个数据元素的有限序列。每个数据元素最多有一个前驱元素,每个元素最多只有一个直接后继元素;只有第一个数据元素没有直接前驱元素,而最后一个元素没有后继元素


在实现线性表的不同存储形式之前,先顶一个接口用于表述线性表的所有操作

package com.sshhsun.list;

public interface LList<T> {
    boolean isEmpty();//判断是否为空
    int length();      //得到长度
    T get(int i);          //返回第i个元素
    void set(int i,T x); //设置第i个元素值x
    void insert(int i,T x); //插入第i个元素值为x,如果超过数组长度则新建一个长度为原来2倍的集合并将原来的值付给新表
    void append(T x); //在线性表最后插入x元素
    T remove(int i);//删除并返回第i个元素
    void removeAll();//清空表
    int search(T key);//返回首次出现的关键字为key的元素位置
}

顺序表

线性表的实现结构MSeqList类实现LList接口的功能

package com.sshhsun.list;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MSeqList<T> implements LList<T> {
    private Object[] element;
    private int len;

    public MSeqList(int size) {
        this.element = new Object[size];
        this.len = 0;
    }

    public MSeqList() {// 默认一个长度
        this(64);
    }

    @Override //判断是否为空
    public boolean isEmpty() {

        return this.len == 0;
    }

    @Override//得到长度
    public int length() {

        return this.len;
    }

    @Override //返回第i个元素
    public T get(int i) {

        if (i >= 0 && i < this.len) {
            return (T) this.element[i];
        }
        return null;
    }

    @Override//设置第i个元素值x
    public void set(int i, T x) {
        if (x == null) {
            return;
        }
        if (i >= 0 && i < this.len) {
            this.element[i] = x;
        } else {
            throw new IndexOutOfBoundsException(i + "");
        }
    }

    @Override//插入第i个元素值为x
    public void insert(int i, T x) {
        if (x == null) {
            return;
        }
        if (this.len == this.element.length) {
            Object[] temp = this.element;
            this.element = new Object[temp.length * 2];

            for (int j = 0; j < temp.length; j++) {
                this.element[j] = temp[j];
            }
        }
        if (i < 0 || i > this.len) {
            throw new IndexOutOfBoundsException(i + "");
        }
        for (int j = this.len - 1; j >= i; j--) {
            this.element[j + 1] = this.element[j];
        }
        this.element[i] = x;
        this.len++;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder("(");
        if (this.len > 0) {
            str.append(this.element[0].toString());
        }
        for (int i = 1; i < this.len; i++) {
            str.append("," + this.element[i].toString());
        }
        str.append(")");
        return str.toString();
    }

    @Override//在线性表最后插入x元素
    public void append(T x) {
        insert(this.len, x);

    }

    @Override//删除并返回第i个元素
    public T remove(int i) {
        if (this.len == 0 || i < 0 || i > this.len) {
            return null;
        }
        T old = (T) this.element[i];
        for (int j = i; j < this.len - 1; j++) {
            this.element[j] = this.element[j + 1];
        }
        this.len--;
        return old;
    }

    @Override//清空表
    public void removeAll() {
        for (int i = 0; i < this.len; i++) {
            this.element[i] = null;
        }
        this.len = 0;
    }

    @Override//返回首次出现的关键字为key的元素位置
    public int search(T key) {
        if (key == null || this.len == 0) {
            return -1;
        }
        for (int i = 0; i < this.len; i++) {
            if (this.element[i] == key) {
                return i;
            }
        }
        return -1;
    }

}

顺序表的操作效率分析

1.顺序表存取任何一个元素的get(),set()方法时间复杂度是 O(1).;
2.对顺序表的插入和删除操作,算法所花费的时间主要用于移动元素。在等概率的情况下,插入一个元素平均需要移动一半的元素,时间复杂度为O(n),删除一个元素的时间复杂度也是O(n).


顺序表解决一个很经典的问题,约瑟夫环的问题
使用顺序表MSeqList解决约瑟夫环的问题:创建一个具有n个元素的顺序表对象List;从第s个元素开始,依次计数,每数到d,就删除对应元素,重复计数并删除元素,直到剩下一个元素。

上代码 !

package com.sshhsun.list;

public class Josephus {

    public Josephus(int number, int start, int distance) {
        MSeqList<String> list = new MSeqList<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、付费专栏及课程。

余额充值