数据结构——顺序表

简介: 数据结构——顺序表

一、什么是顺序表

顺序表是数据结构的一种,是List的子类,以数组的形式进行存储。

顺序表的特点:

  • 顺序表都是连续的。
  • 存取速度快,依靠下标直接进行存取。
  • 不适合频繁插入和删除,需移动大量元素,时间复杂度高。

二、模拟实现顺序表

顺序表首先需要设置默认大小,以及所使用的容量,还需定义一个数组。

 public int[] elem;
    public int usedSize;//0
    //默认容量
    private static final int DEFAULT_SIZE = 10;
 
    public MyArrayList() {
        this.elem = new int[DEFAULT_SIZE];
    }

1、添加元素

直接添加:需要判断是否容量已满需要扩容,再向数组已利用空间之后插入元素。

   /**
     * 判断当前的顺序表是不是满的!
     * @return true:满   false代表空
     */
    public boolean isFull() {
        if(usedSize==elem.length){
            return true;
        }
        return false;
    }
   /**
     * 扩容(实际上顺序表底层扩容为1.5倍)
     */
    public void reSize(){
        this.elem= Arrays.copyOf(elem,2*elem.length);
    }
// 新增元素,默认在数组最后新增
    public void add(int data) {
        if(isFull()){
            reSize();
        }
        elem[usedSize]=data;
        usedSize++;
    }

指定位置添加:首先需要判断位置的合法性,然后再判断是否需要扩容,最后再逐步右移,在指定位置添加元素。

// 在 pos 位置新增元素
    public void add(int pos, int data) {
        if(checkPosInAdd(pos)&&!isFull()){
            for(int j=usedSize-1;j>=pos;j--){
                elem[j+1]=elem[j];
            }
            elem[pos]=data;
            usedSize++;
        }
    }

2、删除元素

删除第一次出现的关键字:先对数组中的元素进行遍历,找到待查找元素的下标,然后左移进行覆盖删除。

 /**
     * 删除第一次出现的关键字key
     * @param key
     */
    public void remove(int key) {
        boolean flag=false;
        for(int i=0;i<usedSize;i++){
            if(elem[i]==key){
                flag=true;
                for(int j=i;j<usedSize-1;j++){
                    elem[j]=elem[j+1];
                }
                elem[usedSize-1]=0;
                usedSize--;
                break;
            }
        }
        if(flag==false){
            System.out.println("顺序表中没有此元素");
        }
 
    }

删除所有出现的关键字:利用双指针进行遍历,设置right和left指针,如果遍历到待删除的元素,则right++,否则left++,将right所指的元素赋值给left。

/**
     * 删除顺序表中所有的key
     * @param val
     */
    public void removeAll(int val){
        int left=0;
        int right=0;
        while(right<usedSize){
            if(elem[right]==val){
                right++;
            }else{
                elem[left]=elem[right];
                left++;
                right++;
            }
        }
        usedSize=left;
    }

3、修改指定位置的元素

判断位置合法性,然后直接进行更新。

// 获取 pos 位置的元素
    public int get(int pos) {
        if(checkPosInAdd(pos)&&pos!=usedSize){
            return elem[pos];
        }else{
            throw new PosException("位置不合法");
        }
    }
// 给 pos 位置的元素设为更新为 value
    public void set(int pos, int value) {
        if(checkPosInAdd(pos)&&pos!=usedSize){
            elem[pos]=value;
        }
    }

4、遍历

    /**
     * 打印顺序表:
     *   根据usedSize判断即可
     */
    public void display() {
      for(int i=0;i<usedSize;i++){
          System.out.print(elem[i]+" ");
      }
        System.out.println();
    }

5、查看是否包含某个元素

// 判定是否包含某个元素
    public boolean contains(int toFind) {
        for(int i=0;i<usedSize;i++){
            if(elem[i]==toFind){
                return true;
            }
        }
        return false;
    }

