模拟顺序表

简介: 本篇博客在于深入理解顺序表的逻辑,因为这融合了很多基础知识,比如数组、类、对象等等…此外,本人这些天也顺利适应了 Java 风格。

一、深入理解顺序表



顺序表(Sequence List)


  1. 顺序表的定义:顺序表是在计算机内存中以数组的形式保存的线性表
  2. 顺序表的特点:表中元素的逻辑顺序与其物理顺序相同


  1. 顺序表的缺点:

(1) 顺序表中间/头部的插入删除,时间复杂度为O(N)

(2)增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗

(3)若增容按2倍增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间


二、创建框架



  1. 创建一个可以定义类型、可以实现功能的类,在这个类中,创建一个数组(表示顺序表中的元素),再创建变量 size( 表示数组中当前拥有的元素个数),接着创建四个函数来实现顺序表的增删查改功能


  1. 创建一个主函数用来测试


  1. 记住一个核心的要点:用数组实现顺序表,就要满足顺序表的规则,


① 数组下标要保持有序
② 数组中间元素不可断


  1. 此外,应该注意一些细小的点:


(1)每个函数接收的是什么,返回的是什么

(2)增加元素前,我们要初始化数组元素为0

(3)增加元素时,我们要考虑从哪个位置增加,要考虑是否有数组越界的情况,要考虑是否需要扩容数组的长度

(4)删除元素时,我们要考虑删除元素对应的数组下标
(5)每次实现函数的时候,考虑此时数组中剩余的元素个数 size


三、代码实现



1. 创建一个 SequenceList 类


import java.util.Arrays;
public class SequenceList {
    int[] element;       //创建一个数组(表示顺序表中的元素)
    int size;            //size表示数组中当前拥有的元素
    //初始化数组元素和对应的size
    public void initial(){
        this.element = new int[5];
        this.size = 0;
    }
    //向顺序表中添加元素--------增  ✓
    public void addNum(int pos, int data){
        expansion();      //判断是否要扩容的问题
        //pos为负数时,表示数组越界,不可逆
        //pos>size时,不满足顺序表对应的顺序规则
        if(pos < 0 ||  pos > this.size){
            System.out.println("无法扩容!");
            return;
        }
        //表示从数组中间插入元素
        if(pos >= 0 && pos <= this.size - 1){
            for (int i = this.size-1; i >= pos ; i--) {
                this.element[i+1] = this.element[i];
            }
        }
        //除了上述的两个if语句,其他的都正常添加
        this.element[pos] = data;
        this.size++;
    }
    //扩容函数  ✓
    public void expansion(){
        if(this.size == this.element.length){
            this.element = Arrays.copyOf(this.element, this.element.length * 2);
        }
    }
    //输出当前顺序表的所有元素  ✓
    public void print(){
        for (int i = 0; i < this.size; i++) {
            System.out.print(this.element[i] + " ");
        }
        System.out.println();
    }
    //从顺序表中删除元素--------删  ✓
    public void deleteNum(int data){
        int pos = 0;
        int flag = 0;
        //找到要删除的元素对应的数组下标
        //然后把下标赋值给pos,并用flag标记一下
        for (int i = 0; i < this.size; i++) {
            if(this.element[i] == data){
                pos = i;
                flag = 1;
                break;
            }
        }
        //如果没找到,有可能越界,有可能数组中就没有该元素
        //不论哪种原因,直接返回就行了
        if(flag == 0){
            System.out.println("你所要删除的元素不在该顺序表的范围内");
            return;
        }
        //如果pos位置处于顺序表的中间,那么就挪动元素进行覆盖
        //如果处于尾部的元素,将被0覆盖
        if(pos >= 0 && pos <= this.element.length - 1){
            for (int i = pos; i < this.size - 1; i++) {
                this.element[i] = this.element[i+1];
            }
        }
        this.size--;
    }
    //从顺序表中查找元素--------查  ✓
    public void findNum(int data){
        int flag = 0;
        //遍历数组,找到元素就把flag置成1,反之把flag置成0
        for (int i = 0; i < this.element.length; i++) {
            if(this.element[i] == data){
                flag = 1;
                System.out.print("你所要找的元素"+data+",它在顺序表中对应的下标是: ");
                System.out.println(i);
                break;
            }
        }
        if(flag == 0){
            System.out.println("找不到你所要找的元素!");
            return;
        }
    }
    //从顺序表中查找元素并修改--------改  ✓
    public void modifyNum(int data, int newNum){
        for (int i = 0; i < this.element.length; i++) {
            if(this.element[i] == data){
                this.element[i] = newNum;
            }
        }
    }
    //清空顺序表
    public void emptyList(){
        this.size = 0;
    }
}


2. 创建主函数用来测试


public class Test {
    public static void main(String[] args) {
        SequenceList test = new SequenceList();
        test.initial();
    }
}


四、分析增、删两个方法



