学过线性表以后,用过的处理一般是头插 、尾插、局部插入以及删除。那么如何将线性表改造成一个可以按照一定顺序插入、按照一定顺序删除的数据结构呢?有了这种按照顺序插入和删除我们可以应用于哪些实例呢?
线性表的插入与删除可以在头部、尾部以及线性表中间的某个结点。
那么我们规定仅仅在一端进行插入与删除操作的数据结构我们定义为栈
。
规定在一端进行插入,另外一端进行删除的数据结构我们定义为队列
。
由此我们在线性表的基础之上重新定义了两种数据结构。
由于线性表分为顺序表
和链表
,由此栈也分为顺序栈
和链栈
,队列也分为顺序队
与链队
。
入栈
和出栈
。先进后出
。入队
和出队
。先进先出
。可以利用栈的先进后出的特性来解决某些问题。
可以利用队列的先进先出的特性来解决某些问题。
暂时就了解这么多,等以后有接触在补充。
顺序栈的初始化
int maxSize;
int[] data;
int top;
随后在main函数赋值即可完成初始化。
进栈操作
//元素进栈
public void push(int x){
if(top==maxSize-1){
return;
}
else{
data[++top]=x;//先移指针后进栈。
}
出栈操作
//元素出栈
public void pop(){
if(top==-1)
return;
else{
int x;
x=data[top--];//先出栈再移动指针
System.out.println(x);
}
顺序表的进栈和出栈操作比较简单些,一般能用顺序栈的尽量用顺序栈。顺序栈其实就是对数组处理,只是有一个top
时刻定位着数组最后一个元素的下标。
带头结点
).//链表结点的定义
public class Lnode{
int data;
Lnode next;
}
private Lnode head=new Lnode();
//初始化
public void init(){
head.next=null;
}
public void push(int x){
Lnode p=new Lnode();
p.data=x;
p.next=head.next;
head.next=p;
}
//链栈无需考虑是否栈满
public void pop(){
if(head.next==null)
return;
else{
Lnode p=new Lnode();
p=head.next;
int x=p.data;
System.out.println("出链栈的是:"+x);
head.next=p.next;
p=null;
}
private int maxSize;
private int[] data;
private int front;
private int rear;
public void init(int maxSize,int front,int rear){
this.maxSize=maxSize;
this.front=front;
this.rear=rear;
this.data=new int[maxSize];
}
//入队操作
public void enQueue(int x){
if(rear==maxSize-1)
return;
else
data[rear++]=x;//先添加元素,再移动指针
}
//出队操作
public void deQueue(){
if(rear==front)
return;
else{
int x=data[front++];//先取元素,在移动指针
System.out.println("出队的是:"+x);
}
}
顺序队的入队和出队中的指针的位置略有不同。严蔚敏版的原话是:在非空队列中,队首指针(front)指向队列的头元素,而尾指针(rear)指向队列的尾元素的下一个位置。
而天勤高分笔记是和其相反的:队尾指针(rear)指向刚进队的元素的位置,队首指针(front)指向刚出队元素的位置
。而我在上面写的跟这两种均不一样,我的是:队首指针(front)指向队列的头元素,队尾指针(rear)指向队列的尾元素。
我写的这个不能适用于循环队列中。
public class Lnode{
int data;
Lnode next;
Lnode front;
Lnode rear;
}
private Lnode lqu=new Lnode() ;
//初始化为空
public void init(){
lqu.front=lqu.rear=null;
}
//入队操作
public void enQueue(int x){
Lnode p=new Lnode();
p.data=x;
p.next=null;
if(lqu.front==null)//若对队列为空则,rear和front同时指向新结点
lqu.front=lqu.rear=p;
else{
lqu.rear.next=p;
lqu.rear=p;
}
}
//出队操作
public void deQueue(){
Lnode p=new Lnode();
if(lqu.rear==null)
return;
p=lqu.front;
int x=p.data;
if(lqu.front==lqu.rear)//需要判断是不是最后一个结点(队列不需要带头结点),
lqu.front=lqu.rear=null;
else
lqu.front=p.next;
System.out.println("出队的元素是:"+x);
p=null;
链队的操作比较麻烦些,但是比较灵活。在front和rear的指针参与下不需要设置头结点
了。也就是说队列没有头结点
。但是需考虑这俩个指针,比如入队为空,两个指针同时指向新结点。仅剩一个结点时出队,则两个指针同时为空。