数据结构代码

2.4 线性表的顺序表示和实现

/*线性表*/
/*顺序表——顺序存储结构*/
#include<iostream>
using namespace std;
#define maxsize 100
typedef struct //定义顺序表的结构体
{
	int data[maxsize];//存放顺序表元素的数组,默认是int型,可根据题目要求将int换成其他类型
	int length;//存放顺序表的长度
}Sqlist;
/*
顺序表的基本操作:
1、InitList(&L);//初始化操作,建立一个空的线性表;(因为涉及原表数据需要作改动,所以使用引用的方法&L)
2、DestroyList(&L);//销毁已存在的线性表L(引用原表)
3、ClearList(&L);//将线性表清空(问:为什么会涉及引用?和销毁表有什么区别吗?)
4、ListInsert(&L,i,e);//在线性表L的i位置插入e元素(问:为什么此处e不用引用)
5、ListDelete(&L,i,&e);//删除线性表L的i位置的e元素,返回e(问:为什么e也要引用?,元素直接删除不就行了,引用是为了干啥)
6、IsEmpty(L);//bool类型的函数,如果L为空则返回true,否则返回false
7、ListLength(L);//返回线性表L的元素个数
8、LocateElem(L,e);//按值查找,在L中查找与给定值e相等的元素,若成功返回该元素在表中的序号,否则返回0
9、GetElem(L,i,&e);//按位查找,将L中的第i个位置元素返回给e
*/

/*
顺序表的删除:
线性表的删除操作是指将表的第i(1<=i<=n)个结点删除使长度为n的线性表(a1,...,ai-1,ai,ai+1,...,an)变成长度为n-1的线性表(a1,...,ai-1,ai+1,...,an)
算法思想:
①判断删除位置i是否合法(合法值为1<=i<=n)
②将与删除的元素保留在e中
③将第i+1至第n位的元素依此向前移动一个位置
④表长减一,删除成功返回OK
*/
/*
int ListDelete(Sqlist &L, int i,int &e)//操作:删除算法
{
	if ((i<1)||(i>L.length))//判断删除位置是否合法
		return false;
    e=L.data[i-1];
	for (int j = i;j < L.length;j++)
	{
		L.data[j-1] = L.data[j];
	}
    L.length--;
	return true;
}
*/
/*int ListDelete(Sqlist L, int i, int& e)//操作:删除操作
{
	if ((i < 1) || (i > L.length))//1、判断删除位置i是否合法
		return false;
	e = L.data[i];
	for (int j=i;j <= L.length-1;j++)//2、将第i+1至第n位的元素依次向前移动一个位置
	{
		e = L.data[i];
		L.data[j-1] = L.data[j];
		L.length--;//3、表长减一,删除成功返回OK
	}
	return e;
}
//时间复杂度:n-1/2(O(n))
*/

