顺序栈&链栈&循环队列&链队基本操作的实现

实验三 顺序栈和队列基本操作的实现

一、实验学时: 2学时

二、实验目的

  • 实现顺序栈和队列的基本操作

三、实验内容

  1. 顺序栈的建立、取栈顶元素、入栈、出栈
  2. 队列的建立、取队中元素、入队、出队、循环队列中入队、出队操作

四、主要仪器设备及耗材

  • 硬件:计算机一台
  • 软件:VC++ 6.0,MSDN2003或者以上版本

五、实验步骤

  1. 分析问题
  2. 写出算法
  3. 编制程序
  4. 上机调试
  5. 分析结果

六、程序清单

1.顺序栈
#include
#include
#define OK 0
#define ERROR -1
#define OVERFLOW -2
#define MAXSIZE 100		//顺序栈存储空间的初始分配量 

//建立顺序栈 
typedef struct
{
	int *base;	//栈底指针
	int *top;	//栈顶指针
	int stacksize; 	//栈可用的最大容量
}SqStack;

//初始化顺序栈 
int InitStack(SqStack &S)
{
	S.base=new int[MAXSIZE];
	if(!S.base) exit(OVERFLOW);
	S.top=S.base;	//top初始为base,空栈
	S.stacksize=MAXSIZE;	//stacksize置为栈的最大容量MAXSIZE
	return OK; 
}

//压栈 
int Push(SqStack &S,int e)
{
	if(S.top-S.base==S.stacksize) return ERROR;
	*S.top++=e;             //它等价于*S.top=e;   S.top++; 
	return OK;
}

//弹栈 
int Pop(SqStack &S,int &e)
{
	if(S.top==S.base) return ERROR;
	e=*--S.top;
	return OK;
}

//取栈顶元素 
int GetTop(SqStack S)
{
	if(S.top!=S.base)
		return *(S.top-1);
}

int main()
{
	SqStack S;
	//初始化栈 
	InitStack(S);
	int jz,num;
	printf("请问你要转换几进制:");
	scanf("%d",&jz);
	printf("请输入你要转换的十进制数:");
	scanf("%d",&num);
	
	while(num!=0)
	{
		//压榨 
		Push(S,(num%jz));
		num/=jz;
	}
	
	//取栈顶元素 
	printf("栈顶元素为%d\n",GetTop(S)); 
	
	while(S.top!=S.base)
	{
		int i;
		//弹栈 
		Pop(S,i);
		printf("%d",i);
	}
}
2.链栈
#include
#include
#define OK 0
#define ERROR -1
#define OVERFLOW -2

//创建链栈 
typedef struct StackNode
{
	int data;
	struct StackNode *next;
}StackNode,*LinkStack;

//初始化
int InitStack(LinkStack &S)
{
	//构造一个空栈S,栈顶指针置空
	S=NULL;
	return OK;
}

//入栈
int Push(LinkStack &S,int e)
{
	//在栈顶插入元素e
	StackNode *p;
	p=new StackNode;
	p->data=e;
	p->next=S;	//将新节点插入栈顶
	S=p;		//修改栈顶指针为p
	return OK;
}

//出栈
int Pop(LinkStack &S,int &e)
{
	//删除S的栈顶元素,用e返回其值
	if(S==NULL) return ERROR;
	e=S->data;
	StackNode *p;
	p=S;	//用p临时保存栈顶元素空间,以备释放
	S=S->next;	//修改栈顶指针
	delete p;	//释放原栈顶元素空间
	return OK;
} 

//取栈顶元素
int GetTop(LinkStack &S)
{
	if(S!=NULL)
		return S->data;
} 

int main()
{
	LinkStack S;
	//链栈初始化 
	InitStack(S);
	int jz,num;
	printf("请问你要转换几进制:");
	scanf("%d",&jz);
	printf("请输入你要转换的十进制数:");
	scanf("%d",&num);
	
	while(num!=0)
	{
		//压栈 
		Push(S,(num%jz));
		num/=jz;
	}
	
	//取栈顶元素
	printf("栈顶元素为:%d\n",GetTop(S)); 
	
	while(S!=NULL)
	{
		int i;
		//弹栈 
		Pop(S,i);
		printf("%d",i);
	} 
}
3.循环队列
#include
#include
#define MAXSIZE 6

//建立顺序队列 
typedef struct
{
	int *base;	//存储空间的基地址
	int front;	//头指针
	int rear;	//尾指针
}SqQueue;

//初始化顺序队列 
int InitQueue(SqQueue &Q)
{
	Q.base=new int[100];
	if(!Q.base) exit(-2);
	Q.front=Q.rear=0;	//头指针和尾指针置为0,队列为空
	return 0;
}

//入队
int EnQueue(SqQueue &Q,int e)
{
	//printf("rear=%d,front=%d\n",Q.rear,Q.front);
	if((Q.rear+1)%MAXSIZE==Q.front)	 //队满
		return -1;
	Q.base[Q.rear]=e;	//新元素加入队尾
	Q.rear=(Q.rear+1)%MAXSIZE;	//队尾指针加1
	//printf("rear=%d,front=%d\n",Q.rear,Q.front);
	return 0; 
}

