一、线性表的定义
线性表
是同一类型数据的一个有限序列
,线性表中数据元素之间的关系是一对一的关系
,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接
的。
线性表的顺序存储要求地址空间是连续的,地址必须一个接一个,不能中断
。如下图为顺序存储结构:
二、顺序存储结构
线性表
的顺序存储每个节点只包含数据部分
,不需要额外包含数据之间的关系,因为数据之间
的关系通过地址连续
来体现,所以非常省空间
它的优点访问非常快速,因为地址是连续的
,只要知道首地址,任意一个元素的地址都可以算出来。假设每个地址占c个空间,则第i个地址为(i-1)*c。
它的缺点是在插入和删除数据时
,可能要移动许多数据,比如一个10000个元素的有序数据,如果我删除了第二个元素,为了继续保持地址连续,所以要把后面9999个元素都向前移动。
三、栈的定义
栈(stack)是限定仅在表尾
进行插入和删除操作的线性表
。
我们把允许插入和删除的一端称为栈顶(top)
,另一端称为栈底(bottom)
。
栈又称作后进先出线性表——Last In First Out(LIFO)
注意:栈是一个被限制的线性表,不提供从中间任何位置删除、插入、访问元素的方法。也就是说栈只能够在栈顶插入和删除元素
。
栈来自与线性表
,因此栈
可以使用顺序表
的方式来实现也可以使用链表的方式
来实现。
系统栈记录中断的点,调用完其他方法后继续运行
代码:
Array.class
package code.ArrayCode;
public class Array<E> {
private E[] data;
private int size;
/*
* 构造函数,传入数据的容量capacity构造Array
* */
public Array(int capacity){
data = (E[])new Object[capacity];
size = 0;
}
//无参数的构造函数,默认数据的容量capacity=10
public Array(){
this(10);
}
//获取数组中的元素个数
public int getSize(){
return size;
}
//获取数组的容量
public int getCapacity(){
return data.length;
}
//返回数组是否为空
public boolean isEmpty(){
return size==0;
}
//在最后一位添加数据
public void addLast(E e){
add(size,e);
}
//在开头添加数据
public void addFirst(E e){
add(0,e);
}
public void add(int index , E e){
//判断index是不是合法的
// 如果index为负数则不合法
// 如果index > size则说明数组中间有空余的位置,并非紧密排列
if(index < 0 || index > size){
throw new IllegalArgumentException("Add failed. Require index >= 0 || index <= size.");
}
//判断数组满了没有
if(size == data.length){
resize(2 * data.length);
}
//从最后一位开始移位,当i=index的时候,index位置上还是有原来位置的数据,
//只不过index和index+1这两个位置的数据一样,原来index位置上的值复制到了index+1
//所以我们可以放心的用新数据覆盖掉index位置上的值
for(int i = size -1 ; i >= index ; i--){
data[i+1] = data[i];
}
//用新值覆盖原index位置上的值
data[index] = e;
size++;
}
//取出索引为index的这个元素
//通过get方法是无法获取没有值的索引
E get(int index){
if(index < 0 || index > size){
throw new IllegalArgumentException("Get failed. Require index >= 0 || index <= size.");
}
return data[index];
}
//在指定索引位置修改数据
void set(int index, E e){
if(index < 0 || index > size){
throw new IllegalArgumentException("Set failed. Require index >= 0 || index <= size.");
}
data[index] = e;
}
//查找数组中是否有元素e
public boolean contains(E e){
for(int i =0 ; i < size; i++){
if(data[i].equals(e)){
return true;
}
}
return false;
}
//查找数组中元素e所在的索引,如果不存在元素e,则返回-1
public int find(E e){
for(int i =0 ; i < size; i++){
if(data[i].equals(e)){
return i;
}
}
return -1;
}
//从数组中删除index位置的元素,返回删除的元素
public E remove(int index){
if(index < 0 || index > size){
throw new IllegalArgumentException("Remove failed. Require index >= 0 || index <= size.");
}
E ret = data[index];
for(int i = index+1 ; i<size ; i++){
//把后边的值赋给前面的值,覆盖掉前面节点的值,实现删除作用
data[i-1] = data[i];
}
size--;
//把size索引所在的值设置为null,让它被垃圾回收
data[size] = null;
if(size == data.length / 4 && data.length / 2 !=0){
resize(data.length / 2);
}
return ret;
}
//从数组中删除第一个元素,返回删除的元素
public E removeFirst(){
return remove(0);
}
//从数组中删除最后一个元素,返回删除的元素
public E removeLast(){
return remove(size-1);
}
//从数组中删除元素e
public void removeElement(E e){
int index = find(e);
if(index != -1){
remove(index);
}
}
public E getLast(){
return get(size-1);
}
public E getFirst(){
return get(0);
}
@Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append(String.format("Array: size = %d , capacity = %d\n" , size, data.length));
res.append("[");
for(int i =0 ; i < size ; i++){
res.append(data[i]);
//如果当前size不是最后一个,则添加一个,
if(i != size-1){
res.append(", ");
}
}
res.append("]");
return res.toString();
}
//增容和缩容操作
private void resize(int newCapacity){
E[] newData = (E[])new Object[newCapacity];
for(int i =0 ; i < size ; i++){
newData[i] = data[i];
}
data = newData;
}
public void test(){
int[] arr = new int[20];
for(int i=0;i<arr.length;i++){
arr[i]=i;
}
//scores开辟三个int值的数组
int[] scores = new int[]{100,99,66};
for(int i=0;i<scores.length;i++){
System.out.println(scores[i]);
}
}
}
ArrayStack.class
package code.ArrayCode;
public class ArrayStack<E> implements Stack<E> {
Array<E> array;
public ArrayStack(int capacity){
array = new Array(capacity);
}
public ArrayStack(){
array = new Array();
}
public int getSize() {
return array.getSize();
}
public boolean isEmpty() {
return array.isEmpty();
}
public int getCapacity(){
return array.getCapacity();
}
public void push(E e) {
array.addLast(e);
}
public E pop() {
return array.removeLast();
}
public E peek() {
return array.getLast();
}
@Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append("Stack: ");
res.append("[");
for(int i =0 ; i < array.getSize() ; i++){
res.append(array.get(i));
//如果当前size不是最后一个,则添加一个,
if(i != array.getSize() -1){
res.append(", ");
}
}
res.append("] top");
return res.toString();
}
}
Stack.class
package code.ArrayCode;
public interface Stack<E> {
int getSize();
boolean isEmpty();
void push(E e);
E pop();
E peek();
}
测试:
public class Main {
public static void main(String[] args) {
Array<Integer> arr = new Array();
for(int i=0;i<10;i++){
arr.addLast(i);
}
System.out.println(arr);
arr.add(1,100);
System.out.println(arr);
arr.addFirst(-1);
System.out.println(arr);
//[-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
arr.remove(2);
System.out.println(arr);
arr.removeElement(4);
System.out.println(arr);
arr.removeFirst();
System.out.println(arr);
for(int i = 0 ; i < 5 ; i ++){
arr.removeFirst();
}
System.out.println(arr);
}
}
测试结果:
Array: size = 10 , capacity = 10
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array: size = 11 , capacity = 20
[0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array: size = 12 , capacity = 20
[-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array: size = 11 , capacity = 20
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array: size = 10 , capacity = 20
[-1, 0, 1, 2, 3, 5, 6, 7, 8, 9]
Array: size = 9 , capacity = 20
[0, 1, 2, 3, 5, 6, 7, 8, 9]
Array: size = 4 , capacity = 10
[6, 7, 8, 9]
总结: