• 数据结构——顺序表


    目录

    一、什么是顺序表?

    二、模拟实现顺序表 

    1、添加元素

    2、删除元素

    3、修改指定位置的元素 

    4、遍历 

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

    6、查找元素下标 

    7、获取指定位置的元素 

    8、清空 

    三、顺序表的应用 

    1、杨辉三角

     2、简单的洗牌

    a、定义一个牌类

    b、买牌 

    c、洗牌 

    d、发牌 

    e、效果显示 


    一、什么是顺序表

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

    顺序表的特点:

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

    二、模拟实现顺序表 

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

    1. public int[] elem;
    2. public int usedSize;//0
    3. //默认容量
    4. private static final int DEFAULT_SIZE = 10;
    5. public MyArrayList() {
    6. this.elem = new int[DEFAULT_SIZE];
    7. }

    1、添加元素

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

    1. /**
    2. * 判断当前的顺序表是不是满的!
    3. * @return true:满 false代表空
    4. */
    5. public boolean isFull() {
    6. if(usedSize==elem.length){
    7. return true;
    8. }
    9. return false;
    10. }
    11. /**
    12. * 扩容(实际上顺序表底层扩容为1.5倍)
    13. */
    14. public void reSize(){
    15. this.elem= Arrays.copyOf(elem,2*elem.length);
    16. }
    17. // 新增元素,默认在数组最后新增
    18. public void add(int data) {
    19. if(isFull()){
    20. reSize();
    21. }
    22. elem[usedSize]=data;
    23. usedSize++;
    24. }

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

    1. // 在 pos 位置新增元素
    2. public void add(int pos, int data) {
    3. if(checkPosInAdd(pos)&&!isFull()){
    4. for(int j=usedSize-1;j>=pos;j--){
    5. elem[j+1]=elem[j];
    6. }
    7. elem[pos]=data;
    8. usedSize++;
    9. }
    10. }

    2、删除元素

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

    1. /**
    2. * 删除第一次出现的关键字key
    3. * @param key
    4. */
    5. public void remove(int key) {
    6. boolean flag=false;
    7. for(int i=0;i<usedSize;i++){
    8. if(elem[i]==key){
    9. flag=true;
    10. for(int j=i;j<usedSize-1;j++){
    11. elem[j]=elem[j+1];
    12. }
    13. elem[usedSize-1]=0;
    14. usedSize--;
    15. break;
    16. }
    17. }
    18. if(flag==false){
    19. System.out.println("顺序表中没有此元素");
    20. }
    21. }

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

    1. /**
    2. * 删除顺序表中所有的key
    3. * @param val
    4. */
    5. public void removeAll(int val){
    6. int left=0;
    7. int right=0;
    8. while(right<usedSize){
    9. if(elem[right]==val){
    10. right++;
    11. }else{
    12. elem[left]=elem[right];
    13. left++;
    14. right++;
    15. }
    16. }
    17. usedSize=left;
    18. }

    3、修改指定位置的元素 

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

    1. // 获取 pos 位置的元素
    2. public int get(int pos) {
    3. if(checkPosInAdd(pos)&&pos!=usedSize){
    4. return elem[pos];
    5. }else{
    6. throw new PosException("位置不合法");
    7. }
    8. }
    9. // 给 pos 位置的元素设为更新为 value
    10. public void set(int pos, int value) {
    11. if(checkPosInAdd(pos)&&pos!=usedSize){
    12. elem[pos]=value;
    13. }
    14. }

    4、遍历 

    1. /**
    2. * 打印顺序表:
    3. * 根据usedSize判断即可
    4. */
    5. public void display() {
    6. for(int i=0;i<usedSize;i++){
    7. System.out.print(elem[i]+" ");
    8. }
    9. System.out.println();
    10. }

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

    1. // 判定是否包含某个元素
    2. public boolean contains(int toFind) {
    3. for(int i=0;i<usedSize;i++){
    4. if(elem[i]==toFind){
    5. return true;
    6. }
    7. }
    8. return false;
    9. }

    6、查找元素下标 

    1. // 查找某个元素对应的位置
    2. public int indexOf(int toFind) {
    3. for(int i=0;i<usedSize;i++){
    4. if(elem[i]==toFind){
    5. return i;
    6. }
    7. }
    8. return -1;
    9. }

    7、获取指定位置的元素 

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

    1. // 获取 pos 位置的元素
    2. public int get(int pos) {
    3. if(checkPosInAdd(pos)&&pos!=usedSize){
    4. return elem[pos];
    5. }else{
    6. throw new PosException("位置不合法");
    7. }
    8. }

    8、清空 

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

    1. // 清空顺序表
    2. public void clear() {
    3. for (int i=0;i<usedSize;i++){
    4. elem[i]=0;
    5. }
    6. usedSize=0;
    7. }

    三、顺序表的应用 

    1、杨辉三角

                                 

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

    1. public static List<List<Integer>> yangHuiTriangle(int n){
    2. List<List<Integer>> list = new ArrayList();
    3. List<Integer> row = new ArrayList();
    4. row.add(1);
    5. list.add(row);
    6. for(int i=1;i<n;i++){
    7. List<Integer> preRow = list.get(i-1);
    8. List<Integer> currentRow = new ArrayList();
    9. currentRow.add(1);
    10. for(int j=1;j<i;j++ ){
    11. Integer m=preRow.get(new Integer(j))+preRow.get(j-1);
    12. currentRow.add(m);
    13. }
    14. currentRow.add(1);
    15. list.add(currentRow);
    16. }
    17. return list;
    18. }

     2、简单的洗牌

    a、定义一个牌类

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

    1. public class Card {
    2. private char design;
    3. private int size;
    4. public Card(char design, int size) {
    5. this.design = design;
    6. this.size = size;
    7. }
    8. public char getDesign() {
    9. return design;
    10. }
    11. public void setDesign(char design) {
    12. this.design = design;
    13. }
    14. public int getSize() {
    15. return size;
    16. }
    17. public void setSize(int size) {
    18. this.size = size;
    19. }
    20. @Override
    21. public String toString() {
    22. return "{" + design +
    23. " " + size +
    24. '}';
    25. }
    26. }

    b、买牌 

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

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

    c、洗牌 

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

    1. /**
    2. * 洗牌:保证牌是乱序的
    3. */
    4. public List<Card> shuffle(List<Card> list){
    5. for(int i=list.size()-1;i>0;i--){
    6. Random random = new Random();
    7. int num=random.nextInt(i);
    8. swap(list,i,num);
    9. }
    10. return list;
    11. }
    12. /**
    13. * 将牌进行交换
    14. */
    15. private void swap(List<Card> list,int i,int j){
    16. Card card=list.get(i);
    17. list.set(i,list.get(j));
    18. list.set(j,card);
    19. }

    d、发牌 

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

    1. /**
    2. * 发牌:三个人轮流连续发五张牌
    3. * @param list
    4. * @return
    5. */
    6. public List<List<Card>> deal(List list){
    7. List<List<Card>> player =new ArrayList<>();
    8. List<Card> player1=new ArrayList<>();
    9. List<Card> player2=new ArrayList<>();
    10. List<Card> player3=new ArrayList<>();
    11. player.add(player1);
    12. player.add(player2);
    13. player.add(player3);
    14. for(int i=0;i<5;i++){
    15. for(int j=0;j<3;j++){
    16. Card card =list.remove(0);
    17. player.get(j).add(card);
    18. }
    19. }
    20. return player;
    21. }

    e、效果显示 

    1. public class Test {
    2. public static void main(String[] args) {
    3. Game game = new Game();
    4. List<Card> list = game.buyCard();
    5. System.out.println(list);
    6. System.out.println("洗牌:");
    7. game.shuffle(list);
    8. System.out.println(list);
    9. List<List<Card>> player=game.deal(list);
    10. List<Card> player1=player.get(0);
    11. List<Card> player2=player.get(1);
    12. List<Card> player3=player.get(2);
    13. System.out.println("玩家1:"+player1);
    14. System.out.println("玩家2:"+player2);
    15. System.out.println("玩家3:"+player3);
    16. }
    17. }

    运行结果:

  • 相关阅读:
    CountDownLatch使用及原理
    Elasticsearch语句—SQL详解
    Spring中的依赖注入、setter与构造器注入、自动装配与集合注入详细描述及使用(XML版中篇)
    代码随想录算法训练营第四十六天 | LeetCode 139. 单词拆分、多重背包、背包总结
    聚观早报 | 羊了个羊幕后推手月流水曾破亿;雷军卸任小米董事长
    【Python基础】函数
    现在啥软件都有开源,BI 呢?
    C++STL常用算法合集(上)
    linux命令详解之-find精确查找和高级使用
    最新版成人高考专升本高数一、高数二有什么区别?
  • 原文地址:https://blog.csdn.net/m0_62404808/article/details/128100529