6、查找元素下标

 // 查找某个元素对应的位置
    public int indexOf(int toFind) {
        for(int i=0;i<usedSize;i++){
            if(elem[i]==toFind){
                return i;
            }
        }
        return -1;
    }

7、获取指定位置的元素

首先判断位置的合法性,再进行查找。

// 获取 pos 位置的元素
    public int get(int pos) {
        if(checkPosInAdd(pos)&&pos!=usedSize){
            return elem[pos];
        }else{
            throw new PosException("位置不合法");
        }
    }

8、清空

将数组中的元素全部置为0,便于回收,修改数组的当前使用长度为0。

// 清空顺序表
    public void clear() {
        for (int i=0;i<usedSize;i++){
            elem[i]=0;
        }
        usedSize=0;
 
    }

三、顺序表的应用

1、杨辉三角

                         


利用二维数组的思想:定义一个泛型为顺序表的顺序表,将每一行的第一个元素和最后一个元素置为1,再利用杨辉三角的特点,当前元素的值=上一行这一列的元素+上一行前一列的元素,之后再将每一行都添加进去。

public static List<List<Integer>> yangHuiTriangle(int n){
        List<List<Integer>> list = new ArrayList();
        List<Integer> row = new ArrayList();
        row.add(1);
        list.add(row);
        for(int i=1;i<n;i++){
            List<Integer> preRow = list.get(i-1);
            List<Integer> currentRow = new ArrayList();
            currentRow.add(1);
            for(int j=1;j<i;j++ ){
                Integer m=preRow.get(new Integer(j))+preRow.get(j-1);
                currentRow.add(m);
            }
            currentRow.add(1);
            list.add(currentRow);
        }
        return list;
    }

2、简单的洗牌

a、定义一个牌类

首先需要定义一个牌类,有花色和大小两个属性。

public class Card {
    private char design;
    private int size;
 
    public Card(char design, int size) {
        this.design = design;
        this.size = size;
    }
 
    public char getDesign() {
        return design;
    }
 
    public void setDesign(char design) {
        this.design = design;
    }
 
    public int getSize() {
        return size;
    }
 
    public void setSize(int size) {
        this.size = size;
    }
 
    @Override
    public String toString() {
        return "{" + design +
                " " + size +
                '}';
    }
}

b、买牌

定义一个指定泛型为Card牌类的顺序表,然后再将52张牌(大小王除外)添加进去。

 /**
     * 买牌
     * 将52张牌(除大小王)加入到集合中
     * J、Q、K用11、12、13替代
     * @return
     */
    public List<Card> buyCard(){
        char[] design={'♥','♦','♣','♠'};
        List<Card> list=new ArrayList<>();
        for(int i=0;i<4;i++){
            for(int j=0;j<13;j++){
                list.add(new Card(design[i],j));
            }
        }
        return list;
    }

c、洗牌

将顺序表中存放的牌打乱:利用for循环,Random类生成一个随机数,然后与指定位置元素交换。

    /**
     * 洗牌:保证牌是乱序的
     */
    public List<Card> shuffle(List<Card> list){
        for(int i=list.size()-1;i>0;i--){
            Random random = new Random();
            int num=random.nextInt(i);
            swap(list,i,num);
        }
        return list;
    }
 
    /**
     * 将牌进行交换
     */
    private void swap(List<Card> list,int i,int j){
        Card card=list.get(i);
        list.set(i,list.get(j));
        list.set(j,card);
    }

d、发牌

假设有三个玩家,依次每人取五张牌:定义一个泛型为牌类顺序表的顺序表,每次从牌顺序表中移除牌向玩家顺序表中添加。

    /**
     * 发牌:三个人轮流连续发五张牌
     * @param list
     * @return
     */
    public List<List<Card>> deal(List<Card> list){
        List<List<Card>> player =new ArrayList<>();
        List<Card> player1=new ArrayList<>();
        List<Card> player2=new ArrayList<>();
        List<Card> player3=new ArrayList<>();
        player.add(player1);
        player.add(player2);
        player.add(player3);
        for(int i=0;i<5;i++){
            for(int j=0;j<3;j++){
                Card card =list.remove(0);
                player.get(j).add(card);
            }
        }
        return player;
    }