/*
顺序表的插入:
线性表的插入运算是指在表的第i(1<=i<=n+1)个位置上,插入一个新结点e,使长度为n的线性表(a1,...,ai-1,ai,...,an)变成长度为n+1的线性表(a1,...,ai-1,e,ai,...,an)变成长度为n+1的线性表(a1,...,ai-1,e,ai,...,an)
算法思想:
①判断插入位置i是否合法
②判断顺序表的存储空间是否已满,若已满返回ERROR
③将第n至第i位的元素依次向后移动一个位置,空出第i个位置
*/
int ListInsert(Sqlist &L, int i, int e)//操作:插入操作——在i位置插入e元素(问:i,e是否都是用户给出的数值?)
{
	if (i<1 || i>L.length + 1)//判断插入位置是否合法
		return false;
	if (L.length == maxsize)//判断存储空间是否为满
		return false;
	for (int j = L.length - 1;j >= i - 1;j--)//注意此处j为L.length-1,且插入是倒着插
		L.data[j + 1] = L.data[j];
	L.data[i - 1] = e;
	L.length++;
	return true;
}
int InitList(Sqlist &L) //构造一个空的顺序表L;
{
	L.length = 0;
	return true;
}
int ListDelete(Sqlist &L, int i,int &e)//操作:删除算法
{
	if ((i<1)||(i>L.length))//判断删除位置是否合法
		return false;
    e=L.data[i-1];
	for (int j = i;j < L.length;j++)
	{
		L.data[j-1] = L.data[j];
	}
    L.length--;
	return true;
}
int GetElem(Sqlist L,int i,int &e) //操作:按位查找——在线性表中查找i位置的元素,返回给e,注意此处的引用符号&的实际使用方法
{
	e = L.data[i-1];//注意这里返回的是数组的i-1
	return e;
}
int LocateElem(Sqlist L, int e)//操作:按值查找——在线性表L中查找值为e的数的位置
{
    int i;
	for (i = 0;i < L.length;i++)
	{
		if (L.data[i]==e) 
			return i+1;
	}
    return -1;
}
int Getlength(Sqlist L)//操作:获得线性表的长度
{
	return(L.length);
}
int main()
{
	Sqlist L;
   int e;
	/*
	int a = 0;
	int i = 0;
	L.length = 10;
	std::cout << "第一次赋值操作后:";
	for (int i = 0;i < 10; i++) //线性表的数组赋值
	{
		L.data[i] = i;
		std::cout << L.data[i];
	}
	ListInsert(L,2,6);
	std::cout << "第一次数组长度为:"<<L.length<<endl;
	std::cout << "第一次插入操作后:" ;
	for (int i = 0;i < 10; i++) //线性表的数组赋值
	{
		std::cout<< L.data[i];
	}
	std::cout << "第二次数组长度为:" <<L.length<<endl;
	ListDelete(L, 3);
	std::cout << "第一次删除操作后:";
	for (int i = 0;i < 10; i++) //线性表的数组赋值
	{
		std::cout<< L.data[i];
	}
	std::cout << "第三次数组长度为:" <<L.length<<endl;
	*/
	InitList(L);
   std::cout << "第一次初始化操作后数组长度为:" <<Getlength(L)<<endl;
	ListInsert(L, 1, 1);
	ListInsert(L, 2, 2);
	ListInsert(L, 3, 3);
	ListInsert(L, 4, 4);
	ListInsert(L, 5, 5);
	for (int i = 0;i < L.length; i++) //线性表的数组赋值
	{
		std::cout << L.data[i];
	}
	std::cout << "第一次插入操作后数组长度为:" <<Getlength(L)<<endl;
	ListDelete(L, 1,e);
	for (int i = 0;i < L.length; i++) //线性表的数组赋值
	{
		std::cout << L.data[i];
	}
	std::cout << "第二次删除操作后数组长度为:" <<Getlength(L)<< endl;
   std::cout << "第二次删除操作中被删除的元素为" <<e<< endl;
   std::cout<<"按位查找第2位的e元素值为:"<<GetElem(L,2,e)<<endl;
   std::cout<<"按值查找元素值为3的数字在数组中的位数为:"<<LocateElem(L,3)<<endl;
	return 0;
}

2.5 线性表的链式表示和实现

