以下是数据结构中关于链队的定义、初始化、判断空队、入队、出队、遍历等基础操作。
定义
typedef struct QNode{
char data;
QNode *next;
}Qnode,*QP;
typedef struct LinkQueue{
QP front;
QP rear;
}Lqueue;
说明: 链队里有两个指针:头指针和尾指针。指针的类型是QNode。 QNode里有两个属性:data和next指针。
初始化
void initial(LinkQueue &lq){
lq.front = lq.rear = new QNode;
lq.front->next = NULL;
}
步骤:
- 开始链表的头尾指针都指向一个新的节点(该节点无data,只作为链表的头结点使用);
- 头指针/尾指针的next设空NULL(因为头指针和尾指针都指向同一个头结点,lq.front->next = NULL等价于lq.rear->next = NULL)。
画出来是这样的:
判断空队
int isNotEmpty(LinkQueue &lq){
if(lq.front!=lq.rear){
return 1;
}
return 0;
}
如果头尾指针都指向同一个节点(头结点),说明链队为空。
入队
void enQueue(LinkQueue &lq,char e){
QP p = new QNode;
p->data = e;
lq.rear->next = p;
p->next = NULL;
lq.rear = p;
}
void addElem(LinkQueue &lq){
char elem='\n';
while(elem!='*'){
cout<<"请输入新节点(输入*退出):";
cin>>elem;
if(elem!='*'){
enQueue(lq,elem);
}
}
showLQ(lq);
}
步骤:
- 声明一个新节点p;
- 链队尾指针rear的next指向p(rear为旧的队尾);
- p的next设空NULL;
- 尾指针rear设为p(p成为新的rear,即新队尾)。
其中步骤2、3次序可调换。
出队
char deQueue(LinkQueue &lq){
char c;
QP p = lq.front->next;
c = p->data;
lq.front->next = p->next;
if(p == lq.rear){
lq.rear = lq.front;
}
delete p;
return c;
}
void delElem(LinkQueue &lq){
if(isNotEmpty(lq)){
cout<<"出队元素为:"<<deQueue(lq)<<endl;
}
showLQ(lq);
}
步骤
- 判断是否为空队;
- 声明一个中间节点p(用来释放出队节点);
- 将p设为队列第一个节点(即头节点的next节点);
- 将p的值提取出来(即出队节点的值);
- 头结点的next设为p的next节点(即头结点的next设为头结点的next节点的next节点,这样就跳过出队的节点了);
- 释放节点p。
- 特别处理:如果尾节点rear指向的节点就是头结点的next,说明链队只剩下最后一个节点了(不算头结点),出队后尾节点rear和头指针front一样指向头结点(就像初始化那样)。
遍历队列
void showLQ(LinkQueue lq){
QP p = lq.front->next;
cout<<"当前链队数据:";
if(!isNotEmpty(lq)){
cout<<"空队!\n";
delete p;
return ;
}
while(p!=NULL){
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
delete p;
}
步骤:
- 判断队列是否为空;
- 设置节点p用作遍历指针;
- p从第一个节点开始向最后一个节点(即到rear指向的节点)遍历,到NULL就停止遍历即可。
运行截图
源码
#include<iostream>
#include<stdio.h>
using namespace std;
typedef struct QNode{
char data;
QNode *next;
}Qnode,*QP;
typedef struct LinkQueue{
QP front;
QP rear;
}Lqueue;
void initial(LinkQueue &lq){
lq.front = lq.rear = new QNode;
lq.rear->next = NULL;
}
int isNotEmpty(LinkQueue &lq){
if(lq.front!=lq.rear){
return 1;
}
return 0;
}
void showLQ(LinkQueue lq){
QP p = lq.front->next;
cout<<"当前链队数据:";
if(!isNotEmpty(lq)){
cout<<"空队!\n";
delete p;
return ;
}
while(p!=NULL){
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
delete p;
}
void enQueue(LinkQueue &lq,char e){
QP p = new QNode;
p->data = e;
lq.rear->next = p;
p->next = NULL;
lq.rear = p;
}
void addElem(LinkQueue &lq){
char elem='\n';
while(elem!='*'){
cout<<"请输入新节点(输入*退出):";
cin>>elem;
if(elem!='*'){
enQueue(lq,elem);
}
}
showLQ(lq);
}
char deQueue(LinkQueue &lq){
char c;
QP p = lq.front->next;
c = p->data;
lq.front->next = p->next;
if(p == lq.rear){
lq.rear = lq.front;
}
delete p;
return c;
}
void delElem(LinkQueue &lq){
if(isNotEmpty(lq)){
cout<<"出队元素为:"<<deQueue(lq)<<endl;
}
showLQ(lq);
}
void menu(LinkQueue &lq){
int c = 0;
while(1){
cout<<"请选择操作:"<<endl;
cout<<"1:入队"<<endl;
cout<<"2:出队"<<endl;
cout<<"3:遍历队"<<endl;
cout<<"4:退出"<<endl;
cin>>c;
switch(c){
case 1:addElem(lq);break;
case 2:delElem(lq);break;
case 3:showLQ(lq);break;
case 4:return;
default:;
}
}
}
int main(){
LinkQueue lq;
initial(lq);
menu(lq);
return 0;
}
|