深感学习一个知识点,不能囫囵吞枣。
首先得对一个概念有正确(开始不一定正确,但至少得头脑清晰)的认知,再尝试按照自己的理解去练习写代码,这样才能真的学到东西。
队列是一种特殊的线性表,特殊之处在于限制了存取点,意思就是插入操作在队头进行,删除操作在队尾进行,分别称之为入队、出队。
由于插入和删除操作分别在队尾和队头进行,最先入队的元素总是最先出队,因此队列也称为先进先出(First In First Out)表。
以下是从顺序队列到顺序循环队列的代码展示:
/**
* 顺序队列
* 当队列为空时,设置队头、队尾下标为0
* @author Administrator
*
*/
public class SeqQueue1 {
private Object value[];
private int front,rear,size;
public SeqQueue1(int capacity){
this.value=new Object[Math.abs(capacity)];
this.front=this.rear=0;
}
public SeqQueue1(){
this(1);
}
//判断是否队空,若空返回true
public boolean isEmpty(){
return this.size==0;
}
//判段队列是否已满,若满返回true
public boolean isFull(){
return this.size==this.value.length;
}
//在队尾添加元素
public void enQueue(Object obj){
if(isFull()){
Object temp[]=new Object[this.value.length+1];
for(int i=0;i<this.value.length;i++){
temp[i]=this.value[i];
}
this.value=temp;
temp=null;
}
this.rear=(this.front+this.size)%this.value.length;
// this.rear++;
this.value[rear]=obj;
this.size++;
}
//队头元素出列
public Object deQueue(){
if(isEmpty())
throw new RuntimeException("队列为空!");
Object obj=this.value[this.front];
this.front=(this.front+1)%this.value.length;
// this.front++;
this.size--;
return obj;
}
//返回队列中元素个数
public int size(){
return this.size;
}
}
/**
* 测试类
* @author Administrator
*
*/
public class StuTest1 {
private String name;
private int score;
public String getName() {
return name;
}
public int getScore() {
return score;
}
public StuTest1(String name,int score){
this.name=name;
this.score=score;
}
public static void main(String[] args) {
SeqQueue1 seq1=new SeqQueue1();
StuTest1 st1=new StuTest1("张三",4);
StuTest1 st2=new StuTest1("李四",5);
StuTest1 st3=new StuTest1("王五",6);
StuTest1 st4=new StuTest1("赵六",7);
seq1.enQueue(st1);
seq1.enQueue(st2);
seq1.enQueue(st3);
seq1.enQueue(st4);
System.out.println(seq1.size());
//循环里不能直接用i<seq.size(),因为每出来一个元素,seq.size()值减1
int num=seq1.size();
for(int i=0;i<num;i++){
StuTest1 st=(StuTest1)seq1.deQueue();
System.out.println("姓名为:"+st.getName()+",学分为:"+st.getScore());
}
}
}
顺序队列缺点分析:
(1)存在数组下标假溢出,就是队列可能没满,但是却不能再往里面添加元素
(2)一次入队/出队操作可能需要同时改变两个下标
为了克服以上不足,可以将顺序队列构造成一个逻辑上首尾相连的循环队列。
/**
* 顺序循环队列
* @author Administrator
*
*/
public class SeqQueue2 {
private Object value[];
private int size,front,rear;
//构造指定容量的空队列
public SeqQueue2(int capacity){
this.value=new Object[Math.abs(capacity)];
this.front=this.rear=0;
}
//构造默认容量的空队列
public SeqQueue2(){
this(1);
}
//判断队列是否为空,若空返回true
public boolean isEmpty(){
return this.front==this.rear;
}
//在队尾添加元素
public boolean enQueue(Object obj){
if(this.front==(this.rear+1)%this.value.length){
Object temp[]=this.value;
this.value=new Object[temp.length+1];
int i=this.front,j=0;
while(i!=this.rear){
this.value[j]=temp[j];
i=(i+1)%temp.length;
j++;
}
this.front=0;
this.rear=j;
}
this.value[this.rear]=obj;
this.rear=(this.rear+1)%this.value.length;
this.size++;
return true;
}
//队头元素出队
public Object deQueue(){
if(isEmpty())
throw new RuntimeException("队列已空!");
else{
Object obj=this.value[this.front];
this.front=(this.front+1)%this.value.length;
this.size--;
return obj;
}
}
//返回队中元素个数
public int size(){
return this.size;
}
}
/**
* 测试类
* @author Administrator
*
*/
public class StuTest2 {
private String name;
private int score;
public String getName() {
return name;
}
public int getScore() {
return score;
}
public StuTest2(String name,int score){
this.name=name;
this.score=score;
}
public static void main(String[] args) {
SeqQueue2 seq2=new SeqQueue2();
StuTest2 st1=new StuTest2("张三",4);
StuTest2 st2=new StuTest2("李四",5);
StuTest2 st3=new StuTest2("王五",6);
StuTest2 st4=new StuTest2("赵六",7);
seq2.enQueue(st1);
seq2.enQueue(st2);
seq2.enQueue(st3);
seq2.enQueue(st4);
//循环里不能直接用i<seq.size(),因为每出来一个元素,seq.size()值减1
int num=seq2.size();
for(int i=0;i<num;i++){
StuTest2 st=(StuTest2)seq2.deQueue();
System.out.println("姓名为:"+st.getName()+",学分为:"+st.getScore());
}
}
}