数据结构---顺序表与ArrayList

本文详细介绍了Java中顺序表的数据结构,包括顺序表的原理、自己实现的顺序表(如MyArrayList和ArrayList)方法,以及其实现中的数组扩容、遍历策略,并讨论了顺序表的优缺点和应用场景,如扑克牌游戏和杨辉三角计算。
摘要由CSDN通过智能技术生成

1.线性表

具有n个相同特性的数据元素的有限序列。常见的线性表有顺序表,链表,栈,队列....

线性表逻辑上连续,物理上(内存上)不一定连续

2.顺序表

顺序表是物理上连续存储数据元素的线性结构,一般采用数组存储 ,数组上完成增删查改。里面包含很多方法可以对数组进行增删查改以及求我们的有效数字等

3.自己实现顺序表的一些方法 

import java.util.Arrays;

public class MyArrayList {
    //    定义一个数组
    public int[] elem;
    //    默认给数字分配空间
    public static final int DEFAUL_CaPACITY=10;
    //构造方法赋值
    public MyArrayList(){
        this.elem=new int[DEFAUL_CaPACITY];
    }
    //有效数字
    public int usedsize;
    // 打印顺序表,打印usedsize下标就可以
    public void display() {
        int i=0;
        for (i=0;i<usedsize;i++){
            System.out.print(elem[i]+" ");
        }
        System.out.println();
    }
    //判断数组是否越界
    public boolean isfull(){
        return usedsize==elem.length;
    }
    // 新增元素,默认在数组最后新增
    public void add(int data) {
        //要判断数组内存大小
        if (isfull()){
            //数组满了要扩容
            Arrays.copyOf(elem,2*elem.length);
        }
     elem[usedsize]=data;
     usedsize++;
    }
    //判断下标是否正确
    public void index(int index){
        if (index<0||index>usedsize){
            throw new PosIndexnotLengthException("位置不合法异常");
        }
    }
    // 在 pos 位置新增元素
    public void add(int pos, int data) {
        //先判断下标
       try {
           index(pos);
           //下标合法
           //依次向后遍历放数组元素
           for (int i=usedsize-1;i>=pos;i--){
               elem[i+1]=elem[i];
           }
           elem[pos]=data;
           usedsize++;
       }catch (PosIndexnotLengthException e){
           e.printStackTrace();
       }
    }
    // 判定是否包含某个元素
    public boolean contains(int toFind) {
        //遍历元素
        for (int i=0;i<usedsize-1;i++){
            if (elem[i]==toFind){
                return true;
            }
        }
        return false;
    }
    // 查找某个元素对应的位置
    public int indexOf(int toFind) {
        for (int i=0;i<usedsize-1;i++){
            if (elem[i]==toFind){
                return i;
            }
        }
          return -1;
    }
    // 获取 pos 位置的元素
    public int get(int pos) {
        //检查pos位置的合法行
        index(pos);
        //合法的会返回
        return elem[pos];
    }
    // 给 pos 位置的元素设为 value
    public void set(int pos, int value) {
        //检查pos位置合法性
        index(pos);
        elem[pos]=value;
    }
    //删除第一次出现的关键字key
    public void remove(int toRemove) {
        //找到这个元素对应的位置
        int index=indexOf(toRemove);
        //没有找到
        if (index==-1){
            System.out.println("没有要删除的数字");
            return;
        }
        //找到
        for (int i=index;i<usedsize-1;i++){
            elem[i]=elem[i+1];
        }
        usedsize--;
    }
    // 获取顺序表长度
    public int size() {
        return usedsize;
    }
    // 清空顺序表
    public void clear() {
        //有效个数为0
      usedsize=0;
    }

    public static void main(String[] args) {
        MyArrayList myArrayList=new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(4);
        myArrayList.display();
        myArrayList.add(2,100);
        myArrayList.display();
        System.out.println(myArrayList.contains(100));
        System.out.println(myArrayList.indexOf(100));
        System.out.println(myArrayList.get(2));
        myArrayList.remove(100);
        myArrayList.display();
    }

}

4.Java里面自己实现的顺序表

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("JavaSE");
        arrayList.add("JavaWeb");
        arrayList.add("JavaEE");
        arrayList.add("JVM");
        arrayList.add("测试课程");
        System.out.println(arrayList);