#include<iostream>
#define OK
#define Status
using namespace std;
typedef struct Lnode{
	int data;
	struct Lnode *next;//我定义我自己(一个嵌套的定义,因为指针指向的也是一个结构体)
}Lnode,*LinkList;//Linklist为指向结构体Lnode的指针类型
/*
单链表的初始化(带头结点的单链表)——即构造一个如图的空表
算法步骤:
①生成新结点作头结点,用头指针指向头结点。
②将头结点的指针域置空。
*/
 void InitList_L(LinkList &L)
{
	L = new Lnode; //或L = (LinkList) malloc (sizeof (LNode));申明新结点的存储空间
	L->next = NULL;
}
 /*
 单链表的算法2——判断头结点指针域是否为空(判空)
 空表:链表中无元素,称为空链表(头结点和头指针仍然在)
 */
 int ListEmpty(LinkList L)
 {
	 if (L->next)
		 return 0;
	 else
		 return 1;
 }
 /*
 单链表的算法3——单链表的销毁,链表销毁后不存在(销毁所有结点,包括头结点,所以此处的单链表不作是否有头结点的区分,因为所有的结点都销毁)
 算法思路:从头指针开始,依次释放所有结点
 */
 int DestroyList_L(LinkList &L) //销毁单链表L
 {
	 Lnode* p;//或LinkList p;
	 while (L) {
		 p = L;
		 L = L -> next;//如何让指针指向下一个结点
		 delete p;
	 }
	 return 0;
 }
 /*
单链表的算法4——清空链表:链表仍存在,但链表中无元素,成为空链表(头指针和头结点依然存在)
算法思路:依次释放所有结点,并将头结点的指针域设置为空
*/
 int ClearList(LinkList& L) {//将L重置为空表
	 Lnode* p, *q;//或LinkList p,q;
	 p = L->next;
	 while (p) {//没到表尾,指针p存放当前结点,p不为空就反复执行
		 q = p->next; //q指向要删除结点的下一个结点
		 delete p;
		 p = q;
	 }
	 L->next = NULL;//头结点指针域为空(头结点一般不存放数据)
	 return 0;
 }
 /*
 单链表的算法5——求单链表的表长
 算法思路:从首元结点开始,遍历的同时计数所有结点
 */
 int Listlength_L(LinkList L) {//返回L中数据元素个数
	 LinkList p;
	 p = L->next;//p指向第一个结点(如果有头结点,那么此处p指向的就是首元结点)
	 int i = 0;
	 while (p)//遍历单链表,统计结点数
	 {
		 i++;
		 p = p->next;
	 }
	 return i;
 }
 /*
 单链表的算法6——找第i位置的元素
 算法思路:
 ①从第i个结点(L->next)顺链扫描,用指针p指向当前扫描到的结点,p初值p = L -> next。
 ②j作计数器,累计当前扫描过的结点数,j初值为1。
 ③当p指向扫描到的下一结点时,计数器j加1。
 ④当j == 1,p所指的结点就是要找的第i个结点。
 */
 /*自写:找第i位置的元素*/
  //错误点一:while循环条件写错了
 //错误点二:算法的健壮性不够,对于不合理输入情况的判断不够
 //错误点三:k的初始值需要注意,是否带头结点,情况不同
 int GetElem(LinkList L,int i,int &e) 
 {
	 int k = 1;
	 LinkList p;
	 p = L-> next;
	 while (i != k)//注意while循环的条件,如果符合条件就会一直执行循环内的语句
	 {
		 p = p-> next;
		 k++;
	 }
	 e = p->data;
	 return e;
 }
 /*题解*/
 int GetElem_L(LinkList L, int i, int& e)//获取线性表L中的某个数据元素的内容,通过变量e返回
 {
	 LinkList p = L->next;
	 int j = 1;//初始化
	 while (p && j < i) {
		 //向后扫描,直到p指向第i个元素或p为空(要求p不为空,且j还没找到i,没找到就一直找)
		 //while循环语句的语法:如果符合条件,则一直执行循环语句,不符合条件时跳出
		 //情况一:j = i,找到了e元素,跳出循环
		 //情况二:p = NULL, 没找到e元素,且链表遍历完了,跳出循环
		 p = p->next;
		 ++j;
	 }
	 //如果p为空或者j>1,则没找到e元素,故如此返回
	 if (!p || j > i)//第i个元素不存在
		 return 1;
	 e = p->data;//取第i个元素
	 return 0;
 }
 /*
 单链表的算法7——按值查找:根据指定元素获取该数据所在的位置
 算法思路:
 ①从第一个结点起,依次和e相比较
 ②如果找到一个其值与e相等的数据元素,则返回其在链表中的“位置”或地址
 ③如果查遍整个链表都没有找到其值与e相等的元素,则返回0或“NULL”
 */
 /*自写:找元素为i的数据在线性表所在的位置,有错误*/
 //错误点一:while循环条件写错了
 //错误点二:算法的健壮性不够,对于不合理输入情况的判断不够
 //错误点三:k的初始值需要注意,是否带头结点,情况不同
 int LocateElem(LinkList L, int e, int &k)
 {
	 k = 1;
	 LinkList p;
	 p = L->next;
	 while (p->data != e)
	 {
		 p = p->next;
		 k++;
	 }
	 return k;
 }
 /*老师解一*/
