1.常用数据结构
数据结构指数据的存储、组织方式。
栈
顶部元素插入和取出快。
除顶部元素外,存储其他元素都很慢。
队列
顶部元素插入和尾部元素取出快。
存储其他元素很慢。
链表
插入和删除都快。
查找慢。
二叉树
插入、删除、查找都快。
删除算法复杂
红黑树
插入、删除、查找都快。
算法复杂
散列表
插入、删除、查找都快。
数据散列,对存储空间有浪费
位图
节省存储空间
不方便描述复杂的数据关系
2.栈
栈(Stack)又名堆栈,是允许在同一端进行插入和删除操作的特殊线性表。其中,允许进行插入和删除操作的一端叫作栈顶(Top),另一端叫作栈底(Bottom),栈底固定,栈顶浮动。栈中的元素个数为零时,该栈叫作空栈。插入一般叫作进栈(Push),删除叫作退栈(Pop)。栈也叫作后进先出(FILO-First In Last Out)的线性表。
要实现一个栈,需要先实现以下核心方法。
- push():向栈中压入一个数据,先入栈的数据在最下边。
- pop():弹出栈顶数据,即移除栈顶数据。
- peek():返回当前的栈顶数据。
3.栈的实现
(1)定义栈的数据结构:
public class Statck<E>{
private Object[] data=null;
private int maxSize=0;//栈的容量
priavte int top=-1;//栈顶的指针
//构造函数,根据指定的size初始化栈
Statck(){
this(10);//默认的栈大小为10
}
Statck(int initialSize){
if(initialSize>=0){
this.maxSize=initialSize;
data=new Object[initialSize];
top=-1;
}else{
throw new RuntimeException("初始化大小不能小于0:"+initialSize);
}
}
}
以上代码定义了一个Stack的类,用来存储栈的数据结构;定义了一个数组data,用来存储栈中的数据;定义了maxSize,表示栈的最大容量;定义了top,表示栈顶数据的指针;
(2)数据入栈,向栈顶压入一个数据:
//进栈,第一个元素top=0;
public boolean push(E e){
if(top==maxSize-1){
throw new RuntimeException("栈已满,无法将元素入栈");
}else{
data[++top]=e;
return true;
}
}
以上代码定义了方法push()来向栈中压入数据,在数据入栈前首先判断栈是否满了,具体的判断依据为栈顶元素的指针位置等于栈的最大容量。注意,这里使用maxSize -1是因为栈顶元素的指针是从0开始计算的。在栈有可用空间时,使用data[++top]=e在栈顶(top位置)上方新压入一个元素并为top加1。
(3)数据出栈,从栈顶移除一个数据:
//弹出栈顶的元素
public E pop(){
if(top==-1){
throw new RuntimeException("栈为空");
}else{
return (E)data[top--];
}
}
以上代码定义了方法pop()来从栈顶移除一个数据,移除前先判断栈顶是否有数据,如果有,则通过data[top--]将栈顶数据移出并给top减1。
(4)数据查询:
//查看栈顶元素但不溢出
public E peek(){
if(top==-1){
throw new RuntimeException("栈为空");
}else{
return (E)data[top];
}
}
以上代码定义了方法peek()来取出栈顶的数据,在取出栈顶的数据前先判断栈顶的元素是否存在,如果存在,则直接返回栈顶元素(注意:这里没有对栈顶的元素进行删除),否则抛出异常。
4.队列
队列是一种只允许在表的前端进行删除操作且在表的后端进行插入操作的线性表。其中,执行插入操作的端叫作队尾,执行删除操作的端叫作队头。没有元素的队列叫作空队列,在队列中插入一个队列元素叫作入队,从队列中删除一个队列元素叫作出队。因为队列只允许在队头插入,在队尾删除,所以最早进入队列的元素将最先从队列中删除,所以队列又叫作先进先出(FIFO-first in first out)线性表。
要实现一个队列,需要先实现以下核心方法。
- add():向队列的尾部加入一个元素(入队),先入队列的元素在最前边。
- poll():删除队列头部的元素(出队)。
- peek():取出队列头部的元素。
5.队列的实现
(1)定义队列的数据结构:
public class Queue<E>{
private Object[] data=null;
private int maxSize=0;//队列的容量
priavte int front;//队列头,允许删除
priavte int rear;//队列尾,允许插入
//构造函数,根据指定的size初始化栈
public Queue(){
this(10);//默认的队列大小为10
}
public Queue(int initialSize){
if(initialSize>=0){
this.maxSize=initialSize;
data=new Object[initialSize];
front=rear=0;
}else{
throw new RuntimeException("初始化大小不能小于0:"+initialSize);
}
}
}
以上代码定义了一个名为Queue的队列数据结构,并定义了用于存储队列数据的data数组、队列头位置标记front、队列尾位置标记rear、队列的容量maxSize。队列的默认长度为 10,在初始化时,front的位置等于rear的位置,都为 0;在有新的数据加入队列时,front的值加1。
(2)向队列插入数据:
//在队列的尾部插入数据
public boolean add(E e){
if(rear==maxSize){
throw new RuntimeException("栈已满,无法插入新的元素");
}else{
data[rear++]=e;
return true;
}
}
以上代码定义了方法add()来向队列中插入数据,在插入前先判断队列是否满了,如果队列有空间,则通过data[rear++]=e向队列的尾部加入数据并将队尾的指针位置加1。
(3)取走队列中的数据:
//删除队列头部的元素,出队
public E poll(){
if(empty()){
throw new RuntimeException("空队列异常");
}else{
E value=(E)data[front];//临时保存队列front端的元素的值
data[front++]=null;//释放队列front端的元素
return value;
}
}
以上代码定义了方法poll()来取出队列头部的数据,并将队列头部的数据设置为null以释放队列头部的位置,最后返回队列头部的数据。
(4)队列数据查询: