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倍的增长,势必会有一定的空间浪费。