仔细分析我们会发现,每次新来的零件放在最上面,每次拿走检验的也是最上面的零件,但是由于检验速度慢一些,所以会造成零件逐渐积压。在这个过程中,每次检验的都是最新传送来的零件。这个例子表现出来的数据结构就是栈。栈是一种后进先出(LIFO——last in first out)的线性表,其特点是只允许在线性表的一端(称为栈顶)插入元素(称为入栈)和删除元素(称为出栈)。
二、栈的实现
可以使用“数组+函数”来模拟栈和栈的一些操作:入栈、出栈、取栈顶元素、判断栈是否为空等:
#include<iostream>
using namespace std;
const int MAX = 10000;
int stack[MAX];
int top = -1; //栈顶“指针”,也就是栈顶对应数组的下标
void push(int n){ //入栈(没有考虑数组已经被存满时不能入栈的情况)
stack[++top] = n;
}
void pop(){ //出栈(没有考虑栈为空时不能出栈的情况)
top--;
}
int getop(){ //取栈顶元素(没有考虑栈为空时不能取栈顶元素的情况)
return stack[top];
}
bool empty(){ //判断栈是否为空
return top==-1;
}
void print(){ //依次输出从栈底到栈顶的元素(测试需要)
for(int i=0;i<=top;i++) cout<<stack[i]<<" ";
cout<<endl;
}
int main()
{
for(int i=1;i<=5;i++) push(i);
print();
cout<<getop()<<endl;
pop();
print();
push(6);push(7);
print();
while(!empty()){ //全部出栈
cout<<getop()<<endl;
pop();
}
return 0;
}
前面的例子体现出来的数据结构就是队列(queue)。队列是一种只允许在一端进行删除操作,在另一端进行插入操作的线性表。允许插入的一端称作队尾 (rear),允许删除的的一端称为队头 (front,或者称为队首) 。队列的数据元素又叫做队列元素。在队尾插入一个队列元素称为入队,从队头删除一个队列元素称为出队 。可知队列是一种典型的先进先出 (FIFO——first in first out) 结构。
#include<iostream>
using namespace std;
const int MAX = 110;
int queue[MAX];
int front = 0; //队首“指针”,也就是队首对应数组的下标
int rear = 0; //队尾“指针”,其实是下一个入队元素存放位置
int flag = 0; //标记最近的操作是入队还是出队
bool empty(){ //判断空队列
return flag==0 && front==rear;
}
void push(int n){ //入队
flag = 1;
queue[rear] = n;
rear = (rear+1)%MAX;
}
int pop(){ //出队(返回了出队元素)
flag = 0;
int t = queue[front];
front = (front+1)%MAX;
return t;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) push(i);
while(!empty()){
//队列里前m-1人依次出队并再次入队
for(int i=1;i<m;i++) push(pop());
//第m个人出队
cout<<pop()<<" ";
}
return 0;
}
#include<iostream>
using namespace std;
const int N = 5;
int Next[N+1] = {0,4,1,5,0,2};
int head = 3;
int main()
{
for(int i=head;i!=0;i=Next[i]){
cout<<i<<" ";
}
return 0;
}
可以使用node *p = new node(n);这样“new +结构体构造函数”的方式生成一个指向结构体的指针,那么生成上述链表的代码如下:
#include<iostream>
using namespace std;
//借助结构体定义链表的结点
struct node{
int key;
node *next; //结点的next指针,指向下一个node接点
node(){} //无参构造函数
node(int key){ //有参构造函数
this->key = key;
this->next = NULL; //NULL是空指针
}
};
node *head; //链表的head指针,指向链表的首结点
int main()
{
node *p,*q;
head = p = new node(3);
q = p;
p = new node(5);
q->next = p;
q = p;
p = new node(2);
q->next = p;
q = p;
p = new node(1);
q->next = p;
q = p;
p = new node(4);
q->next = p;
q = p;
//遍历链表的所有结点
p = head;
while(p!=NULL){ //条件p!=NULL可以简写成p(p不为NULL则条件成立)
cout<<p->key<<" ";
p = p->next;
}
return 0;
}
当然可以将结点的key存储在数组中,使用循环生成链表:
//正向建立链表
const int N = 5;
int a[N] = {3,5,2,1,4};
node *p,*q;
head = q = new node(a[0]);
for(int i=1;i<N;i++){
p = new node(a[i]);
q->next = p;
q = p;
}
//反向建立链表
const int N = 5;
int a[N] = {3,5,2,1,4};
node *p,*q;
q = new node(a[N-1]);
for(int i=N-2;i>=0;i--){
p = new node(a[i]);
p->next = q;
q = p;
}
head = p; //head = q;亦可