线性表是n个具有相同特性的数据元素的有限序列,线性表是一种在实际中广泛使用的数据结构。线性表在逻辑上是线性结构,也就是说是连续的一条直线,但是在物理上不一定是连续的,线性表在物理上存储的时候,通常以数组和链式结构的形式存储,常见的线性表:顺序表、链表、栈、队列...
一、顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改
二、ArrayList简介
在集合框架中,ArrayList是一个普通的类,实现了List接口
由框架图可知:
1、ArrayList是以泛型方式实现的,使用时必须要实例化
2、ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
3、ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
4、ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
5、ArrayList不是线程安全的,在单线程下可以使用
6、ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表
三、ArrayList使用
1、ArrayList的三种构造方法
ArrayList() 无参构造
ArrayList(Collection<? extends E> c) 利用其他Collection构建ArrayList
ArrayList(int initialCapacity) 指定顺序表初始容量
import java.util.ArrayList;
import java.util.List;
public class Main1001_1 {
public static void main(String[] args) {
//ArrayList的三种构造方法
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>(5);
list2.add("aaa");
list2.add("bbb");
list2.add("ccc");
list2.add("ddd");
list2.add("eee");
System.out.println(list2);
ArrayList<String> list3 = new ArrayList<>(list2);
//通过一个集合快速构造出包含传入元素所有元素的新集合
System.out.println(list3);
}
}
2、 ArrayList的常见操作
boolean contains(Object o) | 判断o是否在线性表中 |
int indexOf(Object o) | 返回第一个o所在下标 |
int lastIndexOf(Object o) | 返回最后一个o的下标 |
List<E> subList(int fromIndex, int toIndex) | 截取部分list |
List<E> subList(int fromIndex, int toIndex):
import java.util.ArrayList;
import java.util.List;
public class Main1001_1 {
public static void main(String[] args) {
//ArrayList的三种构造方法
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>(5);
list2.add("aaa");
list2.add("bbb");
list2.add("ccc");
list2.add("ddd");
list2.add("eee");
System.out.println(list2);
ArrayList<String> list3 = new ArrayList<>(list2);
//通过一个集合快速构造出包含传入元素所有元素的新集合
System.out.println(list3);
//sublist
List<String> list4 = list2.subList(1,3);
System.out.println(list4);//左闭右开
//修改这个子集合
list4.set(0,"hello");
System.out.println(list4);
System.out.println(list2);//list2的值也随之修改,注意引用类型的操作
}
}
3、ArrayList的遍历
ArrayList可以使用三种方式进行遍历:for循环+ 下标、foreach、使用迭代器
import java.util.ArrayList;
public class Main1001_2 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
//遍历的三种方法,这里先介绍前两种
for(int i = 0;i < list.size();i++){
System.out.print(list.get(i) + " ");
}
System.out.println();
for(int num : list){
System.out.print(num + " ");
}
}
}
4、 ArrayList的扩容机制
ArrayList是一个动态类型的顺序表,在插入元素的过程中会自动扩容
1)调用无参构造方法,初始化ArrayList对象,底层创建了一个空数组,第一次add的时候才去指定数组的容量
2)扩容是以1.5倍的容量去扩容的
3)ArrayList底层是以数组存储数据的
四、自己实现MyArraylist
import java.util.Arrays;
public class MyArraylist {
public int[] elem;
public int usedSize;//0
//默认容量
private static final int DEFAULT_SIZE = 10;
public MyArraylist() {
this.elem = new int[DEFAULT_SIZE];
}
/**
* 打印顺序表:
* 根据usedSize判断即可
*/
public void display() {
if(usedSize == 0){
System.out.println("[]");
return;
}
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i = 0;i < usedSize;i++){
sb.append(this.elem[i]);
if(i < usedSize - 1){
sb.append(", ");
}
}
sb.append("]");
System.out.println(sb.toString());
}
// 新增元素,默认在数组最后新增
public void add(int data) {
//数据满的时候我们需要进行扩容,扩容的规则是以当前容量的二倍的大小进行
//1、判断是否已满
if(isFull()){
this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
}
this.elem[usedSize] = data;
usedSize++;
}
/**
* 判断当前的顺序表是不是满的!
*
* @return true:满 false代表空
*/
public boolean isFull() {
return usedSize == this.elem.length;
}
private boolean checkPosInAdd(int pos) {
if(pos < 0 || pos > this.elem.length){
throw new IndexOutOfBoundsException("下标异常");
}
return true;//合法
}
// 在 pos 位置新增元素
public void add(int pos, int data) {
//1、判断当前位置是否合法
checkPosInAdd(pos);
//2、判断是否已满
if(isFull()){
this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
}
//3、把pos之后的位置向后移
for(int i = usedSize;i > pos;i--){
this.elem[i] = this.elem[i - 1];
}
//4、把新增的元素插入进去
this.elem[pos] = data;
//5、有效位数加一
usedSize++;
}
// 判定是否包含某个元素
public boolean contains(int toFind) {
for(int i = 0;i < usedSize;i++){
if(this.elem[i] == toFind){
return true;
}
}
return false;
}
// 查找某个元素对应的位置
public int indexOf(int toFind) {
for(int i = 0;i < usedSize;i++){
if(this.elem[i] == toFind){
return i;
}
}
return -1;
}
// 获取 pos 位置的元素
public int get(int pos) {
checkPosInAdd(pos);
return this.elem[pos];
}
private boolean isEmpty() {
if(usedSize == 0){
return true;
}
return false;
}
// 给 pos 位置的元素设为【更新为】 value
public void set(int pos, int value) {
checkPosInAdd(pos);
this.elem[pos] = value;
}
/**
* 删除第一次出现的关键字key
*
* @param key
*/
public void remove(int key) {
int index = indexOf(key);
if(index == -1){
return;
}
for(int i = index;i < usedSize;i++){
this.elem[i] = this.elem[i + 1];
}
usedSize--;
}
// 获取顺序表长度
public int size() {
return usedSize;
}
// 清空顺序表
public void clear() {
usedSize = 0;
// //如果是引用类型,每个下标的元素都应该置为null
// for(int i = 0;i < usedSize;i++){
// this.elem[i] = null;
// }
}
}
public class Test {
public static void main(String[] args) {
MyArraylist list = new MyArraylist();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.display();
list.add(1,10);
list.display();
System.out.println(list.contains(5));
System.out.println(list.indexOf(5));
System.out.println(list.get(3));
list.set(3,33);
list.display();
list.remove(33);
list.display();
}
}
五、使用ArrayList实现扑克牌
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Poker {
private String suit;
private int rank;
public Poker() {
}
@Override
public String toString() {
return "[" + suit + " " + rank + "]";
}
public Poker(String suit, int rank) {
this.suit = suit;
this.rank = rank;
}
private static final String[] suits = {"♠","♥","♣","♦"};
//买一副新牌
public static List<Poker> buy(){
List<Poker> pokers = new ArrayList<>();
for(int i = 0;i < 3;i++){
for(int j = 1;j <= 13;j++){
String suitTemp = suits[i];
pokers.add(new Poker(suitTemp,j));
}
}
return pokers;
}
//洗牌
public static void shuffle(List<Poker> pokers){
//判断参数是否为空
if(pokers == null){
throw new RuntimeException("不能为空");
}
Random random = new Random();
//开始洗牌
for(int i = 0;i < pokers.size();i++){
int index = random.nextInt(pokers.size());//[0,pokers.size())
Poker temp = pokers.get(index);
pokers.set(index,pokers.get(i));
pokers.set(i,temp);
}
}
//发牌
public static List<List<Poker>> toDeting(List<Poker> pokers){
//这个集合里面包含了所有的玩家
List<List<Poker>> players = new ArrayList<>();
//定义每个玩家,这里假设有三个
for(int i = 0;i < 3;i++){
List<Poker> player = new ArrayList<>();
//把玩家加入集合
players.add(player);
}
//开始发牌
for(int i = 0;i < 5;i++){
for(int j = 0;j < players.size();j++){
//先获取玩家
List<Poker> player = players.get(j);
Poker poker = pokers.remove(0);
//把拿到的牌加到玩家的list里面
player.add(poker);
}
}
return players;
}
public String getSuit() {
return suit;
}
public void setSuit(String suit) {
this.suit = suit;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
}
import java.util.ArrayList;
import java.util.List;
public class TestPoker {
public static void main(String[] args) {
List<Poker> pokers = Poker.buy();
System.out.println("新生成一副牌" + pokers);
//洗牌
Poker.shuffle(pokers);
System.out.println("洗牌之后" + pokers);
//测试发牌
List<List<Poker>> players = Poker.toDeting(pokers);
for(int i = 0;i < players.size();i++){
System.out.println("玩家" + (i + 1) + ":" + players.get(i));
}
System.out.println("剩下的牌");
System.out.println(pokers);
}
}