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

news2024/10/6 8:29:24

 目录

一、设计要求

二、实现方法

三、实现过程

1.链栈的实现

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

3.括号匹配

4.链队列的实现

5.队列实现栈

6.应用代码实现汇总

7.小猫钓鱼


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

一、设计要求

1.栈的有关操作*

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

2.栈的应用举例**

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

3.队列的有关操作*

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

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

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

二、实现方法

编辑器:VS2019

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

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

三、实现过程

1.链栈的实现

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

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

Stack.h文件源码

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<assert.h>

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 << "请选择"<<std::endl;
	}
}

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<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<assert.h>

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文件中,然后编写一个菜单,进行选择要进行的应用操作。小猫钓鱼单独写一个文件实现。

test.cpp

#include"Stack.h"
#include"Queue.h"
#include<string.h>
#include<assert.h>
#include<iostream>
#include<time.h>
#include<windows.h>

/************************************************/
//栈出入测试
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 << "请选择"<<std::endl;
	}
}


/**************************************************/
//队列出入测试
void test_Queue()
{
	printf("*********队列的出入操作*********\n");
	int n;
	Queue Q;
	QueueInit(Q);
	printf("请输入入队元素个数:\n");
	std::cin >> 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<string.h>
#include<iostream>

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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/727764.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++读取一行内个数不定的整数的方式

&#x1f4af; 博客内容&#xff1a;C读取一行内个数不定的整数的方式 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准前端&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家&…

如何查询组织结构(组织结构树)

创建简单的组织表 字段1&#xff1a; 组织ID字段2&#xff1a;组织名称字段3&#xff1a;组织的父级ID -- 创建组织结构表 CREATE TABLE organization (id VARCHAR(36) PRIMARY KEY,name VARCHAR(100),parent_id VARCHAR(36) );插入几条数据 INSERT INTO organization (id, …

3D模型轻量化开发工具HOOPS与WebGL的对比分析

HOOPS是一种商业级的3D开发平台&#xff0c;由Tech Soft 3D公司开发。它提供了一套全面的工具和API&#xff0c;用于构建和展示高度复杂的3D场景和模型&#xff0c;可以在多个平台和环境中使用&#xff0c;包括Web、移动设备和桌面&#xff0c;这使得开发者能够在不同的设备上展…

Spring的事务隔离

随着应用程序复杂性的增加&#xff0c;数据库的并发读写需求也越来越高。对于一个电商平台而言&#xff0c;每天都会有数十万笔的交易数据需要处理&#xff0c;这就需要能够高效地处理并发事务。Spring作为一个强大的应用框架&#xff0c;提供了事务管理的功能&#xff0c;可以…

WhaleStudio 完成与涛思数据 TDengine 产品相互兼容性测试认证

近日&#xff0c;WhaleStudio 与涛思数据 TDengine 产品已完成相互兼容性测试认证。 白鲸开源与涛思数据的联合测试结果显示&#xff0c;Whalestudio 平台与涛思数据 TDengine 产品双方产品完全兼容&#xff0c;整体运行稳定高效。 WhaleStudio 是白鲸开源科技根据全球领先的 …

如何在海外推广一个新品牌?

在海外推广一个新品牌时&#xff0c;以下是一些步骤和策略可以帮助你&#xff1a; 1、 市场调研&#xff1a;了解目标海外市场的文化、消费者行为和偏好&#xff0c;以及竞争情况。这将帮助你了解如何定位你的品牌&#xff0c;并制定相应的推广策略。 2、 品牌定位和价值观&am…

ARM半主机模式介绍

文章目录 什么是半主机参考链接&#xff1a; 什么是半主机 半主机是一种机制&#xff0c;它使运行在arm目标上的代码能够在运行调试器的主机上通信和使用输入/输出功能。 这些工具包括键盘输入&#xff0c;屏幕输出和磁盘I/O。例如&#xff0c;你可以使用这种机制来启用C库中的…

华为OD机试真题 Python 实现【新员工座位安排系统】【2022Q4 100分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、Python算法源码六、效果展示1、输入2、输出3、说明 一、题目描述 工位由序列F1,F2…Fn组成&#xff0c;Fi值为0、1或2。其中0代表空置&#xff0c;1代表有人&#xff0c;2代表障碍物。 1、某一空位的友好度为左右连…

【MySQL】幻读被彻底解决了吗?

一、MySQL 幻读被彻底解决了吗 MySQL InnoDB 引擎的默认隔离级别虽然是【可重复读】&#xff0c;但是它很大程度上避免幻读现象&#xff08;并不是完全解决了&#xff09;&#xff0c;解决的方案有两种&#xff1a; 针对快照读&#xff08;普通 select 语句&#xff09;&#…

Element-UI 在表单通过按钮动态增加Tree树形控件

文章目录 问题背景动态增加的Tree控件创建el-tree控件数据动态增加的el-tree控件编辑数据前需进行设置勾选状态新增/编辑请求前需转换格式 问题背景 在表单中动态增加的Tree控件中&#xff0c;注册一个 ref 引用&#xff0c;报错如下&#xff1a; this.$refs[‘showRegionsTre…

Linux下Qt breakpad编译使用

一、下载安装包 下载qbreakpad源码&#xff1a; git clone https://github.com/buzzySmile/qBreakpad.git下载breakpad源码 git clone https://github.com/google/breakpad下载linux-syscall-support 没有这个文件&#xff0c;编译报错 git clone https://github.com/adels…

Stable Diffusion WebUI Ubuntu 22.04 LTS RTX2060 6G 极限显存出图

模型 默认选中 chilloutmix_Ni.safetensors&#xff0c;重启webui.sh进程 正向词 best quality, ultra high res, (photorealistic:1.4), 1girl, <lora:koreanDollLikeness_v15:1> ,<lora:yaeMikoRealistic_yaemikoMixed:1>, 反向词 paintings, sketches, (…

数字万用表的四种妙用方法

数字万用表&#xff08;Digital Multimeter&#xff0c;简称DMM&#xff09;是一种在电子电路测试和维修中常用的仪器。它可以测量电压、电流、电阻等各种电信号参数&#xff0c;同时还可以测试二极管、晶体管等元器件。数字万用表使用数字显示&#xff0c;具有高精度、易读性好…

SQL高级教程第三章

SQL CREATE DATABASE 语句 CREATE DATABASE 语句 CREATE DATABASE 用于创建数据库。 SQL CREATE DATABASE 语法 CREATE DATABASE database_name SQL CREATE DATABASE 实例 现在我们希望创建一个名为 "my_db" 的数据库。 我们使用下面的 CREATE DATABASE 语句&…

SQL19 分组过滤练习题

selectuniversity,round(avg(question_cnt), 3) as avg_question_cnt,round(avg(answer_cnt), 3) as avg_answer_cnt fromuser_profile group byuniversity havingavg_question_cnt < 5or avg_answer_cnt < 20;

抖音矩阵系统源码部署技术分享--基于抖音开放平台

开发概述 开放平台基于开发者诉求和相关平台规则&#xff0c;提供了两种开放模式&#xff1a;能力开放、行业开放。 自研开发者介绍 自研开发者是指有自己的自营业务&#xff0c;或是有多种加盟方的角色&#xff0c;可以基于用户需求&#xff0c;提供完整的技术解决方案。 …

【Redis】高可用之二:哨兵(sentinel)

本文是Redis系列第5篇&#xff0c;前4篇欢迎移步 【Redis】不卡壳的 Redis 学习之路&#xff1a;从十大数据类型开始入手_AQin1012的博客-CSDN博客关于Redis的数据类型&#xff0c;各个文章总有些小不同&#xff0c;我们这里讨论的是Redis 7.0&#xff0c;为确保准确&#xff…

dockerfile常用指令

Dockerfile常用指令 视频学习资料来源这里&#xff0c;点击本行文字即可跳转&#xff0c;讲的比较详细&#xff0c;不过比较老&#xff0c;跟最新的肯定是有一些差异的 Dockerfile官网文档的话点击这里 中文文档可以看看这个&#xff0c;不过没有详细的代码demo 或者是看这个 或…

3. 日志模块(下)

在日志模块的上篇中&#xff0c;我们详细拆解了 MyBatis 是如何整合第三方日志框架&#xff0c;实现了完善的日志功能的。那么在本节中&#xff0c;我们再来具体分析下&#xff1a;为了实现“将日志功能优雅地嵌入到核心流程中&#xff0c;实现无侵入式地日志打印”这一目标&am…

菜谱APP项目实战,可以魔改任意APP——前后端齐全

菜谱APP开发实战&#xff08;可改任意APP&#xff09; 1. 优点 多平台性 由于此APP开发的时候采用的是 uni-app 来开发的&#xff0c;所以说它可以打包成多种形态&#xff0c;在各种平台上进行使用。比如&#xff1a;微信、支付宝等各种小程序。当然也是可以打包成安卓APP&am…