//出队
int DeQueue(SqQueue &Q,int &e)
{
	if(Q.front==Q.rear) return -1;	//队空
	e=Q.base[Q.front];	//队头元素给e
	Q.front=(Q.front+1)%MAXSIZE;	//队头指针加1
	return 0;
} 

//取队头元素
int GetHead(SqQueue Q)
{
	if(Q.front!=Q.rear)	//队列非空
		return Q.base[Q.front];	//返回队头元素的值
} 

//求循环队列长度
int QueueLength(SqQueue Q)
{
	return (Q.rear-Q.front+MAXSIZE)%MAXSIZE;
} 

//胡乱写的...
void f1(SqQueue &Q,int &num)
{
	while(num!=0){
		int flag=EnQueue(Q,num);
		if(!flag)
			printf("%d入队成功!\n",num);
		else
			printf("%d入队失败!\n",num);
		printf("请输入要入队的东东:");
		scanf("%d",&num);
	}
	if(num==0)
		printf("检测到0,入队结束!\n请输入要出队的元素个数:");
		int count,i;
		scanf("%d",&count);
		if(count>QueueLength(Q))
			printf("队列中元素不足...\n");
		for(i=0;i<count;i++)
		{
			int chu;
			DeQueue(Q,chu);
			printf("%d已出队\n",chu);
		}
		printf("请输入要入队的东东:");
		scanf("%d",&num);
		f1(Q,num);
}

int main()
{
	SqQueue Q;
	//循环队列初始化 
	InitQueue(Q);
	int num=0;
	printf("请输入要入队的东东:");
	scanf("%d",&num);
	f1(Q,num);
}
4.链队
#include
#include
#define MAXSIZE 6

//建立队列的链式存储结构
typedef struct QNode
{
	int data;
	struct QNode *next;
}QNode,*QueuePtr;

typedef struct
{
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

//初始化
int InitQueue(LinkQueue &Q)
{
	Q.front=Q.rear=new QNode;	 //生成新结点作为头结点,队头和队尾指针指向该结点
	Q.front->next=NULL;	//头结点的指针域置空
	return 0;
}

//入队
int EnQueue(LinkQueue &Q,int e)
{
	QNode *p;
	p=new QNode;	//为入队元素分配结点空间,用指针p指向
	p->data=e;		//将新结点数据域置为e
	p->next=NULL;Q.rear->next=p;	//将新结点插入到队尾
	Q.rear=p;		//修改队尾指针
	return 0;
} 

//出队
int DeQueue(LinkQueue &Q,int &e)
{
	if(Q.front==Q.rear) return -1;	//队列为空报错
	QNode *p;
	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 0;
} 

//取队头元素
int GetHead(LinkQueue Q)
{
	if(Q.front!=Q.rear)
		return Q.front->next->data;
} 

int main()
{
	//和顺序队列测的方法差不多
}

七、运行结果及分析

1.顺序栈

顺序栈&链栈&循环队列&链队基本操作的实现_第1张图片

2.链栈

顺序栈&链栈&循环队列&链队基本操作的实现_第2张图片

3.循环队列

顺序栈&链栈&循环队列&链队基本操作的实现_第3张图片

4.链队

和循环队列的测试差不多

八、小总结

1.顺序栈
  • 对于顺序栈来说,就跟汉诺塔一样,先进的后出后进的先出。它里面有三个成员:栈顶指针、栈底指针和栈可用的最大容量。
  • 初始化:动态分配一个最大容量大小的数组空间,栈底指针指向它。如果空间满了就溢出。没满就栈顶指针也指向栈底所指。栈可用空间为最大容量。
  • 入栈:若栈满则报错,否则栈顶指针所指空间数据置为元素e,栈顶指针上移。
  • 出栈:栈空报错,否则栈顶指针向下移,元素赋给e。
  • 取栈顶元素:栈非空,则返回栈顶元素即可。
2.链栈
  • 对于链栈来说,感觉比顺序栈简单
  • 初始化:把栈顶指针置空即可。
  • 入栈:开个新结点p,数据域置为e,指向S,S=p(让新加的作栈顶)
  • 出栈:若栈空则报错,否则取出栈顶数据给e,p临时保存原栈顶,让S的下一个做栈顶,释放原栈顶空间。
  • 取栈顶元素:若S非空,则返回栈顶元素。
3.循环队列
  • n个元素的循环队列满的时候只有n-1个元素。P71。这时候(Q.rear+1)%MAXSIZE==Q.front已经成立了。最后一个位置是空着的。但是判满条件已经满足了。
  • 建立队列:自定义类型SqQueue,里面有三个成员。一是base指针,指向存储空间的基地址;二是头指针三是尾指针(只是两个整型变量用来指示队首队尾位置的)。
  • 初始化:基地址指针指向新开辟的基地址空间,若为NULL则溢出。头指针尾指针均置为0,。
  • 入队:队满则报错。将新元素插入队尾,队尾指针加1。
  • 出队:队空报错。队头元素赋给e,头指针加1。
  • 取队头元素:队列非空返回队头值。
  • 求队列长度:(Q.rear-Q.front+MAXSIZE)%MAXSIZE;
4.链队

你可能感兴趣的:(数据结构,队列,数据结构)