Lnode* LocateElem_L(LinkList L, int e)
 {
	 //在线性表L中查找值为e的数据元素
	 //找到,则返回L中值为e的数据元素的地址,查找失败则返回NULL
	 LinkList p = L->next;
	 while (p && p->data != e) {
		 //判断遍历整个链表过程中
		 // 情况一:找到元素e且链表中还有其他元素,则正常返回p
		 // 情况二:还没有找到元素e且p已经为空,返回的p为NULL,可由外部调用函数的人自行判断
		p = p->next;
	 }
	 return p;
 }
/*老师解二*/
int LocateElem_L2(LinkList L, int e)
{
	//在线性表L中查找值为e的数据元素
	//找到,则返回L中值为e的数据元素的地址,查找失败则返回NULL
	LinkList p = L->next;
	int j = 1;
	while (p && p->data != e) {
	//判断遍历整个链表过程中
	// 情况一:找到元素e且链表中还有其他元素,则正常返回p
	// 情况二:还没有找到元素e且p已经为空,返回的p为NULL
		p = p->next;
		j++;
	}
	//if语句判断p是否为空
	// 情况一:不为空则返回j计数器,找到e
	// 情况二:为空则返回0,说明没找到e
	if (p)
		return j;
	else
		return 0;
}
/*
单链表的算法8——插入操作:在第i个结点前插入值为e的新结点
算法思路:
①首先找到ai-1的存储位置p。
②生成一个数据域为e的新结点s。
③插入新结点:
--新结点的指针域指向结点ai
--结点ai-1的指针域指向新结点
*/ 
 int InsertList(LinkList& L, int i, int e)
 {
	 LinkList p = L;//头指针
	 int j = 0;
	 while (p && j < i - 1)//第i-1个结点的地址存放在前一个结点的指针域中,所以此处为j<i-1
	 {
		 p = p->next;
		 ++j;//寻找第i-1个结点,p指向i-1个结点
		 if (!p || j > i - 1)//i大于表长+1或者小于1,插入位置非法
			 return 0;
	 }
	 LinkList s = new Lnode;//生成新结点s,将结点s的数据域置为e
	 s->data = e;//将结点s插入L中
	 s->next = p->next;
	 p->next = s;
 }
 /*
 单链表的算法9——建立单链表:头插法——元素插入在链表头部,也叫前插法
 算法思路:
 ①从一个空表开始,重复读入数据。
 ②生成新结点,将读入数据存放到新结点的数据域中。
 ③从最后一个结点开始,依次将各结点插入到链表的前端
 */
 void CreateList_H(LinkList& L, int n)
 {
	 L = new Lnode;
	 L->next = NULL;//先建立一个带头结点的单链表
	 for (int i = n;i > 0;--i)
	 {
		LinkList p = new Lnode;//生成新结点p=(Lnode*)malloc(sizeof(Lnode));
		cin >> p->data;//输入元素值scanf(&p->data);
		p->next = L->next;//插入到表头
		L->next= p;
	 }
 }
 /*
  单链表的算法9——建立单链表:尾插法——元素插入在链表尾部,也叫后插法
  算法思路:
  ①从一个空表L开始,将新结点逐个插入到链表的尾部,尾指针r指向链表的尾结点。
  ②初始时,r同L均指向头结点。每读入一个数据元素则申请一个新结点,将新结点插入到尾节点后,r指向新结点。
  ③从最后一个结点开始,依次将各结点插入到链表的前端
  */
 void CreateList_R(LinkList& L, int n)
 {
	 L = new Lnode;
	 L->next = NULL;
	 LinkList r = L;//尾指针r指向头结点
	 for (int i = 0;i < n;++i)
	 {
		 LinkList p = new Lnode;
		 cin >> p->data;//生成新结点,输入元素值
		 p->next = NULL;
		 r->next = p;//插入到表尾
		 r = p;//r指向新的尾结点
	 }
 }
 /*
单链表的算法10——删除操作:在第i个结点前删除值为e的新结点(带头结点吗?头结点算不算第一个结点)
算法思路:
①首先找到ai-1的存储位置p,保存要删除的ai的值。
②另p->next指向ai+1。
③释放结点ai的空间。
*/
 int deleteList(LinkList& L, int i, int &e)
 {
	 LinkList p = L;
	 int j = 0;
	 while (p->next && j < i - 1)//这里的条件是什么意思?寻找第i个结点,并令p指向其前驱
	 {
		 p = p->next;
		 ++j;
	 }
	 if (!(p->next) || j > i - 1)//删除位置不合理
		 //位置不合理的两种情况:
		 //①删除位置小于0,j > i-1
		 //②链表为空p->next为空
		 return 0;
	 LinkList q = p->next;//临时保存被删结点的地址以备释放
	 p->next = q->next;//改变删除结点前驱结点的指针域
	 e = q->data;//保存删除结点的数据域
	 delete q;//释放被删除结点的空间
	 return 0;
 }
 void scanLinkList(LinkList L)
 {
	 int k = 0;//k元素用于计数
	 LinkList p;
	 p = L->next;//p指针指向L链表的第一个结点
	 while (p)//如果p不为空,则循环遍历该单链表
	 {
		 cout << p->data << endl;//输出每个元素
		 p = p->next;//p指针不断下移指向下一个结点
		 k++;//k作为链表长度不断加一
	 }
 }
