目录
简介
本篇是对常用数据结构的学习,其中的数据结构实现方法为与C十分接近的C++,顺序表的主函数本人以用C重写,其余的部分不在重写,重写方法见:
绪论
数值计算:数学模型->算法
数据结构:
逻辑结构:集合结构,线性结构,树结构,图结构或网结构
存储结构:顺序存储结构,链式存储结构
数据类型:基本数据类型,抽象数据类型
抽象数据类型:
ADT 抽象数据类型名{
数据对象: <数据对象的定义>
数据关系: <数据关系的定义>
基本操作: <基本操作的定义>
}ADT 抽象数据类型名
基本操作名(参数表)
初始条件:<初始条件描述>
操作结果:<操作结果描述>
算法:
特性:有穷性,确定性,可行性,输入,输出
标准:正确性,可读性,健壮性,高效性
时间复杂度:问题规模n,语句频度
空间复杂度
线性表
有次序的有限序列
基本操作:
InitList(&L) //构造一个空的线性表
DestroyList(&L) //销毁线性表
ClearList(&L) //将L重置为空表
ListEmpty(L) //若L为空表,则返回true,否则返回false
ListLength(L) //返回L中元素的个数
GetElem(L,i,&e) //用e返回L中第i个数据元素的值
LocateElem(L,e) //返回L中第1个值与e相同的元素在L中的位置。若这样的元素不存在,返回值为0
PriorElem(L,cur_e,&pre_e) //若cur_e是L的数据元素,且不是第一个,则用pre_e返回其前驱,否则操作失败,pre_e无定义
NextElem(L,cur_e,&next_e) //若cur_e是L的数据元素,且不是最后一个,则用next_e返回其后继,否则操作失败,next_e无定义
ListInsert(&L,i,e) //在L中第i个位置之前插入新的数据元素e,L的长度加1
ListDelete(&L,i) //删除L的第i个数据,L的数据减1
TraverseList(L) //对线性表进行遍历,在遍历的过程中对L的每个结点访问一次
合并两个线性表
void union(List &La,List Lb)
{
La_len=ListLength(La);
Lb_len=ListLength(Lb); //求线性表的长度
for(i=1;i<=Lb_len;i++)
{
GetElem(Lb,i,e); //取Lb中第i个数据元素赋值给e
if(!LocateElem(La,e,euqal())
ListInsert(La,++La_len,e); //La中不存在和e相同的数据元素,则插入之
}
}
提纯一个线性表
void union(List &La,List Lb)
{
InitList(LA);
La_len=ListLength(La);
Lb_len=ListLength(Lb); //求线性表的长度
for(i=1;i<=Lb_len;i++)
{
GetElem(Lb,i,e); //取Lb中第i个数据元素赋值给e
if(ListEmpty(LA)||!equal(en,e))
{
ListInsert(La,++La_len,e); //La中不存在和e相同的数据元素,则插入之
en=e;
} //La中不存在和e相同的元素,则插入之
}
}
合并两个有序线性表
顺序有序表
void MergeList_Sq(SqList LA, SqList LB, Sqlist &LC)
{
LC.length=LA.lenghth+LB.length;
LC.elem=new ElemType[Lc.length]; //为新表分配一个数组空间
pc=LC.elem; //指针pc,pa,pb分别指向表第一个元素
pa=LA.elem;
pb=LB.elem;
pa_last=LA.elem+LA.length-1; //指针pa_lat指向表尾最后一个元素
pb_last=LB.elem+LB.length-1; //指针pb_lat指向表尾最后一个元素
while((pa<pa_last)&&(pb<=pb_last)) //LA和LB均未到达表尾
{
if(*pa<=*pb) //依次取两表中的较小结点插入到LC最后
*pc++=*pa++;
else *pc++=*pb++;
}
while(pa<=pa_last) *pc++=*pa++; //LB到达表尾,依次将LA的剩余元素插入LC的最后
while(pb<=pb_last) *pc++=*pb++; //LA到达表尾,依次将LB的剩余元素插入LC的最后
}
链式有序表
void MergeList_L(LinkList &LA, LinkList &LB, LinkList &LC)
{
pa=LA->next; pb=LB->next; //pa和pb分别指向两个表的第一个结点
LC=LA; //用LA的头结点作为LC的头结点
pc=LC; //pc的初值指向LC的头结点
while(pa&&pb)
{
if(pa->data<=pb->data)
{
pc->next=pa;
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
}
pc->next=pa?pa:pb;
delete LB;
}
顺序表操作:
#include<stdio.h>
#include<stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status; //Status 是函数返回值类型,其值是函数结果状态代码。
typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型
#define MAXSIZE 100 //顺序表可能达到的最大长度
struct Book {
char id[MAXSIZE];//ISBN
char name[MAXSIZE];//书名
double price;//定价
};
typedef struct {
Book* elem; //存储空间的基地址
int length; //当前长度
} SqList;
Status InitList_Sq(SqList& L) { //算法2.1 顺序表的初始化
//构造一个空的顺序表L
L.elem = new Book[MAXSIZE]; //为顺序表分配一个大小为MAXSIZE的数组空间
if (!L.elem)
exit(OVERFLOW); //存储分配失败退出
L.length = 0; //空表长度为0
return OK;
}
Status GetElem(SqList L, int i, Book& e) {//算法2.2 顺序表的取值
if (i < 1 || i > L.length)
return ERROR; //判断i值是否合理,若不合理,返回ERROR
e = L.elem[i - 1]; //elem[i-1]单元存储第i个数据元素
return OK;
}
int LocateElem_Sq(SqList L, double e) { //算法2.3 顺序表的查找
//顺序表的查找
for (int i = 0; i < L.length; i++)
if (L.elem[i].price == e)
return i + 1;//查找成功,返回序号i+1
return 0;//查找失败,返回0
}
Status ListInsert_Sq(SqList& L, int i, Book e) { //算法2.4 顺序表的插入
//在顺序表L中第i个位置之前插入新的元素e
//i值的合法范围是1<=i<=L.length+1
if ((i < 1) || (i > L.length + 1))
return ERROR; //i值不合法
if (L.length == MAXSIZE)
return ERROR; //当前存储空间已满
for (int j = L.length - 1; j >= i - 1; j--)
L.elem[j + 1] = L.elem[j]; //插入位置及之后的元素后移
L.elem[i - 1] = e; //将新元素e放入第i个位置
++L.length; //表长增1
return OK;
}
Status ListDelete_Sq(SqList& L, int i) { //算法2.5 顺序表的删除
//在顺序表L中删除第i个元素,并用e返回其值
//i值的合法范围是1<=i<=L.length
if ((i < 1) || (i > L.length))
return ERROR; //i值不合法
for (int j = i; j <= L.length; j++)
L.elem[j - 1] = L.elem[j]; //被删除元素之后的元素前移
--L.length; //表长减1
return OK;
}
主函数:
int main() {
SqList L;
int i = 0, temp, a, c, choose, p=1;
double price;
Book e;
char head_1[]="", head_2[]="", head_3[]="";
char buf[256], * s;
printf("1. 建立\n");
printf("2. 输入\n");
printf("3. 取值\n");
printf("4. 查找\n");
printf("5. 插入\n");
printf("6. 删除\n");
printf("7. 输出\n");
printf("0. 退出\n\n");
choose = -1;
while (choose != 0) {
printf("请选择:");
scanf ("%d",&choose);
switch (choose) {
case 1://创建顺序表
if (InitList_Sq(L))
printf("成功建立顺序表\n\n");
else
printf("顺序表建立失败\n\n");
break;
case 2: {//顺序表信息输入
i = 0;
//L.elem = new Book[MAXSIZE];
L.elem = (Book*)malloc(MAXSIZE * sizeof(Book));
if (!L.elem)
exit(OVERFLOW);
L.length = 0;
FILE *fp;
fp = fopen("book.txt","r+");
if (fp==NULL) {
printf("错误!未找到文件!\n" );
exit(ERROR);
}
while (!feof(fp))
{
fgets(buf, 256, fp);
//if ('\n' == buf[0]) continue; //空行继续
s = buf;
sscanf(s, "%s%s%lf", &L.elem[i].id, &L.elem[i].name, &L.elem[i].price);
i++;
}
printf("输入 book.txt 信息完毕\n\n");
L.length = i;
fclose(fp);
}
break;
case 3://顺序表的取值
printf("请输入一个位置用来取值:\n");
scanf("%i", &i);
temp = GetElem(L, i, e);
if (temp != 0) {
printf("查找成功\n");
printf("第 %d 本图书的信息是:\n",i);
printf("%-15s %-30s %lf\n", e.id, e.name, e.price);
}
else
printf("查找失败!位置超出范围\n\n");
break;
case 4: //顺序表的查找
printf("请输入所要查找价格:");
scanf("%lf", &price);
temp = LocateElem_Sq(L, price);
if (temp != 0) {
printf("查找成功\n");
printf("该价格对应的书名为:");
printf("%-30s\n", L.elem[temp - 1].name);
}
else
printf( "查找失败!没有这个价格对应的书籍\n\n");
break;
case 5: //顺序表的插入
printf("请输入插入的位置和书本信息,包括:编号 书名 价格(用空格隔开):");
scanf("%d",&a);
scanf("%s %s %lf", &e.id,&e.name,&e.price); //输入a和b,a代表插入的位置,b代表插入的数值(书本信息)
if (ListInsert_Sq(L, a, e))
printf("插入成功.\n\n");
else
printf("插入失败.\n\n");
break;
case 6: //顺序表的删除
printf("请输入所要删除的书籍的位置:");
scanf("%d",&c);
if (ListDelete_Sq(L, c))
printf("删除成功.\n\n");
else
printf("删除失败.\n\n");
break;
case 7: //顺序表的输出
printf("当前图书系统信息(顺序表)读出:\n");
do
{
printf("%-15s %-30s %lf\n", L.elem[p].id, L.elem[p].name, L.elem[p].price);
p++;
} while (p < L.length);
p = 0;
break;
}
}
return 0;
}
单链表
struct Book {
string id;//ISBN
string name;//书名
double price;//定价
};
typedef struct LNode {
Book data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
Status InitList_L(LinkList &L) { //算法2.6 单链表的初始化
//构造一个空的单链表L
L = new LNode; //生成新结点作为头结点,用头指针L指向头结点
L->next = NULL; //头结点的指针域置空
return OK;
}
Status GetElem_L(LinkList L, int i, Book &e) { //算法2.7 单链表的取值
//在带头结点的单链表L中查找第i个元素
//用e返回L中第i个数据元素的值
int j;
LinkList p;
p = L->next;
j = 1; //初始化,p指向第一个结点,j为计数器
while (j < i && p) { //顺链域向后扫描,直到p指向第i个元素或p为空
p = p->next; //p指向下一个结点
++j; //计数器j相应加1
}
if (!p || j > i)
return ERROR; //i值不合法i>n或i<=0
e = p->data; //取第i个结点的数据域
return OK;
} //GetElem_L
LNode *LocateElem_L(LinkList L, int e) { //算法2.8 按值查找
//在带头结点的单链表L中查找值为e的元素
LinkList p;
p = L->next;
while (p && p->data.price != e)//顺链域向后扫描,直到p为空或p所指结点的数据域等于e
p = p->next; //p指向下一个结点
return p; //查找成功返回值为e的结点地址p,查找失败p为NULL
} //LocateElem_L
Status ListInsert_L(LinkList &L, int i, Book &e) { //算法2.9 单链表的插入
//在带头结点的单链表L中第i个位置插入值为e的新结点
int j;
LinkList p, s;
p = L;
j = 0;
while (p && j < i - 1) {
p = p->next;
++j;
}//查找第i?1个结点,p指向该结点
if (!p || j > i - 1)
return ERROR; //i>n+1或者i<1
s = new LNode; //生成新结点*s
s->data = e; //将结点*s的数据域置为e
s->next = p->next; //将结点*s的指针域指向结点ai
p->next = s; //将结点*p的指针域指向结点*s
++length;
return OK;
} //ListInsert_L
Status ListDelete_L(LinkList &L, int i) { //算法2.9 单链表的删除
//在带头结点的单链表L中,删除第i个位置
LinkList p, q;
int j;
p = L;
j = 0;
while ((p->next) && (j < i - 1)) //查找第i?1个结点,p指向该结点
{
p = p->next;
++j;
}
if (!(p->next) || (j > i - 1))
return ERROR; //当i>n或i<1时,删除位置不合理
q = p->next; //临时保存被删结点的地址以备释放
p->next = q->next; //改变删除结点前驱结点的指针域
delete q; //释放删除结点的空间
--length;
return OK;
} //ListDelete_L
void CreateList_H(LinkList &L, int n) { //算法2.11 前插法创建单链表
//逆位序输入n个元素的值,建立到头结点的单链表L
LinkList p;
L = new LNode;
L->next = NULL; //先建立一个带头结点的空链表
length = 0;
fstream file;
file.open("book.txt");
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
file >> head_1 >> head_2 >> head_3;
while (!file.eof()) {
p = new LNode; //生成新结点*p
file >> p->data.id >> p->data.name >> p->data.price; //输入元素值赋给新结点*p的数据域
p->next = L->next;
L->next = p; //将新结点*p插入到头结点之后
length++;//同时对链表长度进行统计
}
file.close();
} //CreateList_F
void CreateList_R(LinkList &L, int n) { //算法2.12 后插法创建单链表
//正位序输入n个元素的值,建立带表头结点的单链表L
LinkList p, r;
L = new LNode;
L->next = NULL; //先建立一个带头结点的空链表
r = L; //尾指针r指向头结点
length = 0;
fstream file; //打开文件进行读写操作
file.open("book.txt");
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
file >> head_1 >> head_2 >> head_3;
while (!file.eof()) { //将文件中的信息运用后插法插入到链表中
p = new LNode;//生成新结点
file >> p->data.id >> p->data.name >> p->data.price;//输入元素值赋给新结点*p的数据域
p->next = NULL;
r->next = p;//将新结点*p插入尾结点*r之后
r = p;//r指向新的尾结点*p
length++; //同时对链表长度进行统计
}
file.close();
} //CreateList_L
双向链表
struct Book {
string id;//ISBN
string name;//书名
double price;//定价
};
typedef struct DuLNode {
Book data; //数据域
struct DuLNode *prior; //直接前驱
struct DuLNode *next; //直接后继
} DuLNode, *DuLinkList;
Status InitDuList_L(DuLinkList &L) {
//构造一个空的双向链表L
L = new DuLNode; //生成新结点作为头结点,用头指针L指向头结点
L->next = NULL; //头结点的指针域置空
L->prior = NULL;
return OK;
}
DuLNode *GetElemP_DuL(DuLinkList L, int i) {
//在带头结点的双向链表L中查找第i个元素,返回结点的地址
int j;
DuLinkList p;
p = L->next;
j = 1; //初始化,p指向第一个结点,j为计数器
while (j < i && p) { //顺链域向后扫描,直到p指向第i个元素或p为空
p = p->next;
++j;
}
if (!p || j > i)
return NULL; //第i个元素不存在
return p;
} //GetElemP_DuL
Status ListInsert_DuL(DuLinkList &L, int i, Book e) { //算法2.13 双向链表的插入
//在带头结点的双向链表L中第i个位置之前插入元素e,i的合法值为1<=i<=表长+1
DuLinkList s, p;
if (!(p = GetElemP_DuL(L, i))) //在L中确定第i个元素的位置指针p
return ERROR; //p为NULL时,第i个元素不存在
if (i == 1) {//在双向链表的第一个元素上插入
s = new DuLNode; //生成新结点s
s->data = e; //将结点s数据置为e
DuLinkList p = L->next;
L->next = s;
s->prior = L;
s->next = p;//将结点*s插入L中
p->prior = s;
++length;
} else if (i == length) {//在双向链表的最后一个元素上插入
s = new DuLNode; //生成新结点s
s->data = e; //将结点s数据置为e
DuLinkList p = L;
while (p->next)
p = p->next;//将LinkList p指向双向链表结尾
p->next = s;
s->prior = p;//将结点*s插入到p的后面,插入到L中
s->next = NULL;
++length;
} else {
s = new DuLNode; //生成新结点*s
s->data = e; //将结点*s数据域置为e
s->prior = p->prior; //将结点*s插入L中,此步对应图2.20①
p->prior->next = s; //对应图2.20②
s->next = p; //对应图2.20③
p->prior = s; //对应图2.20④
++length;
}
return OK;
} //ListInsert_DuL
Status ListDelete_DuL(DuLinkList &L, int i) { //算法2.14 双向链表的删除
//删除带头结点的双向链表L中第i个位置之前插入元素e,i的合法值为1<=i<=表长
DuLinkList p;
if (!(p = GetElemP_DuL(L, i))) //在L中确定第i个元素的位置指针p
return ERROR; //p为NULL时,第i个元素不存在
if (i == 1)//删除双向链表的第一个元素
L = L->next;
else if (i == length) {//删除双向链表的最后一个元素
p->prior->next = NULL;
delete p;
--length;
return OK;
} else {
p->prior->next = p->next; //修改被删结点的前驱结点的后继指针,对应图2.21①
p->next->prior = p->prior; //修改被删结点的后继结点的前驱指针,对应图2.21②
delete p; //释放被删结点的空间
--length;
return OK;
}
}//ListDelete_DuL
void CreateDuList_L(DuLinkList &L) {
//正位序输入n个元素的值,建立带表头结点的双向链表L,同时建立前驱指针
DuLinkList r, p;
L = new DuLNode;
L->next = NULL; //先建立一个带头结点的空链表
r = L;//尾指针r指向头结点
length = 0;
fstream file;
file.open("book.txt");
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
file >> head_1 >> head_2 >> head_3;
while (!file.eof()) {
p = new DuLNode; //生成新结点
file >> p->data.id >> p->data.name >> p->data.price; //输入元素值
p->next = NULL;
r->next = p; //插入到表尾
r = p; //r指向新的尾结点
p->prior = L->prior; //插入到表头
L->prior = p;
length++;
}
file.close();
} //CreateDuList_L
栈和队列
顺序栈
//顺序栈定义
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100//顺序栈存储空间的初始分配量
typedef int Status;
typedef char SElemType;
typedef struct {
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;//栈可用的最大容量
} SqStack;
//算法3.1 顺序栈的初始化
Status InitStack(SqStack &S) {
//构造一个空栈S
S.base = new SElemType[MAXSIZE];//为顺序栈动态分配一个最大容量为MAXSIZE的数组空间
if (!S.base)
exit(OVERFLOW); //存储分配失败
S.top = S.base; //top初始为base,空栈
S.stacksize = MAXSIZE; //stacksize置为栈的最大容量MAXSIZE
return OK;
}
//算法3.2 顺序栈的入栈
Status Push(SqStack &S, SElemType e) {
// 插入元素e为新的栈顶元素
if (S.top - S.base == S.stacksize)
return ERROR; //栈满
*(S.top++) = e; //元素e压入栈顶,栈顶指针加1
return OK;
}
//算法3.3 顺序栈的出栈
Status Pop(SqStack &S, SElemType &e) {
//删除S的栈顶元素,用e返回其值
if (S.base == S.top)
return ERROR;//栈空
e = *(--S.top); //栈顶指针减1,将栈顶元素赋给e
return OK;
}
//算法3.4 取顺序栈的栈顶元素
char GetTop(SqStack S) {//返回S的栈顶元素,不修改栈顶指针
if (S.top != S.base) //栈非空
return *(S.top - 1); //返回栈顶元素的值,栈顶指针不变
}
链栈
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef char SElemType;
typedef struct StackNode {
SElemType data;
struct StackNode *next;
} StackNode, *LinkStack;
//算法3.5 链栈的初始化
Status InitStack(LinkStack &S) { // 构造一个空栈 S,栈顶指针置空
S = NULL;
return OK;
}
//算法3.6 链栈的入栈
Status Push(LinkStack &S, SElemType e) {//在栈顶插入元素e
LinkStack p;
p = new StackNode; //生成新结点
p->data = e; //将新结点数据域置为e
p->next = S; //将新结点插入栈顶
S = p; //修改栈顶指针为p
return OK;
}
//算法3.7 链栈的出栈
Status Pop(LinkStack &S, SElemType &e) {//删除S的栈顶元素,用e返回其值
LinkStack p;
if (S == NULL)
return ERROR; //栈空
e = S->data; //将栈顶元素赋给e
p = S; //用p临时保存栈顶元素空间,以备释放
S = S->next; //修改栈顶指针
delete p; //释放原栈顶元素的空间
return OK;
}
//算法3.8 取链栈的栈顶元素
SElemType GetTop(LinkStack S) {//返回S的栈顶元素,不修改栈顶指针
if (S != NULL) //栈非空
return S->data; //返回栈顶元素的值,栈顶指针不变
}
链队
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char QElemType;
typedef int Status;
typedef char SElemType;
//- - - - - 队列的链式存储结构- - - - -
typedef struct QNode {
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
} LinkQueue;
//算法3.16 链队的初始化
Status InitQueue(LinkQueue &Q) {//构造一个空队列Q
Q.front = Q.rear = new QNode; //生成新结点作为头结点,队头和队尾指针指向此结点
Q.front->next = NULL; //头结点的指针域置空
return OK;
}
//算法3.17 链队的入队
Status EnQueue(LinkQueue &Q, QElemType e) {//插入元素e为Q的新的队尾元素
QueuePtr p;
p = new QNode; //为入队元素分配结点空间,用指针p指向
p->data = e; //将新结点数据域置为e
p->next = NULL;
Q.rear->next = p; //将新结点插入到队尾
Q.rear = p; //修改队尾指针
return OK;
}
//算法3.18 链队的出队
Status DeQueue(LinkQueue &Q, QElemType &e) {//删除Q的队头元素,用e返回其值
QueuePtr p;
if (Q.front == Q.rear)
return ERROR; //若队列空,则返回ERROR
p = Q.front->next; //p指向队头元素
e = p->data; //e保存队头元素的值
Q.front->next = p->next; //修改头指针
if (Q.rear == p)
Q.rear = Q.front; //最后一个元素被删,队尾指针指向头结点
delete p; //释放原队头元素的空间
return OK;
}
//算法3.19 取链队的队头元素
SElemType GetHead(LinkQueue Q) {//返回Q的队头元素,不修改队头指针
if (Q.front != Q.rear) //队列非空
return Q.front->next->data; //返回队头元素的值,队头指针不变
}
循环链队
#define MAXQSIZE 100
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char QElemType;
typedef char SElemType;
typedef int Status;
typedef struct {
QElemType *base;//初始化时动态分配存储空间
int front;//头指针
int rear;//尾指针
} SqQueue;
//算法3.11 循环队列的初始化
Status InitQueue(SqQueue &Q) {//构造一个空队列Q
Q.base = new QElemType[MAXQSIZE]; //为队列分配一个最大容量为MAXSIZE的数组空间
if (!Q.base)
exit(OVERFLOW); //存储分配失败
Q.front = Q.rear = 0; //头指针和尾指针置为零,队列为空
return OK;
}
//算法3.12 求循环队列的长度
int QueueLength(SqQueue Q) {//返回Q的元素个数,即队列的长度
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
//算法3.13 循环队列的入队
Status EnQueue(SqQueue &Q, QElemType e) {//插入元素e为Q的新的队尾元素
if ((Q.rear + 1) % MAXQSIZE == Q.front) //尾指针在循环意义上加1后等于头指针,表明队满
return ERROR;
Q.base[Q.rear] = e; //新元素插入队尾
Q.rear = (Q.rear + 1) % MAXQSIZE; //队尾指针加1
return OK;
}
//算法3.14 循环队列的出队
Status DeQueue(SqQueue &Q, QElemType &e) {//删除Q的队头元素,用e返回其值
if (Q.front == Q.rear)
return ERROR; //队空
e = Q.base[Q.front]; //保存队头元素
Q.front = (Q.front + 1) % MAXQSIZE; //队头指针加1
return OK;
}
//算法3.15 取循环队列的队头元素
SElemType GetHead(SqQueue Q) {//返回Q的队头元素,不修改队头指针
if (Q.front != Q.rear) //队列非空
return Q.base[Q.front]; //返回队头元素的值,队头指针不变
}
C语言实现循环链队:
串、数组和广义表
BF算法:可参考BF算法(串模式匹配算法)C语言详解 (biancheng.net)
/***字符串匹配算法***/
#include<cstring>
#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
#define MAXSTRLEN 255 //用户可在255以内定义最长串长
typedef char SString[MAXSTRLEN + 1]; //0号单元存放串的长度
Status StrAssign(SString T, const char* chars) { //生成一个其值等于chars的串T
int i;
if (strlen(chars) > MAXSTRLEN)
return ERROR;
else {
T[0] = strlen(chars);
for (i = 1; i <= T[0]; i++)
T[i] = *(chars + i - 1);
return OK;
}
}
//算法4.1 BF算法
int Index(SString S, SString T, int pos)
{
//返回模式T在主串S中第pos个字符之后第s一次出现的位置。若不存在,则返回值为0
//其中,T非空,1≤pos≤StrLength(S)
int i = pos;
int j = 1;
while (i <= S[0] && j <= T[0])
{
if (S[i] == T[j])
{
++i;
++j;
} //继续比较后继字符
else
{
i = i - j + 2;
j = 1;
} //指针后退重新开始匹配
}
if (j > T[0])
return i - T[0];
else
return 0;
return 0;
}//Index
int main()
{
SString S;
StrAssign(S, "bbaaabbaba");
SString T;
StrAssign(T, "abb");
cout << "主串和子串在第" << Index(S, T, 1) << "个字符处首次匹配\n";
return 0;
}