1.顺序队列(环状)
/*1.5 顺序队列
bool EnQueue(const T item) //1.5-a. 入队操作,判断队列是否为满
bool DeQueue(T& item) //1.5-b. 返回队头元素,并删除该元素,判断队列是否为空
bool GetFront(T& item) //1.5-c. 返回队头元素,但不删除,判断队列是否为空】
*/
#include <iostream>
using namespace std;
template <class T>
class ArrayQueue {
private:
int maxSize; //队列最大容量
int front;
int rear;
int* queue;
public:
ArrayQueue(int size)
{
maxSize = size + 1;
queue = new T[maxSize];
front = rear = 0;
}
~ArrayQueue()
{
delete[] queue;
}
void Clear()
{
front = rear;
}
/*
TODO:1.5-a.入队操作,判断队列是否为满,如果队列已满,则输出打印cout << "队列已满,溢出" << endl;,返回false。
否则,将值item进行入队操作。并返回true
返回值说明:入队成功,返回true,否则返回false
*/
bool EnQueue(const T item)
{
if(this->IsFull()){
return false;
}
queue[rear] = item;
rear = (rear + 1) % maxSize;
return true;
}
/*
TODO:1.5-b.返回队头元素,并删除该元素,判断队列是否为空
如果队列为空,则输出打印cout << "队列为空" << endl;并返回false。
否则将队列头元素取出并赋值给item变量并删除该元素,返回true
返回值说明:成功获取队头元素返回true,否则返回false
*/
bool DeQueue(T& item)
{
if(this->IsEmpty()){
return false;
}
item = queue[front];
front = (front + 1) % maxSize;
return true;
}
/*
TODO:1.5-c. 返回队头元素,但不删除,判断队列是否为空
如果队列为空,则打印cout << "队列为空" << endl;并返回false。
否则取出队头元素赋值给item,返回true。
返回值说明:成功获取队头元素,返回true,否则返回false
*/
bool GetFront(T& item)
{
if(this->IsEmpty()){
return false;
}
item = queue[front];
return true;
}
bool IsEmpty()
{
if (front == rear) {
cout << "队列为空" << endl;
return true;
} else {
return false;
}
}
bool IsFull()
{
if ((rear + 1) % maxSize == front) {
cout << "队列已满,溢出" << endl;
return true;
} else {
return false;
}
}
};
int main()
{
int maxsize = 0, iNum = 0, temp1 = 0, temp2 = 0, temp3 = 0;
cin >> maxsize >> iNum >> temp1;
ArrayQueue<int> aq(maxsize);
for (int i = 0; i < iNum; i++) {
aq.EnQueue(i * 3);
}
aq.EnQueue(temp1);
aq.DeQueue(temp2);
cout << "出队:" << temp2 << endl;
aq.GetFront(temp3);
cout << "读取队头元素:" << temp3 << endl;
return 0;
}
2.链式队列(结构体链表)
#include <iostream>
using namespace std; // 标准库包含在命名空间std中
// 结点类模板
/*
TODO:定义一个模板结构体,包含:一个模板类型变量data存数据,
一个该结构体指针类型变量next作为后继结点指针,一个无参构造函数,
一个带数据和指针形参的构造函数
*/
template <class ElemType>
struct Node
{
ElemType data;
struct Node<ElemType> *next;
Node()
// 操作结果:构造指针域为空的结点
{
data = NULL;
next = NULL;
}
Node(ElemType item, Node<ElemType> *link)
// 操作结果:构造一个数据域为item和指针域为link的结点
{
data = item;
next = link;
}
};
// 结点类模板的实现部分
/*
TODO:定义无参构造函数
函数功能:初始化结构体成员,next置为空
参数说明:无
返回值说明:无
*/
/*
TODO:定义带参构造函数
函数功能:使用形参初始化结构体成员.
参数说明:item-数据,link-后继指针
返回值说明:无
*/
// 链队列类模板
template<class ElemType>
class LinkQueue
{
protected:
int count;
Node<ElemType> *front;
Node<ElemType> *rear;
/*
TODO:定义protected类型成员:两个模板类Node指针变量front, rear存队首队尾,
int型变量count存元素个数
*/
public:
// 抽象数据类型方法声明及重载编译系统默认方法声明:
LinkQueue(); // 无参数的构造函数模板
virtual ~LinkQueue(); // 析构函数模板
bool Empty() const; // 判断队列是否为空
void Clear(); // 将队列清空
bool OutQueue(ElemType &e); // 出队操作
bool InQueue(const ElemType &e); // 入队操作
};
// 链队列类模板的实现部分
/*
TODO:构造一个空队列
函数功能:初始化类成员,生成头结点,空队列元素个数为0
参数说明:无
返回值说明:无
*/
template<class ElemType>
LinkQueue<ElemType>::LinkQueue()
// 操作结果:构造一个空队列
{
count = 0;
front = rear = NULL;
}
/*
TODO:完成定义析构函数的功能
函数功能:调用函数释放存储空间.
参数说明:无
返回值说明:无
*/
template<class ElemType>
LinkQueue<ElemType>::~LinkQueue()
// 操作结果:销毁队列
{
Clear();
}
/*
TODO:判断队列是否为空
函数功能:判断队列是否为空;如果队列中元素个数为0,则返回true;否则返回false.
参数说明:无
返回值说明:如果队列为空则返回true,否则返回false
*/
template<class ElemType>
bool LinkQueue<ElemType>::Empty() const
// 操作结果:如队列为空,则返回true,否则返回false
{
if (count == 0)
return true;
else return false;
}
/*
TODO:清空队列
函数功能:当队列不空时循环调用函数出队列.
参数说明:无
返回值说明:无
*/
template<class ElemType>
void LinkQueue<ElemType>::Clear()
// 操作结果:清空队列
{
while (front !=NULL)
{
rear = front;
front = front->next;
delete rear;
}
rear = NULL;
count = 0;
}
/*
TODO:完成获取出队列的第一元素功能
函数功能:如果队列空直接返回失败,否则利用临时变量取出队头元素,释放出队的结点,
个数减少1.
参数说明:e-存放出队列的第一个元素的变量
返回值说明:如队列非空,用e返回出队列第一个的元素,返回true,否则返回false
*/
template<class ElemType>
bool LinkQueue<ElemType>::OutQueue(ElemType &e)
// 操作结果:如果队列非空,那么删除队头元素,并用e返回其值,返回true,
// 否则返回false,
{
Node <ElemType> *temp;
if (count == 0)
{
return false;
}
else {
e = front->data;
temp = front;
front = front->next;
delete temp;
if (front == NULL)
{
rear == NULL;
}
count--;
return true;
}
}
/*
TODO:完成将一个元素值插进队列的功能
函数功能:生成新结点,新结点追加在队尾,rear指向新队尾,元素个数自加1.
参数说明:e-存放进队列的元素的变量
返回值说明:返回true
*/
template<class ElemType>
bool LinkQueue<ElemType>::InQueue(const ElemType &e)
// 操作结果:插入元素e为新的队尾,返回true
{
if(rear == NULL){
front = rear = new Node<ElemType> (e,NULL);
}
else{
rear->next = new Node<ElemType> (e,NULL);
rear = rear->next;
}
count ++;
return true;
}
template <class ElemType>
void Show(const ElemType &e)
// 操作结果: 显示数据元素
{
cout << e << " "; // 输出e
}
int main(void)
{
LinkQueue<double> sa;
double x;
for (int i = 0; i < 6; i++) {
cin >> x;
sa.InQueue(x);
/*
TODO:sa调用InQueue传参x进队列
*/
}
cout << "out queue:";
while (sa.OutQueue(x)) {
cout << x << " ";
}
return 0;
}
3.KMP算法
/*1.7-b,c KMP模式匹配算法
//1.7-b. 计算字符串特征向量的算法,返回特征向量的数组。
int* next(string P)
//1.7-c. KMP模式匹配算法,返回子串第一次出现的位置,若不存在,返回-1
int KMPStrMatching(string T, string P, int* N, int startIndex)
*/
#include <assert.h>
#include <iostream>
#include <string.h>
using namespace std;
/*
TODO:计算字符串p的特征向量的算法,返回特征向量的数组。
功能描述:定义int型变量m,初始值为P的长度;
调用函数assert传参 m>0 判断;
定义int型指针变量N,初始化为int型数组,长度为m;
调用函数assert传参 N != 0 判断;
N[0]赋值0;
for循环,循环变量i从1开始到小于m的长度结束,
定义int型变量k,初始值为N[i - 1]
while循环,循环条件:k不等于0 并且 P[i]不等于P[k]
循环体:N[i] 赋值为 k+1
while循环结束后,
如果变量i大于0 并且 P[i]等于P[k] 时,N[i]赋值为k+1,
否则,N[i]赋值为0
for循环结束后,返回N
参数说明:P-要计算特征向量的字符串
返回值说明:指向特征向量的指针
*/
int* next(string P)
{
int m = P.size();
assert (m > 0);
int *N = new int[m];
assert (N!=0);
N[0] = 0;
for (int j = 1;j < m;j ++)
{
int k = N[j-1];
while (k > 0&& P[j] !=P[k])
k = N[k-1];
if (P[j]==P[k])
N[j] = k + 1;
else
N[j] = 0;
}
return N;
}
/*
TODO:KMP模式匹配算法,返回子串第一次出现的位置
功能描述:定义int型变量lastIndex,初始值为T的长度减P的长度;
如果lastIndex减startIndex 小于 0,返回-1;
定义int型变量i;定义int型变量j,初始值为0;
for循环,循环变量i从0开始到小于T的长度结束,
while循环,循环条件:P[j]不等于T[i] 并且 j大于0,
循环体:j赋值为N[j - 1]
while循环结束后,
如果P[j]等于T[i],j累加1;
如果j等于P的长度,返回(i - j + 1);
for循环结束后,返回-1
参数说明:T-原始字符串,P-子串,N-字符串P的特征向量
返回值说明:查找到则返回子串第一次出现的位置;没有查找到,返回-1
*/
int KMPStrMatching(string T, string P, int* N, int startIndex)
{
int lastIndex = T.size()-P.size();
if ((lastIndex - startIndex )< 0)
return (-1);
int i = startIndex;
int j = 0;
while (i < T.size()&&j <P.size()){
if (P[j] == T[i]){
i++;
j++;
}
else if (j!=0)
j = N[j-1];
else
i++;
}
if (j == P.size())
return (i-j);
else
return (-1);
}
int main()
{
string p; //要查找的字符串
string q; //原始字符串
getline(cin, p);
getline(cin, q);
int* N;
N = next(p);
for (int i = 0; i < p.length(); i++)
cout << N[i] << " ";
cout << endl;
cout << KMPStrMatching(q, p, N, 0) << endl;
}