e、效果显示

public class Test {
    public static void main(String[] args) {
        Game game = new Game();
        List<Card> list = game.buyCard();
        System.out.println(list);
        System.out.println("洗牌:");
        game.shuffle(list);
        System.out.println(list);
        List<List<Card>> player=game.deal(list);
        List<Card> player1=player.get(0);
        List<Card> player2=player.get(1);
        List<Card> player3=player.get(2);
        System.out.println("玩家1:"+player1);
        System.out.println("玩家2:"+player2);
        System.out.println("玩家3:"+player3);
 
    }
}

运行结果:

目录
相关文章
|
2月前
|
存储 C语言
【数据结构】顺序表
数据结构中的动态顺序表
37 3
【数据结构】顺序表
|
3月前
|
存储
数据结构—顺序表(如果想知道顺序表的全部基础知识点,那么只看这一篇就足够了!)
数据结构—顺序表(如果想知道顺序表的全部基础知识点,那么只看这一篇就足够了!)
|
11天前
|
存储 Java 程序员
【数据结构】初识集合&深入剖析顺序表(Arraylist)
Java集合框架主要由接口、实现类及迭代器组成,包括Collection和Map两大类。Collection涵盖List(有序、可重复)、Set(无序、不可重复),Map则由键值对构成。集合通过接口定义基本操作,具体实现由各类如ArrayList、HashSet等提供。迭代器允许遍历集合而不暴露其实现细节。List系列集合元素有序且可重复,Set系列元素无序且不可重复。集合遍历可通过迭代器、增强for循环、普通for循环及Lambda表达式实现,各有适用场景。其中ArrayList实现了动态数组功能,可根据需求自动调整大小。
26 11
|
3月前
|
存储 缓存 算法
数据结构和算法学习记录——总结顺序表和链表(双向带头循环链表)的优缺点、CPU高速缓存命中率
数据结构和算法学习记录——总结顺序表和链表(双向带头循环链表)的优缺点、CPU高速缓存命中率
40 0
|
19天前
|
存储 C语言 C++
数据结构基础详解(C语言) 顺序表:顺序表静态分配和动态分配增删改查基本操作的基本介绍及c语言代码实现
本文介绍了顺序表的定义及其在C/C++中的实现方法。顺序表通过连续存储空间实现线性表,使逻辑上相邻的元素在物理位置上也相邻。文章详细描述了静态分配与动态分配两种方式下的顺序表定义、初始化、插入、删除、查找等基本操作,并提供了具体代码示例。静态分配方式下顺序表的长度固定,而动态分配则可根据需求调整大小。此外,还总结了顺序表的优点,如随机访问效率高、存储密度大,以及缺点,如扩展不便和插入删除操作成本高等特点。
|
19天前
|
存储 算法 C语言
C语言手撕数据结构代码_顺序表_静态存储_动态存储
本文介绍了基于静态和动态存储的顺序表操作实现,涵盖创建、删除、插入、合并、求交集与差集、逆置及循环移动等常见操作。通过详细的C语言代码示例,展示了如何高效地处理顺序表数据结构的各种问题。
|
1月前
|
存储 算法
【数据结构与算法】顺序表
【数据结构与算法】顺序表
16 0
【数据结构与算法】顺序表
|
1月前
|
存储 算法
【初阶数据结构篇】顺序表和链表算法题
此题可以先找到中间节点,然后把后半部分逆置,最近前后两部分一一比对,如果节点的值全部相同,则即为回文。
|
1月前
|
存储 测试技术
【初阶数据结构篇】顺序表的实现(赋源码)
线性表(linearlist)是n个具有相同特性的数据元素的有限序列。
|
1月前
|
存储 编译器
【数据结构】顺序表(长期维护)
【数据结构】顺序表(长期维护)