// 获取list中有效元素个数
        System.out.println(arrayList.size());
// 获取和设置index位置上的元素,注意index必须介于[0, size)间
        System.out.println(arrayList.get(1));
        arrayList.set(1, "JavaWEB");
        System.out.println(arrayList.get(1));
// 在list的index位置插入指定元素,index及后续的元素统一往后搬移一个位置
        arrayList.add(1, "Java数据结构");
        System.out.println(arrayList);
// 删除指定元素,找到了就删除,该元素之后的元素统一往前搬移一个位置
        arrayList.remove("JVM");
        System.out.println(arrayList);
// 删除list中index位置上的元素,注意index不要超过list中有效元素个数,否则会抛出下标越界异常
        arrayList.remove(arrayList.size() - 1);
        System.out.println(arrayList);

    }
}

5.Java数组的扩容 

 

6.顺序表的3种遍历

import java.util.ArrayList;
import java.util.Iterator;

public class Test1 {
    //顺序表的遍历
    public static void main(String[] args) {
        ArrayList<Integer>arrayList=new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
//        for循环遍历
        for (int i=0;i< arrayList.size();i++){
            System.out.print(arrayList.get(i)+" ");
        }
        System.out.println();
//    foreach循环
        for (Integer integer:arrayList) {
            System.out.print(integer+" ");
        }
        System.out.println();
//       使用迭代器
        Iterator<Integer>iterator= arrayList.listIterator();
        while (iterator.hasNext()){
            System.out.print(iterator.next()+" ");
        }
        System.out.println();
    }
}

7.顺序表的应用,扑克牌 

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

class Card{
    //牌面值
    public int rank;
    //花色
    public String suit;
    //提供构造方法
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
    //重写tostring可以打印出来

    @Override
    public String toString() {
        return "Card{" +
                "rank=" + rank +
                ", suit='" + suit + '\'' +
                '}';
    }
}
public class Carddemo {
    //cards相当于是包装袋
    List<Card>cards=new ArrayList<>();
    //花色枚举出来
    public static final String[]suits={"♥","♠","♣","♦"};
    //买一副牌,因为有很多牌所以放在list里
    public List<Card> buyDeskCard(){
        //数字大小
        for (int i = 1; i <=13 ; i++) {
            //每张牌的花色
            for (int j = 0; j < 4; j++) {
                Card card=new Card(i,suits[j]);
                //只要有1张牌就放在cards里
                cards.add(card);
            }
        }
        return cards;
    }
    //交换逻辑
    public void swap(List<Card> cards,int i,int j){
        Card tmp=cards.get(i);
        cards.set(i,cards.get(j));
        cards.set(j,tmp);
    }
    public void shuffle(List<Card> cards){
        //使用随机数将牌洗
        Random random=new Random(1000);
        //后面与前面随机交换
        for (int i = cards.size()-1; i >0 ; i--) {
            int index=random.nextInt(i);
            //交换一下
            swap(cards,index,i);
        }
    }
    //玩牌
    public List<List<Card>> test(List<Card> cards){
        //每个人都有自己list,截一张放自己的liest里面
        List<Card>hand1=new ArrayList<>();
        List<Card>hand2=new ArrayList<>();
        List<Card>hand3=new ArrayList<>();
        //把这些hand组织起来,就知道放在哪个hand里面
        List<List<Card>> hands=new ArrayList<>();
        hands.add(hand1);
        hands.add(hand2);
        hands.add(hand3);
        //每个人摸5张牌
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 3; j++) {
                hands.get(j).add(cards.remove(0));
            }
        }
        return hands;
    }
}

8.顺序表的应用,杨辉三角 

 

public class Test {

    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> ret = new ArrayList<>();

        List<Integer> list = new ArrayList<>();
        list.add(1);

        ret.add(list);

        for (int i = 1; i < numRows; i++) {
            List<Integer> curRow = new ArrayList<>();
            curRow.add(1);
            //上一行
            List<Integer> prevRow = ret.get(i-1);
            for (int j = 1; j < i; j++) {
                int num = prevRow.get(j)+prevRow.get(j-1);
                curRow.add(num);
            }
            curRow.add(1);
            ret.add(curRow);
        }
        return ret;
    }

9.顺序表的缺点

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

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

3. 增容一般是呈1.5倍的增长,势必会有一定的空间浪费。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值