int main()
{
	int e;
	int k;
	LinkList L;//定义链表
	Lnode *p;//定义结点指针p
	//LinkList p;//定义结点指针p(和上边一样)
	InitList_L(L);//初始化
	ClearList(L);//清空链表
	//CreateList_H(L, 5);//头插法
	//CreateList_R(L, 5);//尾插法
	scanLinkList(L);
	InsertList(L, 1, 1);//插入
	InsertList(L, 2, 2);
	InsertList(L, 3, 3);
	InsertList(L, 4, 4);
	InsertList(L, 5, 5);
	scanLinkList(L);//遍历
	//GetElem_L(L, 2, e);//按位查找
	GetElem(L, 3, e);
	cout<<"线性表L的第三个元素为:" <<e<<endl;
	//cout << "线性表L的元素为3的数据所在位置为:" <<LocateElem_L(L, 3) <<endl;//按值查找
	cout << "线性表L的元素为3的数据所在位置为:" << LocateElem(L, 3, k) << endl;
	deleteList(L, 1, e);//删除
	cout << "被删除元素为:" << e<<endl;
	scanLinkList(L);
}

3.1 栈的顺序表示和实现

/*线性表*/
/*顺序栈——顺序存储结构*/
/*存储方式:同一般线性表的顺序存储结构完全相同*/
/*利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。栈底一般在低地址端*/
/*--附设top指针,指示栈顶元素在顺序栈中的位置*/
/*--另设base指针,指示栈底元素在顺序栈中的位置*/
#include<iostream>
#include<stdio.h>
#define MAXSIZE 100
using namespace std;
typedef struct {
	int *base;//栈底指针
	int *top;//栈顶指针
	int stacksize;//栈可用最大容量
}SqStack;
/*顺序栈算法一:顺序栈的初始化*/
int InitStack(SqStack& S)//构造一个空栈
{
	S.base = new int[MAXSIZE];//或S.base=(SElemtype*)malloc(MAXSIZE *sizeof(SElemtype));
	if (!S.base)exit(OVERFLOW);//存储分配失败
	S.top = S.base;//栈顶指针等于栈底指针
	S.stacksize = MAXSIZE;
	return 0;
}
/*顺序栈算法二:判断顺序栈是否为空*/
int Is_Empty(SqStack& S)
{
	//若栈空,则返回TRUE;否则返回FALSE
	if (S.top == S.base)
		return 0;
	else
		return 1;
}
/*顺序栈算法三:求顺序栈长度*/
int StackLength(SqStack S)
{
	return S.top - S.base;
}
/*顺序栈算法四:清空顺序栈*/
int ClearStack(SqStack &S)//有问题,是否需要带引用符
{
	if (S.base)//判断栈是否存在
		S.top = S.base;
	return 0;
}
/*顺序栈算法五:销毁顺序栈*/
int DestroyStack(SqStack& S)
{
	if (S.base) {//如果栈存在且不为空
		delete S.base;//删除栈底指针
		S.stacksize = 0;//将栈的个数设置为0
		S.base = S.top = NULL;//top指针和base指针均设置为空(不是已经删除栈底指针了吗,为什么还要置空)
	}
	return 0;
}
/*顺序栈算法六:顺序栈的入栈*/
/*算法思想:
* ①判断是否栈满,若满则出错(上溢)
* ②元素e压入栈顶
* ③栈顶指针加一*/
int Push(SqStack& S, int e)
{
	if (S.top - S.base == S.stacksize)//栈满
		return 1;
	*S.top++ = e;//将e赋给top指针所指的空间,然后top指向下一空间
	return 0;
}
/*顺序栈算法七:顺序栈的出栈*/
/*算法思想:
* ①判断是否栈空,若空则出错(下溢)
* ②获取栈顶元素e
* ③栈顶指针减一*/
int pop(SqStack& S, int& e)
{
	//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
	if (S.top == S.base)//等价于if(StackEmpty(S))
		return 1;
	else
	{
		e = *--S.top;//指针先下移,然后再取指针当初所取的元素的值赋值给e
		return 0;
	}
}
void ScanSqStack(SqStack S)//遍历栈
{
	int e = StackLength(S);
	if (e > 0)
	{
		for (int i = 0;i < e;i++)
		{
			cout << S.base[i] << endl;
		}
	}
	else
	{
		cout << "顺序栈为空" << endl;
	}
}
int main()
{
	int e;
	SqStack S;
	InitStack(S);//初始化栈
	Push(S, 1);//入栈
	Push(S, 2);
	Push(S, 3);
	Push(S, 4);
	Push(S, 5);
	ScanSqStack(S);
	cout<<"栈长度为" << StackLength(S) << endl;
	pop(S,e);//出栈
	ScanSqStack(S);//遍历栈
	cout << "栈长度为" << StackLength(S) << endl;
	ClearStack(S);
	cout<<"判断是否栈空,如果栈空返回0,如果栈不空返回1:" << Is_Empty(S) << endl;
	DestroyStack(S);
	ScanSqStack(S);//遍历栈
}

