用顺序存储方式实现循环队列的 6 种情况(可运行)
王道书提到的 线性队列 实现的 6 种情况,其对应代码实现如下。
为增加可读性使用 ANSI 代码设置输出文本颜色,Windows 系统建议使用 powershell
运行。
// test.cpp
// 编译运行命令 g++ test.cpp -otest ; ./test
#include <iostream>
using namespace std;
#define MaxSize 10
#define ElemType int
// 队尾指针Q.rear的位置:
// (a)指向表尾的后一位 (b)指向表尾
// 判断队满队空的三种方法:
// 1. 牺牲存储单元 2.引入size变量 3.引入tag变量(true表示入队,false表示出队)
// 注意:C++取模运算所得结果的符号与被除数相同。
//a1
struct a1 { ElemType data[MaxSize]; int front, rear; };
void InitQueue(a1 &Q) { Q.front = Q.rear = 0; }
bool EnQueue(a1 &Q, ElemType x) { if ((Q.rear + 1) % MaxSize == Q.front) return false; Q.data[Q.rear] = x; Q.rear = (Q.rear + 1) % MaxSize; return true; }
bool DeQueue(a1 &Q, ElemType &x) { if (Q.front == Q.rear) return false; x = Q.data[Q.front]; Q.front = (Q.front + 1) % MaxSize; return true; }
//a2
struct a2 { ElemType data[MaxSize]; int front, rear, size; };
void InitQueue(a2 &Q) { Q.front = Q.rear = Q.size = 0; }
bool EnQueue(a2 &Q, ElemType x) { if (Q.size == MaxSize) return false; Q.data[Q.rear] = x; Q.rear = (Q.rear + 1) % MaxSize; Q.size++; return true; }
bool DeQueue(a2 &Q, ElemType &x) { if (Q.size == 0) return false; x = Q.data[Q.front]; Q.front = (Q.front + 1) % MaxSize; Q.size--; return true; }
//a3
struct a3 { ElemType data[MaxSize]; int front, rear; bool tag; };
void InitQueue(a3 &Q) { Q.front = Q.rear = 0; Q.tag = false; }
bool EnQueue(a3 &Q, ElemType x) { if (Q.front == Q.rear && Q.tag) return false; Q.data[Q.rear] = x; Q.rear = (Q.rear + 1) % MaxSize; Q.tag = true; return true; }
bool DeQueue(a3 &Q, ElemType &x) { if (Q.front == Q.rear && !Q.tag) return false; x = Q.data[Q.front]; Q.front = (Q.front + 1) % MaxSize; Q.tag = false; return true; }
//b1
struct b1 { ElemType data[MaxSize]; int front, rear; };
void InitQueue(b1 &Q) { Q.front = 0; Q.rear = MaxSize - 1; }
bool EnQueue(b1 &Q, ElemType x) { if ((Q.rear + 2) % MaxSize == Q.front) return false; Q.rear = (Q.rear + 1) % MaxSize; Q.data[Q.rear] = x; return true;}
bool DeQueue(b1 &Q, ElemType &x) { if ((Q.rear + 1) % MaxSize == Q.front) return false; x = Q.data[Q.front]; Q.front = (Q.front + 1) % MaxSize; return true;}
//b2
struct b2 { ElemType data[MaxSize]; int front, rear, size; };
void InitQueue(b2 &Q) { Q.front = Q.size = 0; Q.rear = MaxSize - 1; }
bool EnQueue(b2 &Q, ElemType x) { if (Q.size == MaxSize) return false; Q.rear = (Q.rear + 1) % MaxSize; Q.data[Q.rear] = x; Q.size++; return true; }
bool DeQueue(b2 &Q, ElemType &x) { if (Q.size == 0) return false; x = Q.data[Q.front]; Q.front = (Q.front + 1) % MaxSize; Q.size--; return true; }
//b3
struct b3 { ElemType data[MaxSize]; int front, rear; bool tag; };
void InitQueue(b3 &Q) { Q.front = 0; Q.rear = -1; Q.tag = false; }
bool EnQueue(b3 &Q, ElemType x) { if ((Q.rear + 1) % MaxSize == Q.front && Q.tag) return false; Q.rear = (Q.rear + 1) % MaxSize; Q.data[Q.rear] = x; Q.tag = true; return true; }
bool DeQueue(b3 &Q, ElemType &x) { if ((Q.rear + 1) % MaxSize == Q.front && !Q.tag) return false; x = Q.data[Q.front]; Q.front = (Q.front + 1) % MaxSize; Q.tag = false; return true; }
void PrintQueue(a1 &Q) { cout << "- a1 "; for (int i = 0; i < (Q.rear - Q.front + MaxSize) % MaxSize; i++) printf("\e[33m%d\e[0m|", Q.data[(Q.front + i) % MaxSize]); cout << endl; }
void PrintQueue(a2 &Q) { cout << "- a2 "; for (int i = 0; i < Q.size; i++) printf("\e[33m%d\e[0m|", Q.data[(Q.front + i) % MaxSize]); cout << endl; }
void PrintQueue(a3 &Q) { cout << "- a3 "; int size = ((Q.rear == Q.front) && Q.tag) ? MaxSize : (Q.rear - Q.front + MaxSize) % MaxSize; for (int i = 0; i < size; i++) printf("\e[33m%d\e[0m|", Q.data[(Q.front + i) % MaxSize]); cout << endl; }
void PrintQueue(b1 &Q) { cout << "- b1 "; for (int i = 0; i < (Q.rear - Q.front + 1 + MaxSize) % MaxSize; i++) printf("\e[33m%d\e[0m|", Q.data[(Q.front + i) % MaxSize]); cout << endl; }
void PrintQueue(b2 &Q) { cout << "- b2 "; for (int i = 0; i < Q.size; i++) printf("\e[33m%d\e[0m|", Q.data[(Q.front + i) % MaxSize]); cout << endl; }
void PrintQueue(b3 &Q) { cout << "- b3 "; int size = ((Q.rear - Q.front + 1) % MaxSize == 0 && Q.tag) ? MaxSize : (Q.rear - Q.front + 1 + MaxSize) % MaxSize; for (int i = 0; i < size; i++) printf("\e[33m%d\e[0m|", Q.data[(Q.front + i) % MaxSize]); cout << endl; }
void Do (bool fun, const char* msg) { if (!fun) printf("\e[1;3;31m[%s]失败\e[0m "); }
void testQueue() {
printf("执行\e[32m线性队列\e[0m测试\n");
a1 a1; a2 a2; a3 a3; b1 b1; b2 b2; b3 b3;
InitQueue(a1); InitQueue(a2); InitQueue(a3); InitQueue(b1); InitQueue(b2); InitQueue(b3);
///
// 此处修改测试代码
// 把队列一次性填满
for (int i = 0; i < MaxSize; i++) { Do(EnQueue(a1, i + 1), "a1入队"); Do(EnQueue(a2, i + 1), "a2入队"); Do(EnQueue(a3, i + 1), "a3入队"); Do(EnQueue(b1, i + 1), "b1入队"); Do(EnQueue(b2, i + 1), "b2入队"); Do(EnQueue(b3, i + 1), "b3入队"); } cout << endl;
PrintQueue(a1); PrintQueue(a2); PrintQueue(a3); PrintQueue(b1); PrintQueue(b2); PrintQueue(b3);
printf("a1和b1各少了一个元素,恰好是通过\e[33m牺牲一个元素位置\e[0m来判断队空队满的体现。\n");
printf("\n\e[32m各出队 5 次\e[0m");
ElemType res = 0;
for (int i = 0; i < 5; i++) { Do(DeQueue(a1, res), "a1出队"); Do(DeQueue(a2, res), "a2出队"); Do(DeQueue(a3, res), "a3出队"); Do(DeQueue(b1, res), "b1出队"); Do(DeQueue(b2, res), "b2出队"); Do(DeQueue(b3, res), "b3出队"); } cout << endl;
PrintQueue(a1); PrintQueue(a2); PrintQueue(a3); PrintQueue(b1); PrintQueue(b2); PrintQueue(b3);
printf("\n\e[32m各入队 3 次\e[0m");
for (int i = 0; i < 3; i++) { Do(EnQueue(a1, i + 1), "a1入队"); Do(EnQueue(a2, i + 1), "a2入队"); Do(EnQueue(a3, i + 1), "a3入队"); Do(EnQueue(b1, i + 1), "b1入队"); Do(EnQueue(b2, i + 1), "b2入队"); Do(EnQueue(b3, i + 1), "b3入队"); } cout << endl;
PrintQueue(a1); PrintQueue(a2); PrintQueue(a3); PrintQueue(b1); PrintQueue(b2); PrintQueue(b3);
///
}
int main(int argc, char const *argv[])
{
testQueue();
cout << endl;
return 0;
}
@echo off
chcp 65001 > nul
@REM 文件名run.bat,运行程序的简易批处理脚本
(g++ test.cpp -otest ) && (
echo 编译完成 正在执行
echo +++++++++++++++++++++
(test) && (
echo.
echo +++++++++++++++++++++
echo 执行完成
) ||(
echo.
echo ---------------------
echo 程序执行出错)
) || (echo 编译出错)
@REM pause