我们主要来看一下增加元素和删除元素的这两个方法,其他的方法只需要遍历数组即可,较为简单,不再赘述。


1. addNum 方法


我们要理解如何操作,使得中间任一位置插入元素,画图实现!

例如,我们插入一个元素 data = 6,数组下标 pos = 2,那么数组下标为 2 之后的元素都要往后挪,挪动的时候不能覆盖,可以参考下图的挪动顺序自我理解。先挪 4,再挪 2, 9 ,7,5。此外我们更应该注意 for 循环的区间问题


5d5b9bde35024f6c82e944fccffc2cb7.jpg


2. deleteNum 方法


我们要理解如何操作,使得中间某一位置元素被删除,画图实现!


例如,我们删除一个元素 data = 5,数组下标 pos = 2,那么数组下标为 2 之后的元素都要往前挪,挪动的时候不能覆盖,可以参考下图的挪动顺序自我理解。先挪 7,再挪 9, 2 ,4。此外我们更应该注意 for 循环的区间问题


258350c8e60242759f913e72de33ff15.jpg


五、测试



(1)增加功能


public class Test {
    public static void main(String[] args) {
        SequenceList test = new SequenceList();
        test.initial();
        test.addNum(0,1);
        test.addNum(1,3);
        test.addNum(2,5);
        test.addNum(3,7);
        test.addNum(4,9);
        test.print();
        test.addNum(3,8);
        test.print();
        test.addNum(0,2);
        test.print();
        test.addNum(7,4);
        test.print();
    }
}


输出结果:


ec8496284b0b4f0b844d9d36f17fedd7.png


(2)删除功能


public class Test {
    public static void main(String[] args) {
        SequenceList test = new SequenceList();
        test.initial();
        test.addNum(0,1);
        test.addNum(1,3);
        test.addNum(2,5);
        test.addNum(3,7);
        test.addNum(4,9);
        test.print();
        test.deleteNum(9);
        test.print();
        test.deleteNum(1);
        test.print();
        test.deleteNum(5);
        test.print();
    }
}


输出结果:


7d5e4eea2413427aaa325990afe01ce9.png


(3)查找功能


public class Test {
    public static void main(String[] args) {
        SequenceList test = new SequenceList();
        test.initial();
        test.addNum(0,1);
        test.addNum(1,3);
        test.addNum(2,5);
        test.addNum(3,7);
        test.addNum(4,9);
        test.print();
        test.findNum(1);
        test.findNum(5);
        test.findNum(9);
        test.findNum(100);
    }
}


输出结果:


55c841997c234fbabe290b16a8bcdcfa.png


(4)修改功能


public class Test {
    public static void main(String[] args) {
        SequenceList test = new SequenceList();
        test.initial();
        test.addNum(0,1);
        test.addNum(1,3);
        test.addNum(2,5);
        test.addNum(3,7);
        test.addNum(4,9);
        test.print();
        test.modifyNum(1,2);
        test.modifyNum(5,8);
        test.modifyNum(9,10);
        test.print();
    }
}


输出结果:


2e0965f81f6c4e35ac92624617669138.png


总结



  1. 本人之前用 C 代码写了通讯录的一个小项目,里面创建了一个结构体,很多功能都是通过指针实现的。结构体与 Java 的类很相似,但是 Java 的类可强太多了!它可以创建成员函数对成员变量直接操作,之后通过实例化对象,这就使实现功能十分方便了!省略了很多繁杂过程。


  1. 本篇博客在于深入理解顺序表的逻辑,因为这融合了很多基础知识,比如数组、类、对象等等…此外,本人这些天也顺利适应了 Java 风格。


image.jpeg


Over. 谢谢观看哟~



目录
相关文章
|
存储 机器学习/深度学习 算法
模拟实现单链表、双链表、栈、队列——数组模拟
我们在数据结构中都学到过单链表、双链表、栈和队列,当我们实现的时候时使用结构体指针实现的。定义一个结构体,结构体中存储指针变量和存放数值的变量。当然,C++的STL库中已经有实现好的栈和队列,我们可以直接用。但是在做算法题时,有时候我们会发现超出时间限制。原因是我们用STL库中的栈和队列容器时,效率相对来说较慢。我们这时就引出用数组模拟实现栈和队列。用数组模拟实现的使用起来效率更高、更方便。当然,我们也会讲到用数组模拟实现单链表和双链表。
69 0
|
6月前
|
存储 算法
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
41 0
|
7月前
|
存储 算法 程序员
顺序表的模拟
顺序表的模拟
|
存储
模拟实现顺序表
模拟实现顺序表
43 0
|
7月前
|
存储 测试技术
单链表的模拟实现
单链表的模拟实现
52 0
|
存储 C语言 开发者
顺序表操作详解
顺序表操作详解
|
存储
【数据结构】模拟实现顺序表
【数据结构】模拟实现顺序表
06 顺序表操作
06 顺序表操作
26 0