3.2 栈的链式表示和实现

/*线性表*/
/*链栈——链式存储结构*/
/*链栈是运算受限的单链表,只能在链表头部进行操作*/
#include<iostream>
#include<stdio.h>
using namespace std;
typedef struct StackNode {
	int data;
	struct StackNode* next;
}StackNode,*LinkStack;
/*链栈算法一:链栈的初始化*/
int InitStack(LinkStack& S)
{
	//构造一个空栈,栈顶指针置为空
	S = NULL;
	return 0;
}
/*链栈算法二:判断链栈是否为空*/
int StackEmpty(LinkStack S)
{
	if (S == NULL)
		return 0;
	else
		return 1;
}
/*链栈算法三:链栈的入栈*/
int Push(LinkStack& S, int e)
{
	LinkStack p = new StackNode;//生成新结点p
	p->data = e;//将新结点数据域置为e
	p->next = S;//将新结点插入栈顶
	S = p;//修改栈顶指针
	return 0;
}
/*链栈算法四:链栈的出栈*/
int Pop(LinkStack& S, int& e)
{
	if (S == NULL)
		return 0;
	e = S->data;
	LinkStack p = S;
	S = S->next;
	delete p;
	return 0;
}
/*链栈算法五:取栈顶元素*/
int GetTop(LinkStack S)
{
	if (S != NULL)
		return S->data;
}
void scanStack(LinkStack S)
{
	while (S)
	{
		cout << S->data << endl;
		S = S->next;
	}
}
int main()
{
	int e;
	LinkStack S;
	InitStack(S);
	cout<<"是否栈空,栈空返回0,不空返回1:" << StackEmpty(S) << endl;
	Push(S, 1);
	Push(S, 2);
	Push(S, 3);
	scanStack(S);
	Pop(S,e);
	cout << "弹出栈顶元素后:" << endl;
	scanStack(S);
}
/*栈与递归*/
/*1、递归的定义*/
/*若一个对象部分地包含它自己,或用它自己给自己定义,则称这个对象是递归的;*/
/*若一个过程直接或间接地调用自己,则称这个过程是递归的过程。例如:递归求n的阶乘。*/
/*2、以下三种情况常常用到递归方法:*/
/*①递归定义的数学函数:*/
/*②具有递归特性的数据结构:二叉树,广义表...*/
/*③可递归求解的问题:迷宫问题,Hanoi塔问题...*/
/*3、分治法求解递归问题算法的一般形式:*/
/*void p(参数表)*/
/*{
if(递归结束条件) 可直接求解步骤;——基本项*/
/*else p(较小的参数);}——归纳项*/

