数据结构课设---C语言为主体+引用

 目录

一、设计要求

二、实现方法

三、实现过程

1.链栈的实现

2.前缀表达式变后缀表达式

3.括号匹配

4.链队列的实现

5.队列实现栈

6.应用代码实现汇总

7.小猫钓鱼


文章只写了代码的实现,并未进行原理的讲解,希望大家不喜勿喷

数据结构课设---C语言为主体+引用_第1张图片

一、设计要求

1.栈的有关操作*

要求实现对链栈的入栈和出栈操作。

2.栈的应用举例**

利用链栈实现中缀表达式变成后缀表达式、括号匹配问题。

3.队列的有关操作*

实现对链队列的入队和出队操作,通过链队列实现队列实现栈。

4.栈和队列的综合应用举例**

综合链栈和链队列实现小猫钓鱼游戏。

二、实现方法

编辑器:VS2019

语言:主要是以C语言为主,结合了c++的引用。所以文件后缀名要用 .cpp

实现原理:先实现链栈和链队列的增删查改和取长度、判空等方法,再此基础之上来实现相关的应用。

三、实现过程

1.链栈的实现

先创建一个头文件Stack.h,将所需的头文件和方法名先包含在里面。

在创建StackCode.cpp文件,用于实现方法。

Stack.h文件源码

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include

typedef char ElemType;//栈中的数据类型为char
//typedef int ElemType;//用于小猫钓鱼,记得切换

typedef struct stack {
	ElemType data;
	struct stack* next;
}StackNode, * LinkStackNode;

void InitStack(LinkStackNode& L);//初始化
LinkStackNode CreatNode(ElemType e);//创建一个新节点
void StackPush(LinkStackNode& L, ElemType e);//栈插入
void StackPop(LinkStackNode& L, ElemType& e);//出栈
void GetStackTop(LinkStackNode& L,ElemType& e);//取栈顶元素
bool StackEmpty(LinkStackNode& L);//判空
int StackSize(LinkStackNode L);//取栈大小
void DestroyStack(LinkStackNode& L);//栈的销毁
void Print(LinkStackNode L);//打印

StackCode.cpp文件源码 

#include"Stack.h"

void InitStack(LinkStackNode& L)
{
	L = NULL;
}

LinkStackNode CreatNode(ElemType e)
{
	LinkStackNode newnode = (LinkStackNode)malloc(sizeof(StackNode));
	if (!newnode)
	{
		printf("malloc is fail\n");
		exit(-1);
	}
	//新节点赋值
	newnode->data = e;
	newnode->next = NULL;
	return newnode;
}

void StackPush(LinkStackNode& L, ElemType e)
{
	LinkStackNode newnode = CreatNode(e);//创建一个节点
	newnode->next = L;//相当于头插到链中
	L = newnode;//换头节点
}

void StackPop(LinkStackNode& L, ElemType& e) {
	if (L == NULL)
	{
		printf("L is NULL\n");
		exit(-1);
	}
	LinkStackNode next = L->next;//取头的下一个节点
	e = L->data;
	free(L);
	L = next;//使L再次指向头位置
}

void GetStackTop(LinkStackNode& L, ElemType& e) {
	if (L == NULL)
	{
		printf("L is NULL\n");
		return;
	}
	e = L->data;
}

void DestroyStack(LinkStackNode& L) {
	LinkStackNode cur = L;
	while (cur) {
		L = L->next;
		free(cur);
		cur = L;
	}
}

int StackSize(LinkStackNode L)
{
	LinkStackNode cur = L;
	int count = 0;
	while (cur)
	{
		count++;
		cur = cur->next;
	}
	return count;
}

bool StackEmpty(LinkStackNode& L) {
	return L == NULL;
}

void Print(LinkStackNode L)
{
	LinkStackNode cur = L;
	while (cur)
	{
		//printf("%d->", cur->data);
		std::cout << cur->data << "->";
		cur = cur->next;
	}
	printf("NULL\n");
}

 测试代码:

