美文网首页
Java实现线性表的顺序和链式存储

Java实现线性表的顺序和链式存储

作者: 一只变强的Hacker | 来源:发表于2019-07-22 23:20 被阅读0次

    什么是线性表?

    ​ 线性表(Linear List),是由同类型数据元素构成有序序列的线性结构,表中元素个数称为线性表的长度;线性表没有元素时,称为空表;表的起始位置称为表头,表的结束位置称为表尾

    抽象数据类型描述

    ​ 类型名称:线性表(List)

    ​ 数据对象集:线性表是n(n>=0)个元素构成的有序序列(a,a2,...,an)

    ​ 操作集:Item 表示元素类型,整数 i 表示位置

    • boolean isEmpty() 线性表是否为空
    • int size() 线性表中的元素个数
    • void insert(Item item, int i) 在 i 位置插入元素
    • void delete(int i) 在第i个位置删除数据(即删除数组下标为i-1这个位置)
    • int find(Item item) 查找某个元素,如果找到,返回下标;否则返回-1

    顺序存储实现(固定大小)

    ​ 创建一个泛型类List:

    public class List<Item>{
        private Item[] data; // 泛型数组存储数据
        private int last = -1; // last表示最后一个元素的下标
    }
    

    ​ 构造函数:

    public List(int size){
            data = (Item[]) new Object[size]; // java不允许创建泛型数组,所以需要用到类型转换
    }
    

    插入数据

    ​ 在这里,我们插入数据的位置范围是1n+1,即第一个位置到最后一个位置+1(这里的n就表示当前List中的元素个数)。所以我们就会发现我们在插入数据后,这些数据都是连续的。比如:在创建了List之后,数组中没有元素,元素个数为0,那么此时插入的范围就是10+1,只有1这个位置可以插入,之后再插入第二个元素,这时元素的个数已经变成了1,此时的范围是1~1+1,以此类推,存储在这个线性表中的数据总会是连续的。

    image

    ​ 当我们向线性表中插入数据时,首先要看看这个线性表满了没有,如果满了不能插入,判断满的条件就是:last==data.length-1如果最后一个元素的下标等于数组的最后一个下标,说明满了。

    ​ 然后,要判断插入的位置是否合法:i < 1 || i > last+2(n+1 >= i >= 1)。

    ​ 之前说过,List中存储的数据是连续的,所以我们插入时不能直接插入,需要将元素往后挪出一个空位才能够在特定的位置进行插入:

    // 挪动的顺序毫无疑问是从最后一个元素挪,否则你从第i个元素挪的话就会覆盖掉后面的元素
    for (int j=last; j>=i-1; j--){
        data[j+1] = data[j];
    }
    // 插入数据
    data[i-1] = item;
    // last加1
    last = last + 1;
    

    删除元素

    ​ 和插入元素类似,只是挪动元素是往前挪动元素,填补删除后留下的空位。直接上代码:

    // 如果List空,不能删除
    if (isEmpty()){
        System.out.println("List为空,不能删除");
    }
    // 规定的删除位置在1~n+1
    if (i < 1 || i > last+2){
        System.out.println("删除位置非法,无法插入!");
    }
    // 在删除之后需要先将数据往前挪
    for (int j=i-1; j<last; j++){
        data[j] = data[j+1];
    }
    last = last - 1;
    

    完整代码:

    public class List<Item> {
        // Java不允许创建泛型数组,所以做强制类型转换
        private Item[] data;
        private int last = -1; // 表示List中最后一个元素的下标
    
        // 构造函数-创建List时指定大小
        public List(int size){
            data = (Item[]) new Object[size];
        }
    
        // List是否为空
        public boolean isEmpty(){
            return last==-1;
        }
    
        // 返回List的大小
        public int size(){
            return last+1;
        }
    
        // 在第i个位置插入数据(即插入到数组下标为i-1这个位置)
        public void insert(Item item, int i){
            // 如果List满了,不能插入
            if (last==data.length-1){
                System.out.println("数组满,无法插入!");
            }
            // 规定的插入位置在1~n+1之间
            if (i < 1 || i > last+2){
                System.out.println("插入位置非法,无法插入!");
            }
            // 在插入之前需要先将数据往后挪
            for (int j=last; j>=i-1; j--){
                data[j+1] = data[j];
            }
            data[i-1] = item;
            last = last + 1;
        }
    
        // 在第i个位置删除数据(即删除数组下标为i-1这个位置)
        public void delete(int i){
            // 如果List空,不能删除
            if (isEmpty()){
                System.out.println("List为空,不能删除");
            }
            // 规定的删除位置在1~n+1
            if (i < 1 || i > last+2){
                System.out.println("删除位置非法,无法插入!");
            }
            // 在删除之后需要先将数据往前挪
            for (int j=i-1; j<last; j++){
                data[j] = data[j+1];
            }
            last = last - 1;
        }
    
        // 查找某个元素,如果查找到,返回下标,否则返回-1
        public int find(Item item){
            for (int i=0; i<last+1; i++){
                if (data[i]==item){
                    return i;
                }
            }
            return -1;
        }
    
        public void printData(){
            for (Item item:data){
                System.out.print(" " + item);
            }
            System.out.println("");
        }
    
        // 测试
        public static void main(String[] args) {
            List<Integer> testList = new List(5);
            testList.insert(1,1);
            testList.insert(2,2);
            testList.insert(3,3);
            testList.insert(4,4);
            testList.insert(5,5);
            testList.printData();
            testList.delete(1);
            testList.printData();
            System.out.println(testList.find(3));
        }
    }
    

    链式存储实现

    ​ 创建一个泛型类 LinkedList:

    public class LinkedList<Item> {
        private Node head; // 线性表的表头(链表的入口)
        private int N; // 结点的数量(线性表中的元素数量)
    
        // node结点类
        private class Node{
            Item item;
            Node next;
            // 构造器
            public Node(Item item, Node next) {
                this.item = item;
                this.next = next;
            }
        }
    }
    

    ​ 求线性表的长度和是否为空:

    public int length(){
        return N;
    }
    
    public boolean isEmpty(){
        return head==null; // 当head为null或N为0
    }
    

    ​ 查找相应的位置的结点:

    public Node findXth(int X){
        Node temp = head;
        int i = 1;
        // 当当前结点不为空且位置小于X时
        while (temp != null && i < X){
            temp = temp.next;
            i = i+1;
        }
        // 跳出循环有两种可能,当前结点为空或i==X
        if (i == X){
            return temp;
        } else{
            return null;
        }
    }
    

    插入数据

    ​ 因为是链式存储,所以不必关心空间的问题,只需care插入问题。

    ​ 要向链表中插入结点,首先要分插入的位置。如果是插到链表的头,需要做特殊处理:让插入结点的next的值变为head,head的值置为新插入的结点;如果插入到其他位置,只需要先找到插入位置的前一个结点p,然后是两步(顺序不能更改):1、设置插入的结点的next的值为p的next。2、改变p的next的值为插入的结点。

    public void insert(int i, Item item){
        Node temp, p;
        if (i == 1){
            temp = new Node(item, head);
            head = temp;
            N = N+1;
            return;
        }
        p = findXth(i-1);
        if (p == null){
            System.out.println("参数i错误!");
            return;
        } else{
            temp = new Node(item, p.next);
            p.next = temp;
            N = N+1;
            return;
        }
    }
    

    删除数据

    ​ 和插入类似,区分删除的是头结点还是其他位置,删除头结点:只需head置为head的next;删除其他结点:找到前一个结点p,使其next置为p.next.next即可,java会自动进行垃圾回收。

    public void delete(int i){
        Node p;
        if (i == 1){
            if (head == null){
                System.out.println("链表为空!");
                return;
            } else{
                head = head.next;
                N = N-1;
                return;
            }
        }
        p = findXth(i-1);
        if (p == null || p.next == null){
            System.out.println("第i个结点不存在!");
        } else {
            p.next = p.next.next;
            N = N-1;
        }
    }
    

    相关文章

      网友评论

          本文标题:Java实现线性表的顺序和链式存储

          本文链接:https://www.haomeiwen.com/subject/egtnlctx.html