zoukankan      html  css  js  c++  java
  • 数据结构Java实现01----线性表与顺序表

    一、线性结构

    如果一个数据元素序列满足:

    (1)除第一个和最后一个数据元素外,每个数据元素只有一个前驱数据元素和一个后继数据元素;

    (2)第一个数据元素没有前驱数据元素;

    (3)最后一个数据元素没有后继数据元素。

    则称这样的数据结构为线性结构。

    二、线性表抽象数据类型:

    1、线性表抽象数据类型的概念:

    线性表抽象数据类型主要包括两个方面:既数据集合和该数据集合上的操作集合。

    数据集合:

      可以表示为a0,a1,a2,...an-1,每个数据元素的数据类型可以是任意的类型。

    操作集合包括如下:

    1.插入
    2.查找
    3.删除 

    4.判断是否为空
    5.求元素个数

    2、设计线性表抽象数据类型的Java接口:

    代码如下:

     1 package com.myutil.list;
     2 
     3 public interface List {
     4     //插入元素
     5     public void insert(int index,Object obj) throws Exception;
     6     //重载插入方法
     7     public void insert(Object obj) throws Exception;
     8     //获取指定位置的元素
     9     public Object get(int index) throws Exception;
    10     //删除元素
    11     public void delete(int index) throws Exception;
    12     //获得线性表长度
    13     public int size();
    14     //判断线性表是否为空
    15     public boolean isEmpty();
    16 }

    然后我们让子类去实现这个接口就行了。

    三、顺序表:(在物理存储结构上连续,大小固定)

    1、顺序表的概念:

    计算机有两种基本的存储结构(物理存储结构):顺序结构、离散结构。使用顺序结构实现的线性表称为顺序表。如下图所示:

    d3384f05-39d1-46d9-a580-bf4b531d740c

    Java内存中,栈内存和堆内存占了很大一部分空间:栈内存的存储是顺序结构,堆内存的存储是离散结构。

    2、设计顺序表类:

    我们在上面第二段的List接口基础之上,设计一个顺序表:

    (1)List.java:(线性表,和上面的第二段中代码一样)

     1 package com.myutil.list;
     2 
     3 public interface List {
     4     //插入元素
     5     public void insert(int index,Object obj) throws Exception;
     6     //重载插入方法
     7     public void insert(Object obj) throws Exception;
     8     //获取指定位置的元素
     9     public Object get(int index) throws Exception;
    10     //删除元素
    11     public void delete(int index) throws Exception;
    12     //获得线性表长度
    13     public int size();
    14     //判断线性表是否为空
    15     public boolean isEmpty();
    16 }

    (2)SequentailList.java:(核心代码)

     1 package com.myutil.list;
     2 
     3 //SequentialList:顺序表
     4 
     5 public class SequentialList implements List {
     6 
     7     //默认的顺序表的最大长度
     8     private final int defaultSize = 10;
     9     //最大长度
    10     private int maxSize;
    11     //当前长度
    12     private int size;
    13     //对象数组
    14     Object[] listArray;
    15 
    16 
    17     public SequentialList() {
    18         init(defaultSize);
    19     }
    20 
    21     public SequentialList(int size) {
    22         init(size);
    23     }
    24 
    25     //顺序表的初始化方法(建立顺序表)
    26     private void init(int size) {
    27         maxSize = size;
    28         this.size = 0;
    29         listArray = new Object[size];
    30     }
    31     
    32     @Override
    33     public void insert(int index, Object obj) throws Exception {
    34         //如果当前线性表已满,那就不允许插入数据
    35         if (size == maxSize) {
    36             throw new Exception("顺序表已满,无法插入!");
    37         }
    38         //插入位置编号是否合法
    39         if (index < 0 || index > size) {
    40             throw new Exception("参数错误!");
    41         }
    42         //移动元素
    43         for (int j = size - 1; j >= index; j--) {
    44             listArray[j + 1] = listArray[j];
    45         }
    46 
    47         listArray[index] = obj;  //不管当前线性表的size是否为零,这句话都能正常执行,即都能正常插入
    48         size++;
    49     }
    50     
    51     @Override
    52     public void insert(Object obj) throws Exception {
    53         insert(size, obj);    
    54     }
    55     
    56     @Override
    57     public Object get(int index) throws Exception {
    58         if (index < 0 || index >= size) {
    59             throw new Exception("参数错误!");
    60         }
    61         return listArray[index];
    62     }
    63 
    64     @Override
    65     public void delete(int index) throws Exception {
    66         if (isEmpty()) {
    67             throw new Exception("顺序表为空,无法删除!");
    68         }
    69         if (index < 0 || index > size - 1) {
    70             throw new Exception("参数错误!");
    71         }
    72         //移动元素
    73         for (int j = index; j < size - 1; j++) {
    74             listArray[j] = listArray[j + 1];
    75         }
    76         size--;
    77     }
    78 
    79     @Override
    80     public int size() {
    81         return size;
    82     }
    83 
    84 
    85     @Override
    86     public boolean isEmpty() {
    87         return size == 0;
    88     }
    89 }

    我们来看一下第54行的插入操作insert()方法:如果需要在index位置插入一个数据,那么index后面的元素就要整体往后移动一位。这里面需要特别注意的是:

    插入操作:移动元素时,要从后往前操作,不能从前往后操作,不然元素会被覆盖的

    删除元素:移动元素时,要从前往后操作。

    (3)测试类:

     1 package com.myutil.list;
     2 
     3 public class Test {
     4 
     5     public static void main(String[] args) {
     6 
     7         SequentialList list = new SequentialList(20);
     8 
     9         try {
    10             list.insert(0, 100);
    11             list.insert(0, 50);
    12             list.insert(1, 20);
    13             list.insert(60);
    14 
    15             for (int i = 0; i < list.size(); i++) {
    16                 System.out.println("第" + i + "个数为" + list.get(i));
    17             }
    18 
    19         } catch (Exception e) {
    20             e.printStackTrace();
    21         }
    22     }
    23 }

    我们要注意插入的规则是什么,不然会觉得这个顺序表打印输出的顺序很奇怪。

    运行效果:

    第0个数为50
    第1个数为20
    第2个数为100
    第3个数为60

    3、顺序表效率分析:

    • 顺序表插入和删除一个元素的时间复杂度为O(n)。
    • 顺序表支持随机访问,顺序表读取一个元素的时间复杂度为O(1)。因为我们是可以通过下标直接访问的,所以时间复杂度是固定的,和问题规模无关。

    4、顺序表的优缺点:

    • 顺序表的优点是:支持随机访问;空间利用率高(连续分配,不存在空间浪费)。
    • 顺序表的缺点是:大小固定(一开始就要固定顺序表的最大长度)插入和删除元素需要移动大量的数据。

    5、顺序表的应用:

    设计一个顺序表,可以保存100个学生的资料,保存以下三个学生的资料,并打印输出。

    0393f396-1a75-4b69-927f-3e923f86d207

    代码实现:

    (1)List.java:

      和上面的代码保持不变

    (2)SequentailList.java:

      和上面的代码保持不变

    (3)Students.java:学生类

     1 package com.myutil.list.use;
     2 
     3 //学生类
     4 public class Students {
     5 
     6   private String id;// 学号
     7   private String name;// 姓名
     8   private String gender;// 性别
     9   private int age;// 年龄
    10 
    11   public Students() {
    12 
    13   }
    14 
    15   public Students(String sid, String name, String gender, int age) {
    16       this.id = sid;
    17       this.name = name;
    18       this.gender = gender;
    19       this.age = age;
    20   }
    21 
    22 
    23   public String getId() {
    24       return id;
    25   }
    26 
    27   public void setId(String id) {
    28       this.id = id;
    29   }
    30 
    31   public String getName() {
    32       return name;
    33   }
    34 
    35   public void setName(String name) {
    36       this.name = name;
    37   }
    38 
    39   public String getGender() {
    40       return gender;
    41   }
    42 
    43   public void setGender(String gender) {
    44       this.gender = gender;
    45   }
    46 
    47   public int getAge() {
    48       return age;
    49   }
    50 
    51   public void setAge(int age) {
    52       this.age = age;
    53   }
    54 
    55   public String toString() {
    56       return "学号:" + this.getId() + " 姓名:" + this.getName() + " 性别:" + this.getGender() + " 年龄:" + this.getAge();
    57   }
    58 
    59 }

    (4)Test.java:

     1 package com.myutil.list.use;
     2 
     3 import com.myutil.list.SequentialList;
     4 
     5 public class Test {
     6 
     7     /**
     8      * @param args
     9      */
    10     public static void main(String[] args) {
    11         SequentialList list = new SequentialList(100);
    12 
    13         try {
    14             list.insert(list.size(), new Students("S0001", "张三", "男", 18)); //第一个参数list.size代表的是:我每次都是在顺序表的最后一个位置(当前线性表的长度的位置)进行插入操作。这一行里,size是等于0
    15             list.insert(new Students("S0002", "李四", "男", 19));
    16             list.insert(list.size(), new Students("S0003", "王五", "女", 21));
    17             list.insert(new Students("S0004","赵六","女",20));
    18 
    19             for (int i = 0; i < list.size(); i++) {
    20                 System.out.println(list.get(i));
    21             }
    22 
    23         } catch (Exception ex) {
    24             ex.printStackTrace();
    25         }
    26     }
    27 
    28 }

    注意第11行的注释:第一个参数list.size代表的是:我每次都是在顺序表的最后一个位置(当前线性表的长度的位置)进行插入操作;这样的话,遍历时才是按照张三、李四、王五的顺序进行输出的。

    运行效果:

    学号:S0001 姓名:张三 性别:男 年龄:18
    学号:S0002 姓名:李四 性别:男 年龄:19
    学号:S0003 姓名:王五 性别:女 年龄:21
    学号:S0004 姓名:赵六 性别:女 年龄:20

    本文参考博客:http://www.cnblogs.com/smyhvae/p/4758808.html,并加入自己的一点改动,后续还会有优化改动,例如加入泛型等。。。。。。

  • 相关阅读:
    MySQL常用函数大全讲解
    mysql 获取最近一个月每一天
    Mysql查询某个月的每一天的数据
    Mysql 查询一天中,每个小时数据的数量
    oracle 和 mysql 遍历当前月份每一天
    sql查询总结
    Qt样式表——选择器详解(父子关系,插图详细解释)
    Qt样式表之盒子模型(以QSS来讲解,而不是CSS)
    程序员晋升必备技能——单元测试框架(小豆君的干货铺)
    为什么川普反对中国补贴农业(渐进式发展是非常正确的,如果贸然改动农村土地制度,在城市还不能提供足够的就业岗位下将大量的农民推向城市……请欣赏一下巴西、印度城市的贫民窟)
  • 原文地址:https://www.cnblogs.com/midiyu/p/8158395.html
Copyright © 2011-2022 走看看