3.5 队列的顺序表示和实现

/*队列*/
/*队列是仅在表尾进行插入操作,在表头进行删除操作的线性表。*/
/*表尾即an端,称为队尾;表头即a1端,称为队头。*/
/*它是一种先进先出(FIFO)的线性表。*/
/*顺序队列——顺序存储结构*/
#include<iostream>
#include<stdio.h>
#define MAXQSIZE 100//最大队列长度
using namespace std;
typedef struct {
	int* base;//初始化的动态分配存储空间
	int front;//头指针
	int rear;//尾指针
}SqQueue;
/*顺序队列算法1——队列的初始化*/
int InitQueue(SqQueue& Q)
{
	Q.base = new int[MAXQSIZE];//分配数组空间
	//Q.base=(QElemType *)malloc(MAXSIZE *sizeof(QElemType));
	if (!Q.base) exit(OVERFLOW);//存储分配失败
	Q.front = Q.rear = 0;//头指针尾指针置为0,队列为空
	return 0;
}
/*顺序队列算法2——求队列的长度*/
int QueueLength(SqQueue Q)
{
	return((Q.rear - Q.front+MAXQSIZE)%MAXQSIZE);
}
/*顺序队列算法3——循环队列出队*/
int DeQueue(SqQueue& Q, int& e)
{
	if (Q.front == Q.rear)//队空
		return 0;
	e = Q.base[Q.front];//保存队头元素
	Q.front = (Q.front + 1) % MAXQSIZE;//队头指针+1
	return e;
}
/*顺序队列算法3.1——循环队列入队*/
int InsertQueue(SqQueue& Q, int e)
{
	//需要判断队列是否为满队列吗?如何判断
	Q.base[Q.rear] = e;//将要插入的元素赋给rear指针
	Q.rear = (Q.rear + 1) % MAXQSIZE;//队尾指针+1
	return 0;
}
/*顺序队列算法4——取队头元素*/
int GetHead(SqQueue Q)
{
	if (Q.front != Q.rear)//队列不为空
		return Q.base[Q.front];//返回队头指针元素的值,队头指针不变
	return 1;
}
void scanQueue(SqQueue Q)
{
	int e = Q.front;
	int r = Q.rear;
	for (int i = e;i < r;i++)
	{
		cout << Q.base[i] << endl;
	}
}
int main()
{
	int e;
	SqQueue Q;
	InitQueue(Q);//初始化队列
	InsertQueue(Q, 1);//插入队列元素
	InsertQueue(Q, 2);
	InsertQueue(Q, 3);
	cout<<"队头元素为:"<<GetHead(Q)<<endl;
	scanQueue(Q);//遍历队列
	cout<<"出队元素为:"<<DeQueue(Q, e)<<endl;
	InsertQueue(Q, 4);
	scanQueue(Q);
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值