数据结构中顺序表,链表的操作及方法:
1.初始化→构造方法
2.增\删\查\改→普通方法
3.销毁→可能不存在
一.线性表
线性表:(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
二.顺序表
1.概念及结构:顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。顺序表一般可以分为:
①静态顺序表:使用定长数组存储。
②动态顺序表:使用动态开辟的数组存储。
2.接口实现:
public void pushBack(int element) //增在最后
public void pushFront(int element) //增在开头
public void insert(int index, int element) //要考虑是否把数插在数组下标以外的地方
public void popBack() //删最后
public void popFront() //删最前
public void earse(int index) //删中间
public void print() //打印
private void ensureCapacity() //扩容
public int indexOf(int element) //查数据内容,返回该数据的下标
public int get(int index) //查下标,返回该下标对应的数据
public void remove(int element) //删除掉某一个元素,如果出现多次,删除第一次出现的
public void removeAll(int element) { //删除表中所有出现的这个数据
3.顺序表应该考虑的问题:
①中间/头部的插入删除,时间复杂度为O(N);
②增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗;
③增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
4.写程序的步骤:写出伪代码再将代码翻译成java代码
5.扩容,增\删\查\改的思维引导:
考虑数组容量(array.length)和已有数据个数(size)之间的关系
1).容量够用:size<array.length;
2).容量不够用:(类似搬家,搬到以前家的1.5或2倍大)
int newCapacity=array.length*2;
①搬新家(重新定义一个数组,大内存)
int[] newArray=new int[newCapacity];
②搬家(把原来数组内容放到新数组中)
for(int i=0;i<size;i++){
newArray[i]=array[i];
}
③告诉别人搬家了(访问新的属性)
this.Array=newArray;
④退掉老房子:原来的数组对象没有引用指向,自动释放变成垃圾。
6.画图演示顺序表的增/删
7.范例
// 顺序表的元素类型 int
public class MyArrayList1 {
// 属性是什么
private int[] array; // 代表的是存在数据的数组
// array.length 代表的是数组的容量
private int size; // 记录顺序表的已有数据个数
// 构造方法
public MyArrayList1() {
// 1. 申请空间
array = new int[2];
// 2. 初始化数据个数
size = 0;
}
//index 需要插入的数据的下标;element 需要插入的数据
// 增(重点)
// 平均 O(1)
public void pushBack(int element) { //增在最后
ensureCapacity(); //调用扩容函数,增容
array[size++] = element; //直接把数插到最后即可
}
public void pushFront(int element) { //增在开头
ensureCapacity(); //调用扩容函数,增容
for (int i = size; i >= 1; i--) {
array[i] = array[i - 1]; //用循环把前一个数赋给后一个数
}
//此时下标为0的地方为空
array[0] = element; //把要插入的数赋给下标为0的地方
size++; //让size自增一次
}
public void insert(int index, int element) { //要考虑是否把数插在数组下标以外的地方
if (index < 0 || index > size) { //只要满足一个条件就输出“下标错误”
System.err.println("下标错误");
return;
}
ensureCapacity();
for (int i = size - 1; i >= index; i--) {
array[i + 1] = array[i];
}
//for(int i=size;i>=index;i--){array[i]=array[i-1];}size++;
array[index] = element;
size++;
}
// 删(重点)
public void popBack() { //删最后
if (size <= 0) { //顺序表为空则输出“顺序表为空”
System.err.println("顺序表为空");
return;
}
array[--size] = 0; //在原数组中让size-1为0即可,即size先--再引用
}
public void popFront() { //删最前
if (size <= 0) {
System.err.println("顺序表为空");
return;
}
//删最前面的数时,将后一个数赋给前一个数即可
//for后面一般是修改后的数组的范围
for (int i = 0; i < size - 1; i++) {
array[i] = array[i + 1];
}
array[--size] = 0;
}
public void earse(int index) { //删中间
if (size <= 0) {
System.err.println("顺序表为空");
return;
}
if (index < 0 || index >= size) {
System.err.println("下标错误");
return;
}
for (int i = index + 1; i < size; i++) {
array[i - 1] = array[i];
}
//for(int i=index;i<size-1;i++){array[i]=array[i+1];}
array[--size] = 0;
}
// 打印
public void print() {
System.out.println("打印顺序表: 当前容量: " + array.length);
for (int i = 0; i < size; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
// 保证容量够用,否则进行扩容
private void ensureCapacity() {
if (size < array.length) {
return;
}
int newCapacity = array.length * 2;
int[] newArray = new int[newCapacity];
for (int i = 0; i < size; i++) {
newArray[i] = array[i];
}
this.array = newArray; //访问属性
}
//查 返回 element 在顺序表中的下标,如果出现多次,返回第一次出现的下标
public int indexOf(int element) {
for (int i = 0; i < size; i++) {
if (array[i] == element) {
return i;
}
}
return -1;
}
//get是查的第二种方式,返回的是那个下标所在的值
public int get(int index) {
if (index < 0 || index >= size) {
System.err.println("下标错误");
return -1;
}
return array[index];
}
//set是改
public void set(int index, int element) {
if (index < 0 || index >= size) {
System.err.println("下标错误");
return;
}
array[index] = element;
}
//删除掉某一个元素,如果出现多次,删除第一次出现的
public void remove(int element) {
int mindex = indexOf(element); //调用indexOf函数找到那个数字的下标
if (index != -1) { //说明那个数在表内
earse(index); //调用earse函数进行删除下标为index的数
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void removeAll(int element) { //删除表中所有出现的这个数据
int j = 0;
for (int i = 0; i < size; i++) {
if (array[i] != element) {
array[j++] = array[i];
}
}
size = j;
}
public static void main(String[] args) {
MyArrayList1 list = new MyArrayList1();
list.print();
list.pushBack(1);
list.pushBack(2);
list.pushBack(3);
// 1 2 3
list.print();
list.pushFront(10);
list.pushFront(20);
list.pushFront(30);
// 30 20 10 1 2 3
list.print();
list.insert(3, 100);
// 30 20 10 100 1 2 3
list.print();
list.insert(20, 200);
// 报错
list.earse(2);
list.earse(2);
list.print();
// 30 20 1 2 3
list.popFront();
list.popFront();
list.popFront();
list.print();
// 2 3
list.popBack();
list.popBack();
list.print();
// 空的
list.popBack();
// 报错
}
}
运行结果:
IDE (集成开发环境)| Integration Development Environment
notepad++ 编辑器(Text Editor)
javac 编译器(Compiler)
java 运行环境(Runtime)
jdb 调试器(Debugger)