void test_Stack()
{
	printf("*********栈的出入操作************\n");
	LinkStackNode stack;
	InitStack(stack);
	//入栈数据
	printf("请输入入栈元素个数:\n");
	int n;
	scanf("%d", &n);
	printf("请依次输入入栈的元素(字符类型)\n");
	for (int i = 0; i < n; i++)
	{
		ElemType val;
		std::cin >> val;  //c++的输入,比较方便所以这里使用了,也可以改为c的scanf
		StackPush(stack, val);
	}
	printf("入栈元素为:\n");
	Print(stack);
	printf("请选择:1.入栈  2.出栈  3.释放栈空间\n");
	int option;
	while (std::cin>>option)
	{
		switch (option)
		{
		case 1:ElemType elem;
			printf("请输入入栈元素\n");
			std::cin >> elem;
			StackPush(stack, elem);
			printf("入栈后为:\n");
			Print(stack);
			break;
		case 2:
			ElemType e;
			StackPop(stack, e);
			std::cout << "出栈元素为" << e << ", 出栈后栈为:" << std::endl;//c++的打印,可以改用c的printf
			Print(stack);
			break;
		case 3:
			DestroyStack(stack);
			printf("栈空间以释放\n");
			system("pause");
			return;
			break;
		default:
			printf("输入错误,请重新输入\n");
		}
		std::cout << "请选择"<

2.前缀表达式变后缀表达式

int Return_Prio(char c)  //计算运算符的优先级
{
	if (c == '+' || c == '-')
		return 1;
	else if (c == '*' || c == '/' || c == '%')
		return 2;
	else if (c == '^')
		return 3;
	else
		return 0;
}
//中缀变后缀
void mid_to_postfix(char* str,char* ans)
{
	ElemType elem;//栈出来的元素
	int j = 0;
	LinkStackNode L;
	InitStack(L);
	//出入元素
	for (int i = 0; i < strlen(str); i++)
	{
		//取元素
		char c = str[i];
		//判断单个元素,进行出入栈进行匹配
		switch (c)
		{
		//如果是运算符,则进行比较,高于栈顶优先级则入栈,低于栈顶优先级则出栈到后缀
		case '+':
		case '-':
		case '*':
		case '/':
		case '%':
		case '^':
			while (!StackEmpty(L))//栈非空时
			{
				//将优先级大于c的全部入后缀
				GetStackTop(L, elem);
				if (Return_Prio(elem) >= Return_Prio(c))
				{
					ans[j++] = elem;//入后缀
					StackPop(L, elem);//删除改栈顶
				}
				else
				{
					break;
				}
			}
			StackPush(L, c);//将str的算术符入栈
			break;
		//括号比较
		case '(':
			StackPush(L, c);//左括号直接入栈
			break;
		case ')'://如果时右括号,就一直出栈入后缀,直到左括号
			StackPop(L, elem);
			while (elem != '(')
			{
				ans[j++] = elem;
				StackPop(L, elem);
			}
			break;
		default:ans[j++] = c;//操作数,直接入后缀
		}
	}
	//将栈中剩余的算术符全部出栈
	while (!StackEmpty(L))
	{
		StackPop(L, elem);
		ans[j++] = elem;
	}
	ans[j] = '\0';
	DestroyStack(L);
}
void test_mid_to_postfix()
{
	printf("请输入一个中缀表达式\n");
	char s[100];
	scanf("%s", s);
	char postfix[100];
	mid_to_postfix(s, postfix);
	printf("其后缀表达式为%s\n", postfix);
	system("pause");
}

3.括号匹配

bool chkParenthesis(char* A, int n)
//判断是否满足匹配
{
	LinkStackNode st;
	InitStack(st);
	char tmp;
	for (int i = 0; i < n; i++)
	{
		char c = A[i];
		switch (c)
		{
		//左括号入栈
		case '(':
			StackPush(st, c);
			break;
		case '[':
			StackPush(st, c);
			break;
		case '{':
			StackPush(st, c);
			break;
		//右括号出栈,前提判断栈顶是否为左括号与之匹配
		case ')':
			
			GetStackTop(st, tmp);
			if (StackEmpty(st) || tmp != '(')
				return false;
			else
				StackPop(st, tmp);
			break;
		case ']':
			
			GetStackTop(st, tmp);
			if (StackEmpty(st) || tmp != '[')
				return false;
			else
				StackPop(st, tmp);
			break;
		case '}':
			
			GetStackTop(st, tmp);
			if (StackEmpty(st) || tmp != '{')
				return false;
			else
				StackPop(st, tmp);
			break;
		default:return false;//其他字符直接fasle
		}
	}
	if (!StackEmpty(st))//栈为空才表名括号是匹配的
		return false;
	return true;
}
void test_chkParenthesis()
{
	printf("请输入需要判断的括号\n");
	char A[100];
	scanf("%s", A);
	int n = strlen(A);
	bool res= chkParenthesis(A, n);
	if (res)
		printf("结果为:true\n");
	else
		printf("结果为:false\n");
	system("pause");
}

4.链队列的实现

先创建一个头文件Queue.h,将所需的头文件和方法名先包含在里面。

在创建QueueCode.cpp文件,用于实现方法。

Queue.h源码

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include

typedef char ElemType;//用于队列实现栈时
//typedef int ElemType;//用于小猫钓鱼,记得切换

typedef struct QueueNode
{
	struct QueueNode* next;
	ElemType data;
}QNode, *LQNode;

typedef struct//设置头尾指针
{
	LQNode head;
	LQNode tail;
}Queue;


void QueueInit(Queue& Q);//初始化
void QueuePush(Queue& Q,ElemType e);//入队
void QueuePop(Queue& Q,ElemType &e);//出队
bool QueueEmpty(Queue Q);//判空
int QueueSize(Queue Q);//求队列大小
ElemType GetQueueTop(Queue Q);//去队头元素 
int GetQueueBack(Queue Q);//去队尾元素
void QueueDestroy(Queue& Q);//释放空间
void QueuePrint(Queue Q);

QueueCode.cpp源码

#include"Queue.h"

void QueueInit(Queue& Q)
{
	//创建头
	Q.head = (LQNode)malloc(sizeof(QNode));
	if (!Q.head)
	{
		printf("malloc is fail\n");
		exit(-1);
	}
	Q.head->next = NULL;
	Q.tail = Q.head;
}

void QueuePush(Queue& Q,ElemType e) {
	//创建节点
	LQNode p = (LQNode)malloc(sizeof(QNode));
	if (!p)
	{
		printf("malloc is fail\n");
		exit(-1);
	}
	p->data = e;
	p->next = Q.tail->next;
	Q.tail->next = p;
	Q.tail = p;
}

void QueuePop(Queue& Q, ElemType& e)
{
	if (Q.head == Q.tail)
	{
		printf("Q is NULL\n");
		return;
	}
	//指向待删除的结点
	LQNode p = Q.head->next;
	e = p->data;
	//链接删除节点后面的链
	Q.head->next = p->next;
	if (Q.tail == p)//如果删除是尾节点,则删后链为空,尾就要与头相等
	{
		Q.tail = Q.head;
	}
	free(p);
}

bool QueueEmpty(Queue Q)
{
	if (Q.head == Q.tail)
		return true;
	return false;
}

int QueueSize(Queue Q)
{
	LQNode tmp = Q.head->next;
	if (Q.head == Q.tail)
	{
		printf("Q is NULL\n");
		return 0;
	}
	int count = 0;
	while (tmp != NULL)
	{
		tmp = tmp->next;
		count++;
	}
	return count;
}

void QueueDestroy(Queue& Q)
{
	LQNode tmp = Q.head->next;
	//释放每一个节点
	while (tmp)
	{
		LQNode next = tmp->next;
		free(tmp);
		tmp = next;
	}
	Q.head = Q.tail;
}

ElemType GetQueueTop(Queue Q)
{
	if (Q.head->next==NULL)
		return '0';
	return (Q.head->next)->data;
}

int GetQueueBack(Queue Q)
{
	return (Q.tail)->data;
}

void QueuePrint(Queue Q)
{
	 
	LQNode tmp= Q.head->next;
	if (Q.head == Q.tail)
	{
		printf("Q is NULL\n");
		return;
	}
	while (tmp !=NULL)
	{
		//printf("%d->", tmp->data);
		std::cout << tmp->data<<"->";
		tmp = tmp->next;
	}
	printf("NULL\n");
}

5.队列实现栈

typedef struct {
	Queue first;
	Queue second;
} MyStack;//两个队列实现栈
MyStack* myStackCreate() {//初始化
	MyStack* node = (MyStack*)malloc(sizeof(MyStack));
	QueueInit(node->first);
	QueueInit(node->second);//从外到内初始化
	return node;
}//初始化
void myStackPush(MyStack* obj, ElemType x) {
	//入栈即往非空入队列
	if (!QueueEmpty(obj->first))
	{
		QueuePush(obj->first, x);
	}
	else
	{
		QueuePush(obj->second, x);
	}
}
ElemType myStackPop(MyStack* obj) {
	//出栈即非空出队列到拎一个空队列,剩下最后一个元素即为出栈元素
	assert(obj);
	ElemType rval;
	if (!QueueEmpty(obj->first))
	{
		while (QueueSize(obj->first) > 1)//直到最后一个元素之前
		{
			QueuePush(obj->second, GetQueueTop(obj->first));
			QueuePop(obj->first,rval);
		}
		//清空该队列,使变为空
		ElemType cur = GetQueueTop(obj->first);
		QueuePop(obj->first,rval);
		return cur;
	}
	else
	{
		while (QueueSize(obj->second) > 1)
		{
			QueuePush(obj->first, GetQueueTop(obj->second));
			QueuePop(obj->second,rval);
		}
		ElemType cur = GetQueueTop(obj->second);
		QueuePop(obj->second, rval);
		return cur;
	}
}
ElemType myStackTop(MyStack* obj) {
	assert(obj);
	if (!QueueEmpty(obj->first))//非空队列取
		return GetQueueBack(obj->first);//栈顶元素相当于队列尾元素
	else
		return GetQueueBack(obj->second);
}
bool myStackEmpty(MyStack* obj) {
	assert(obj);
	if (QueueEmpty(obj->first) && QueueEmpty(obj->second))//两队列全空为空
		return true;
	else
		return false;
}
void myStackFree(MyStack* obj) {
	//销毁改“栈”
	QueueDestroy(obj->first);
	QueueDestroy(obj->second);
	free(obj);
	obj = NULL;//从内到外销毁
}
void test_Queeu_to_Staack()
{
	char s[100];
	printf("请输入队列模拟栈的入栈元素:\n");
	scanf("%s", s);
	printf("入栈后为:");
	int len = strlen(s);
	for (int i = 0; i < len; i++)
	{
		printf("%c ", s[i]);
	}
	printf("\n");
	MyStack* myst;
	myst=myStackCreate();
	for (int i = 0; i < strlen(s); i++)
	{
		myStackPush(myst, s[i]);
	}
	ElemType e=0;
	printf("栈顶元素为:%c\n", myStackTop(myst));
	e = myStackPop(myst);
	printf("出栈一个元素后栈顶元素为:%c\n", myStackTop(myst));
	myStackFree(myst);
	system("pause");
}

6.应用代码实现汇总

以上中缀表达式变后缀表达式、括号匹配、队列实现栈的应用写在一个test.cpp文件中,然后编写一个菜单,进行选择要进行的应用操作。小猫钓鱼单独写一个文件实现。

数据结构课设---C语言为主体+引用_第2张图片

test.cpp

#include"Stack.h"
#include"Queue.h"
#include
#include
#include
#include
#include

/************************************************/
//栈出入测试
void test_Stack()
{
	printf("*********栈的出入操作************\n");
	LinkStackNode stack;
	InitStack(stack);
	//入栈数据
	printf("请输入入栈元素个数:\n");
	int n;
	scanf("%d", &n);
	printf("请依次输入入栈的元素(字符类型)\n");
	for (int i = 0; i < n; i++)
	{
		ElemType val;
		std::cin >> val;
		StackPush(stack, val);
	}
	printf("入栈元素为:\n");
	Print(stack);
	printf("请选择:1.入栈  2.出栈  3.释放栈空间\n");
	int option;
	while (std::cin>>option)
	{
		switch (option)
		{
		case 1:ElemType elem;
			printf("请输入入栈元素\n");
			std::cin >> elem;
			StackPush(stack, elem);
			printf("入栈后为:\n");
			Print(stack);
			break;
		case 2:
			ElemType e;
			StackPop(stack, e);
			std::cout << "出栈元素为" << e << ", 出栈后栈为:" << std::endl;
			Print(stack);
			break;
		case 3:
			DestroyStack(stack);
			printf("栈空间以释放\n");
			system("pause");
			return;
			break;
		default:
			printf("输入错误,请重新输入\n");
		}
		std::cout << "请选择"<> n;
	printf("请输入入队元素\n");
	for (int i = 0; i < n; i++)
	{
		ElemType val;
		std::cin >> val;
		QueuePush(Q, val);
	}
	printf("入队后为:\n");
	QueuePrint(Q);
	printf("请选择:1.入队  2.出队   3.释放队列空间\n");
	int op;
	//std::cin >> op;
	while (std::cin >> op)
	{
		switch (op)
		{
		case 1:
			printf("请输入入队元素\n");
			ElemType elem;
			std::cin >> elem;
			QueuePush(Q, elem);
			printf("入队后为:\n");
			QueuePrint(Q);
			break;
		case 2:
			ElemType e;
			QueuePop(Q, e);
			std::cout << "出队元素为" << e << "出对后为:\n";
			QueuePrint(Q);
			break;
		case 3:
			std::cout << "队列已销毁" << std::endl;
			QueueDestroy(Q);
			system("pause");
			return;
			break;
		default:
			printf("输入错误,请重新输入\n");
		}
		printf("请选择:\n");
	}
}





/**********************************************/
//中缀表达式变后缀表达式
//先比较算术符优先级
int Return_Prio(char c)
{
	if (c == '+' || c == '-')
		return 1;
	else if (c == '*' || c == '/' || c == '%')
		return 2;
	else if (c == '^')
		return 3;
	else
		return 0;
}
//中缀变后缀
void mid_to_postfix(char* str,char* ans)
{
	ElemType elem;//栈出来的元素
	int j = 0;
	LinkStackNode L;
	InitStack(L);
	//出入元素
	for (int i = 0; i < strlen(str); i++)
	{
		//取元素
		char c = str[i];
		//判断单个元素,进行出入栈进行匹配
		switch (c)
		{
		//如果是运算符,则进行比较,高于栈顶优先级则入栈,低于栈顶优先级则出栈到后缀
		case '+':
		case '-':
		case '*':
		case '/':
		case '%':
		case '^':
			while (!StackEmpty(L))//栈非空时
			{
				//将优先级大于c的全部入后缀
				GetStackTop(L, elem);
				if (Return_Prio(elem) >= Return_Prio(c))
				{
					ans[j++] = elem;//入后缀
					StackPop(L, elem);//删除改栈顶
				}
				else
				{
					break;
				}
			}
			StackPush(L, c);//将str的算术符入栈
			break;
		//括号比较
		case '(':
			StackPush(L, c);//左括号直接入栈
			break;
		case ')'://如果时右括号,就一直出栈入后缀,直到左括号
			StackPop(L, elem);
			while (elem != '(')
			{
				ans[j++] = elem;
				StackPop(L, elem);
			}
			break;
		default:ans[j++] = c;//操作数,直接入后缀
		}
	}
	//将栈中剩余的算术符全部出栈
	while (!StackEmpty(L))
	{
		StackPop(L, elem);
		ans[j++] = elem;
	}
	ans[j] = '\0';
	DestroyStack(L);
}
void test_mid_to_postfix()
{
	printf("请输入一个中缀表达式\n");
	char s[100];
	scanf("%s", s);
	char postfix[100];
	mid_to_postfix(s, postfix);
	printf("其后缀表达式为%s\n", postfix);
	system("pause");
}




/***********************************************************/
//括号匹配  //ElemType为int时,不能用;
bool chkParenthesis(char* A, int n)
{
	LinkStackNode st;
	InitStack(st);
	char tmp;
	for (int i = 0; i < n; i++)
	{
		char c = A[i];
		switch (c)
		{
		//左括号入栈
		case '(':
			StackPush(st, c);
			break;
		case '[':
			StackPush(st, c);
			break;
		case '{':
			StackPush(st, c);
			break;
		//右括号出栈,前提判断栈顶是否为左括号与之匹配
		case ')':
			
			GetStackTop(st, tmp);
			if (StackEmpty(st) || tmp != '(')
				return false;
			else
				StackPop(st, tmp);
			break;
		case ']':
			
			GetStackTop(st, tmp);
			if (StackEmpty(st) || tmp != '[')
				return false;
			else
				StackPop(st, tmp);
			break;
		case '}':
			
			GetStackTop(st, tmp);
			if (StackEmpty(st) || tmp != '{')
				return false;
			else
				StackPop(st, tmp);
			break;
		default:return false;//其他字符直接fasle
		}
	}
	if (!StackEmpty(st))//栈为空才表名括号是匹配的
		return false;
	return true;
}
void test_chkParenthesis()
{
	printf("请输入需要判断的括号\n");
	char A[100];
	scanf("%s", A);
	int n = strlen(A);
	bool res= chkParenthesis(A, n);
	if (res)
		printf("结果为:true\n");
	else
		printf("结果为:false\n");
	system("pause");
}




/********************************************************/
//队列实现栈
typedef struct {
	Queue first;
	Queue second;
} MyStack;//两个队列实现栈
MyStack* myStackCreate() {//初始化
	MyStack* node = (MyStack*)malloc(sizeof(MyStack));
	QueueInit(node->first);
	QueueInit(node->second);//从外到内初始化
	return node;
}//初始化
void myStackPush(MyStack* obj, ElemType x) {
	//入栈即往非空入队列
	if (!QueueEmpty(obj->first))
	{
		QueuePush(obj->first, x);
	}
	else
	{
		QueuePush(obj->second, x);
	}
}
ElemType myStackPop(MyStack* obj) {
	//出栈即非空出队列到拎一个空队列,剩下最后一个元素即为出栈元素
	assert(obj);
	ElemType rval;
	if (!QueueEmpty(obj->first))
	{
		while (QueueSize(obj->first) > 1)//直到最后一个元素之前
		{
			QueuePush(obj->second, GetQueueTop(obj->first));
			QueuePop(obj->first,rval);
		}
		//清空该队列,使变为空
		ElemType cur = GetQueueTop(obj->first);
		QueuePop(obj->first,rval);
		return cur;
	}
	else
	{
		while (QueueSize(obj->second) > 1)
		{
			QueuePush(obj->first, GetQueueTop(obj->second));
			QueuePop(obj->second,rval);
		}
		ElemType cur = GetQueueTop(obj->second);
		QueuePop(obj->second, rval);
		return cur;
	}
}
ElemType myStackTop(MyStack* obj) {
	assert(obj);
	if (!QueueEmpty(obj->first))//非空队列取
		return GetQueueBack(obj->first);//栈顶元素相当于队列尾元素
	else
		return GetQueueBack(obj->second);
}
bool myStackEmpty(MyStack* obj) {
	assert(obj);
	if (QueueEmpty(obj->first) && QueueEmpty(obj->second))//两队列全空为空
		return true;
	else
		return false;
}
void myStackFree(MyStack* obj) {
	//销毁改“栈”
	QueueDestroy(obj->first);
	QueueDestroy(obj->second);
	free(obj);
	obj = NULL;//从内到外销毁
}
void test_Queeu_to_Staack()
{
	char s[100];
	printf("请输入队列模拟栈的入栈元素:\n");
	scanf("%s", s);
	printf("入栈后为:");
	int len = strlen(s);
	for (int i = 0; i < len; i++)
	{
		printf("%c ", s[i]);
	}
	printf("\n");
	MyStack* myst;
	myst=myStackCreate();
	for (int i = 0; i < strlen(s); i++)
	{
		myStackPush(myst, s[i]);
	}
	ElemType e=0;
	printf("栈顶元素为:%c\n", myStackTop(myst));
	e = myStackPop(myst);
	printf("出栈一个元素后栈顶元素为:%c\n", myStackTop(myst));
	myStackFree(myst);
	system("pause");
}

/**********************************************************/
/**********************************************************/
//菜单
void menu()
{
	printf("*******************************************************\n");
	printf("*******************************************************\n");
	printf("********1.栈的出入             2.队列的出入   *********\n");
	printf("********3.中缀变后缀表达式     4.括号匹配     *********\n");
	printf("********5.队列实现栈           6.银行取钱模拟 *********\n");
	printf("********             0.退出                 *********\n");
	printf("*******************************************************\n");
	printf("*******************************************************\n");
	printf("请选择:\n");
}

int main()
{
	menu();
	int op;
	
	while (std::cin >> op)
	{
		switch(op)
		{
		case 0:
			printf("程序已退出...\n");
			exit(0);
			break;
		case 1:
			test_Stack();
			break;
		case 2:
			test_Queue();
			break;
		case 3:
			test_mid_to_postfix();
			break;
		case 4:
			test_chkParenthesis();
			break;
		case 5:
			test_Queeu_to_Staack();
			break;
		case 6:
			test_Bank();
			break;
		default:
			printf("选择错误,请重新选择\n");
		}
		system("cls");
		menu();
	}

	return 0;
}

7.小猫钓鱼

小猫钓鱼是栈和队列的综合应用,这里需要将Stack.h和Queue.h中的typedef char ElemType;改为typedef int ElemType;下面将小猫钓鱼单独用一个fish_cat.cpp文件来写:

#include"Stack.h"
#include"Queue.h"
#include
#include

void Test_cat_fish() {
	Queue Q1, Q2;//玩家1 2,出牌为队列的形式 
	LinkStackNode s;//栈 ,桌子上的牌 ,收派即为出栈
	//初始化队列,两人手中都还没有牌
	QueueInit(Q1);
	QueueInit(Q2);
	InitStack(s);//桌子上没有牌 

	int book[10];//记录桌面上是否存在0~9的牌
	for (int i = 1; i <= 9; i++) {
		book[i] = 0;
	}
	int N;

	//发牌
	printf("请输入发牌数:\n");
	scanf("%d", &N);
	printf("请为玩家1发牌:\n");
	for (int i = 1; i <= N; i++) {
		int card_val;
		std::cin >> card_val;
		QueuePush(Q1, card_val);
	}
	printf("请为玩家2发牌:\n");
	for (int i = 1; i <= N; i++) {
		int card_val;
		std::cin >> card_val;
		QueuePush(Q2, card_val);
	}

	//打牌中....
	while (!QueueEmpty(Q1) && !QueueEmpty(Q2)) {

		ElemType push_card = GetQueueTop(Q1);//玩家一所出的牌	
		if (book[push_card] == 0) { //检查桌面上是否有改牌,没有就入栈(桌)
			ElemType tmp;
			QueuePop(Q1, tmp);//将此牌出队 
			StackPush(s, push_card); //打出的牌放到桌子上,入栈 
			book[push_card] = 1;//标记此牌,已存在
		}
		else {//桌面有所出的牌,先将改牌出,再收牌,入队位
			ElemType tmp;
			QueuePop(Q1, tmp);//先出牌,不入栈了,直接入队尾 
			QueuePush(Q1, push_card);//将赢的牌入队尾

			ElemType top_val;//栈顶元素
			GetStackTop(s, top_val);
			while (top_val != push_card) {//赢得牌依次放到队尾 
				book[top_val] = 0;//取消标记
				StackPop(s, tmp);//出栈
				QueuePush(Q1, top_val); //放到队尾 

				GetStackTop(s, top_val);//再取栈顶元素判断
			}
			//此时栈顶元素等于push_val,则将此牌,出栈入队列
			StackPop(s, tmp);
			book[tmp] = 0;
			QueuePush(Q1, top_val);
		}

		//判断玩家是否有手牌
		if (QueueEmpty(Q1)) {
			break;
		}//手中的牌打完,游戏结束,玩家一输 


		//玩家二出牌
		push_card = GetQueueTop(Q2);
		if (book[push_card] == 0) {//桌面没有次牌 
			ElemType tmp;
			QueuePop(Q2, tmp); //该牌出队 
			StackPush(s, push_card);//入栈
			book[push_card] = 1;//标记 
		}
		else { //桌上有相同大小的牌 
			ElemType tmp;
			QueuePop(Q2, tmp);//先出牌,不入栈了,直接入队尾 
			QueuePush(Q2, push_card);//将赢的牌入队尾

			ElemType top_val;//栈顶元素
			GetStackTop(s, top_val);
			while (top_val != push_card) {//赢得牌依次放到队尾 
				book[top_val] = 0;//取消标记
				StackPop(s, tmp);//出栈
				QueuePush(Q2, top_val); //放到队尾 

				GetStackTop(s, top_val);//再取栈顶元素判断
			}
			//此时栈顶元素等于push_val,则将此牌,出栈入队列
			StackPop(s, tmp);
			book[tmp] = 0;
			QueuePush(Q2, top_val);

			if (QueueEmpty(Q2)) {
				break;
			}
		}
	}
	//判定输赢
	if (QueueEmpty(Q2)) {
		printf("玩家一赢了!\n");
		printf("当前的牌是:\n");
		QueuePrint(Q1);

		//
		if (StackSize(s) > 0) { //桌上有牌输出中上的牌 
			printf("\n 桌上的牌是:\n");
			Print(s);
		}
		else {
			printf("桌上没有牌了!\n");
		}
	}
	else {
		printf("玩家二赢!\n");
		printf("当前手里的牌是:\n");
		QueuePrint(Q2);
		if (StackSize(s) > 0) {
			printf("\n桌上的牌是:\n");
			Print(s);
		}
		else {
			printf("桌上没有牌了!\n");
		}
	}
	system("pause");
}

int main()
{
	Test_cat_fish();
	return 0;
}

你可能感兴趣的:(数据结构,c语言)