数据结构实验二

顺序栈基本操作

/*
创建一个空的顺序栈,并实现栈的入栈、出栈、返回栈的长度、返回栈顶元素、栈的遍历等基本算法。
请将下面的程序补充完整。
输入格式
测试样例格式说明:
根据菜单操作:
1、输入1,表示要实现Push操作,紧跟着输入要Push的元素
2、输入2,表示要实现Pop操作
3、输入3,返回栈顶元素
4、输入4,返回栈的元素个数
5、输入5,表示从栈顶到栈底输出栈的所有元素
6、输入0,表示程序结束
输入样例
1
2
1
4
1
6
5
3
4
2
5
2
2
2
0
输出样例
A Stack Has Created.
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Element 2 is Successfully Pushed!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Element 4 is Successfully Pushed!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Element 6 is Successfully Pushed!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Stack is: 6 4 2 
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Top Element is 6!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Length of the Stack is 3!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Element 6 is Successfully Poped!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Stack is: 4 2 
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Element 4 is Successfully Poped!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
The Element 2 is Successfully Poped!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:
Pop Error!
1:Push 
2:Pop 
3:Get the Top 
4:Return the Length of the Stack
5:Load the Stack
0:Exit
Please choose:*/

#include<malloc.h> 
#include<stdio.h> 
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量

typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等

struct SqStack
{
     SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL//栈底指针 
     SElemType *top; // 栈顶指针
     int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈

Status InitStack(SqStack &S)      
{      
// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE
// 请补全代码
	S.base=S.base=(SElemType*)malloc(STACK_INIT_SIZE* sizeof(SElemType));//new SElemType[STACK_INIT_SIZE];//为顺序栈动态分配一个最大容量为STACK_INIT_SIZE的数组空间
	if(!S.base)
		return ERROR;//存储分配失败
	S.top=S.base;//top初始化为base 空栈
	S.stacksize=STACK_INIT_SIZE;//stacksize置为栈的最大容量
	return OK; 
}

Status Push(SqStack &S,SElemType e)  //入栈 
{
// 在栈S中插入元素e为新的栈顶元素
// 请补全代码
	if(S.top-S.base>=S.stacksize)
	{
	    S.base=(SElemType*)malloc((STACK_INIT_SIZE+STACKINCREMENT)*sizeof(SElemType));
	    if(!S.base)
	        return ERROR;
	    S.top=S.base+S.stacksize;
	    S.stacksize+=STACKINCREMENT;
	}
	//*S.top++=e;
	*S.top=e;
	S.top++;//先赋值再自增
	return OK;	
}

Status Pop(SqStack &S,SElemType &e)  //出栈 
{
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
// 请补全代码
	if(S.top==S.base)//栈空 
		return ERROR;
	e=*(S.top-1);
	S.top--;
	//e=*--S.top;//--S.top;e=*S.top;//取栈顶元素e 栈顶元素减一 
	return OK;
}

Status GetTop(SqStack S,SElemType &e) //取栈顶元素  
{ 
// 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
// 请补全代码
	if(S.top==S.base)
		return ERROR;
	e=*(S.top-1);//返回栈顶元素,栈顶指针不变  
	return OK;
}

int StackLength(SqStack S) 
{
// 返回栈S的元素个数
// 请补全代码
	return S.top-S.base; 
}

Status StackTraverse(SqStack S)// 从栈顶到栈底依次输出栈中的每个元素
{
	SElemType *p=(SElemType *)malloc(sizeof(SElemType));//请填空
	p=S.top;        //请填空
	if(S.top==S.base)//请填空
		printf("The Stack is Empty!"); 
	else
	{
		printf("The Stack is: ");
		p--;
		while(p>=S.base)            //请填空
		{
		               //请填空
			printf("%d ", *p);
			p--;	
		}
	}
	printf("\n");
	return OK;
}

int main()
{
    int a;
    SqStack S;
	SElemType x, e;
    if(InitStack(S))    // 判断顺序表是否创建成功,请填空
	{
		printf("A Stack Has Created.\n");
	}
	while(1)
	{
	    printf("1:Push \n2:Pop \n3:Get the Top \n4:Return the Length of the Stack\n5:Load the Stack\n0:Exit\nPlease choose:\n");
		scanf("%d",&a);
			switch(a)
			{
				case 1: scanf("%d", &x);
				    if(!Push(S,x))
					  	printf("Push Error!\n"); // 判断Push是否合法,请填空
					else 
					  	printf("The Element %d is Successfully Pushed!\n", x); 
				    break;
				case 2: 
					if(!Pop(S,e))
						printf("Pop Error!\n"); // 判断Pop是否合法,请填空
					else 
						printf("The Element %d is Successfully Poped!\n", e);
				  	break;
				case 3:
					if(!GetTop(S,e))
						printf("Get Top Error!\n"); // 判断Get Top是否合法,请填空
					else 
						printf("The Top Element is %d!\n", e);
				   	break;
				case 4: 
					printf("The Length of the Stack is %d!\n",StackLength(S)); //请填空
				  	break;
				case 5: StackTraverse(S);  //请填空
						break;
				case 0: return 1;
			}
	}
}

8584 循环队列的基本操作

/*Description 创建一个空的循环队列,并实现入队、出队、返回队列的长度、返回队头元素、队列的遍历等基本算法。
请将下面的程序补充完整。
输入格式
测试样例格式说明:
根据菜单操作:
1、输入1,表示要实现入队操作,紧跟着输入要入队的元素
2、输入2,表示要实现出队操作
3、输入3,返回队头元素
4、输入4,返回队列的元素个数
5、输入5,表示从队头到队尾输出队的所有元素
6、输入0,表示程序结束
输入样例
1
1
1
2
1
3
5
2
3
5
0
输出样例
A Queue Has Created.
1:Enter 
2:Delete 
3:Get the Front 
4:Return the Length of the Queue
5:Load the Queue
0:Exit
Please choose:
The Element 1 is Successfully Entered!
1:Enter 
2:Delete 
3:Get the Front 
4:Return the Length of the Queue
5:Load the Queue
0:Exit
Please choose:
The Element 2 is Successfully Entered!
1:Enter 
2:Delete 
3:Get the Front 
4:Return the Length of the Queue
5:Load the Queue
0:Exit
Please choose:
The Element 3 is Successfully Entered!
1:Enter 
2:Delete 
3:Get the Front 
4:Return the Length of the Queue
5:Load the Queue
0:Exit
Please choose:
The Queue is: 1 2 3 
1:Enter 
2:Delete 
3:Get the Front 
4:Return the Length of the Queue
5:Load the Queue
0:Exit
Please choose:
The Element 1 is Successfully Deleted!
1:Enter 
2:Delete 
3:Get the Front 
4:Return the Length of the Queue
5:Load the Queue
0:Exit
Please choose:
The Head of the Queue is 2!
1:Enter 
2:Delete 
3:Get the Front 
4:Return the Length of the Queue
5:Load the Queue
0:Exit
Please choose:
The Queue is: 2 3 
1:Enter 
2:Delete 
3:Get the Front 
4:Return the Length of the Queue
5:Load the Queue
0:Exit
Please choose:
这段代码是一个基于数组的循环队列的实现,其中包括了队列的初始化、入队、出队、获取队头元素、获取队列长度、遍历队列等操作。
其中,MAXQSIZE 定义了队列的最大长度,QElemType 定义了队列中元素的类型,SqQueue 是队列的结构体,包括了队列的存储空间、头指针、尾指针等信息。
具体来说,InitQueue 函数用于初始化队列,EnQueue 函数用于将元素入队,DeQueue 函数用于将元素出队
GetHead 函数用于获取队头元素,QueueLength 函数用于获取队列长度,QueueTraverse 函数用于遍历队列。
在 main 函数中,通过一个 while 循环来不断接收用户的输入,根据用户的选择来执行相应的操作。
其中,1 表示将元素入队,2 表示将元素出队,3 表示获取队头元素,4 表示获取队列长度,5 表示遍历队列,0 表示退出程序。
*/
#include<malloc.h> 
#include<stdio.h> 
#define OK 1
#define ERROR 0
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int QElemType;
#define MAXQSIZE 100 // 最大队列长度(对于循环队列,最大队列长度要减1)

typedef struct
{
   QElemType *base; // 初始化的动态分配存储空间
   int front; // 头指针,若队列不空,指向队列头元素
   int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
 }SqQueue;

Status InitQueue(SqQueue &Q)   
{
    Q.base = (QElemType*)malloc(MAXQSIZE*sizeof(QElemType)); // 动态分配存储空间
    if(!Q.base) 
		return ERROR; // 如果分配失败,返回ERROR
    Q.front = Q.rear = 0; // 头指针和尾指针都指向0
    return OK; // 返回OK
}

Status EnQueue(SqQueue &Q,QElemType e)  //入队 
{ 
    if((Q.rear+1)%MAXQSIZE == Q.front) 
		return ERROR; // 如果队列已满,返回ERROR
    Q.base[Q.rear] = e; // 将元素e赋值给队尾
    Q.rear = (Q.rear+1)%MAXQSIZE; // 尾指针加1
    return OK; // 返回OK
}

Status DeQueue(SqQueue &Q, QElemType &e) //出队 
{  
    if(Q.front == Q.rear) 
		return ERROR; // 如果队列为空,返回ERROR
    e = Q.base[Q.front]; // 将队头元素赋值给e
    Q.front = (Q.front+1)%MAXQSIZE; // 头指针加1
    return OK; // 返回OK
}

Status GetHead(SqQueue Q, QElemType &e)//取队头元素
{	
    if(Q.front == Q.rear) 
		return ERROR; // 如果队列为空,返回ERROR
    e = Q.base[Q.front]; // 将队头元素赋值给e
    return OK; // 返回OK
}

int QueueLength(SqQueue Q)  // 返回队列长度
{
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE; 
}

Status QueueTraverse(SqQueue Q)  // 遍历队列
{ 
    int i;
    i=Q.front;
    if(Q.front == Q.rear) 
		printf("The Queue is Empty!");  // 如果队列为空,输出"The Queue is Empty!"
    else{
        printf("The Queue is: ");
        while(i != Q.rear)     
        {
            printf("%d ",Q.base[i]); // 输出队列元素
            i = (i+1)%MAXQSIZE; // i加1
        }
    }
    printf("\n"); // 换行 
    return OK; // 返回OK
}

int main()
{
    int a;
    SqQueue S;
    QElemType x, e;
    if(InitQueue(S) == OK)    
    {
        printf("A Queue Has Created.\n"); // 输出"A Queue Has Created."
    }
    while(1)
    {
        printf("1:Enter \n2:Delete \n3:Get the Front \n4:Return the Length of the Queue\n5:Load the Queue\n0:Exit\nPlease choose:\n"); // 输出菜单
        scanf("%d",&a); // 输入选项
        switch(a)
        {
            case 1: scanf("%d", &x);
                    if(EnQueue(S, x) == ERROR) 
						printf("Enter Error!\n"); // 如果入队失败,输出"Enter Error!"
                    else 
						printf("The Element %d is Successfully Entered!\n", x); // 如果入队成功,输出"The Element %d is Successfully Entered!"
                    break;
            case 2: if(DeQueue(S, e) == ERROR) 
						printf("Delete Error!\n"); // 如果出队失败,输出"Delete Error!"
                    else 
						printf("The Element %d is Successfully Deleted!\n", e); // 如果出队成功,输出"The Element %d is Successfully Deleted!"
                    break;
            case 3: if(GetHead(S, e) == ERROR) 
						printf("Get Head Error!\n"); // 如果获取队头元素失败,输出"Get Head Error!"
                    else 
						printf("The Head of the Queue is %d!\n", e); // 如果获取队头元素成功,输出"The Head of the Queue is %d!"
                    break;
            case 4: printf("The Length of the Queue is %d!\n",QueueLength(S));  // 输出队列长度
                    break;
            case 5: QueueTraverse(S); // 遍历队列
                    break;
            case 0: return 1; // 退出程序
        }
    }
}

8585 栈的应用——进制转换

/*将输入的十进制数转换为八进制数并输出。
具体实现是将十进制数不断除以8,将余数压入栈中,最后依次输出栈中元素即可。
其中,stack<int> s定义了一个int类型的栈
s.push(n % 8)将n%8的结果压入栈s,s.top()返回栈顶元素,s.pop()弹出栈顶元素。*/
#include <iostream> 
#include <stack> 
using namespace std;
int main() 
{ //主函数
    int n; //定义变量n
    cin >> n; //输入n
    stack<int> s; //定义栈s
    while (n) 
	{ //当n不为0时
        s.push(n % 8); //将n%8的结果压入栈s
        n /= 8; //n除以8
    }
    while (!s.empty()) 
	{ //当栈s不为空时
        cout << s.top(); //输出栈顶元素
        s.pop(); //弹出栈顶元素
    }
	//FILO 
    cout << endl; //输出换行
    return 0; //返回0
}

/*#include<malloc.h>
#include<stdio.h>
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量

typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等

struct SqStack
{
     SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
     SElemType *top; // 栈顶指针
     int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈

Status InitStack(SqStack &S)
{// 请补全代码
    S.base= (SElemType*)malloc(STACK_INIT_SIZE *sizeof(SElemType*));
    if(!S.base)
    	return  ERROR;
    S.top=S.base;
    S.stacksize=STACK_INIT_SIZE;// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE
    return OK;
}

Status Push(SqStack &S,SElemType e)
{
    if(S.top-S.base>=STACK_INIT_SIZE)//扩展
    {
        S.base= (SElemType*)malloc((STACK_INIT_SIZE+STACKINCREMENT) *sizeof(SElemType*));
        if(!S.base) 
			return ERROR;
        S.top=S.base+S.stacksize;
        S.stacksize+=STACKINCREMENT;
    }
    *S.top=e;
    S.top++;
// 在栈S中插入元素e为新的栈顶元素
}

Status StackTraverse(SqStack &S)
{
// 从栈顶到栈底依次输出栈中的每个元素
	SElemType *p = (SElemType *)malloc(sizeof(SElemType));
	p = S.top;
	if(S.top==S.base)
		printf("The Stack is Empty!");
	else
	{
		p--;
		while(p>=S.base)
		{
			printf("%d", *p);
			p--;
		}
	}
	printf("\n");
	return OK;
}

int main()
{
    int n;
    scanf("%d",&n);
    SqStack s;
    InitStack(s);
    while(n!=0)
    {
        Push(s,n%8);
        n/=8;
    }
    StackTraverse(s);
    return 0;
}*/

8586 括号匹配检验

/*Description 利用栈编写满足下列要求的括号匹配检验程序:
假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,
即([]())或[([][])]等为正确的格式,[(]或([())或(()])均为不正确的格式。
输入一个包含上述括号的表达式,检验括号是否配对。
本题给出部分check()函数,要求将check()函数补充完整,并完成整个程序。
输入格式
第一行:输入一个包含圆括号或方括号、不超过80个字符的表达式串。
输出格式
第一行:若输入表达式括号匹配,输出"matching"; 若不匹配,输出具体信息:
"isn't matched pairs", 或"lack of left parenthesis"或"lack of right parenthesis"
输入样例
8*[3*(35-23)]
输出样例
matching*/
typedef char SElemType; // 定义栈元素类型
#include"malloc.h" // 动态内存分配
#include"stdio.h" // 标准输入输出
#include"math.h" // 数学函数
#include"stdlib.h" // 标准库函数 包含exit() 
#define OK 1 // 宏定义
#define ERROR 0 // 宏定义
#define TRUE 1 // 宏定义
#define FALSE 0 // 宏定义
typedef int Status; // 定义函数返回值类型
#define STACK_INIT_SIZE 10 // 宏定义
#define STACKINCREMENT 2 // 宏定义
struct SqStack // 定义顺序栈
{
	SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
	SElemType *top; // 栈顶指针
	int stacksize; // 当前已分配的存储空间,以元素为单位
 }; 
Status InitStack(SqStack &S) // 初始化栈
{ 
    S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType)); // 动态分配内存
    if(!S.base) 
		exit(ERROR); // 内存分配失败
    S.top = S.base; // 栈顶指针指向栈底
    S.stacksize = STACK_INIT_SIZE; // 栈的大小
    return OK; // 返回成功
}

Status StackEmpty(SqStack S) // 判断栈是否为空
{ 
    if(S.top == S.base) 
		return TRUE; // 栈为空
    else return FALSE; // 栈不为空
}

Status Push(SqStack &S,SElemType e) // 元素入栈
{ 
    if(S.top - S.base >= S.stacksize) // 栈满,追加存储空间
    {
        S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType)); // 动态分配内存
        /*其中,realloc函数是C语言中的动态内存分配函数,用于重新分配之前已分配的内存空间。
		S.base指向之前已分配的内存空间,S.stacksize是之前已分配的内存空间大小,STACKINCREMENT是每次追加的内存空间大小。
		这条语句的作用是在栈满时,重新分配内存空间,使得栈能够继续存储元素。*/
		if(!S.base) 
			exit(ERROR); // 内存分配失败
        S.top = S.base + S.stacksize; // 栈顶指针指向栈底
        S.stacksize += STACKINCREMENT; // 栈的大小增加
    }
    *S.top++ = e; // 元素入栈
    return OK; // 返回成功
}

 Status Pop(SqStack &S,SElemType &e) // 元素出栈
{ 
    if(S.top == S.base) 
		return ERROR; // 栈为空
    e = *--S.top; // 元素出栈,栈顶指针减一 
    return OK; // 返回成功
}

void check() // 检验括号是否配对
 { 
	SqStack s; // 定义栈
	SElemType ch[80],*p,e; // 定义字符数组和指针
    if(InitStack(s)) // 初始化栈成功
	{
    	//printf("请输入表达式\n"); // 输出提示
     	gets(ch); // 输入字符串
     	p=ch; // 指针指向字符串首地址
     	while(*p) // 没到串尾
       		switch(*p)
       		{
	            case '(': // 左括号入栈,且p++
	            case '[':Push(s, *p++); break;
	            case ')': // 右括号出栈,且p++
	            case ']':
						if(!StackEmpty(s)) // 栈不空
		                {
		                    Pop(s, e); // 弹出栈顶元素
		                    if((*p==')'&&e!='(')||(*p==']'&&e!='[')) // 弹出的栈顶元素与*p不配对
		                    {
		                      	printf("isn't matched pairs\n"); // 输出提示信息
		                      	exit(ERROR); // 退出程序
		                    }
		                    else
		                    {
		                      	p++; // 指针向后移
		                      	break; // 跳出switch语句
		                    }
		                }
		                else // 栈空
		                {
		                    printf("lack of left parenthesis\n"); // 输出提示信息
		                    exit(ERROR); // 退出程序
		                }
	         	default: p++; break; // 其它字符不处理,指针向后移
       }
    if(StackEmpty(s)) // 字符串结束时栈空
       printf("matching\n"); // 输出提示信息
    else
       printf("lack of right parenthesis\n"); // 输出提示信息
   }
 }
int main() // 主函数
 {
   check(); // 调用函数
 }
 
/*
#include <iostream>
#include <stack>
#include <string>

using namespace std;

bool check(string s)
{
    stack<char> st;
    for (int i = 0; i < s.size(); i++)
	{
        if (s[i] == '(' || s[i] == '[') 
		{ // 如果是左括号,入栈
            st.push(s[i]);
        } 
		else if (s[i] == ')') 
		{ // 如果是右括号,判断是否匹配
            if (st.empty() || st.top() != '(') 
			{ // 如果栈为空或者栈顶元素不是对应的左括号,返回false
                return false;
            } 
			else 
			{ // 否则,弹出栈顶元素
                st.pop();
            }
        } 
		else if (s[i] == ']') 
		{ // 如果是右括号,判断是否匹配
            if (st.empty() || st.top() != '[') 
			{ // 如果栈为空或者栈顶元素不是对应的左括号,返回false
                return false;
            } 
			else { // 否则,弹出栈顶元素
                st.pop();
            }
        }
    }
    return st.empty(); // 如果栈为空,说明所有括号都匹配了,返回true,否则返回false
}

int main() 
{
    string s;
    cin >> s;
    if (check(s)) 
	{ // 判断是否匹配
        cout << "Matched" << endl;
    } else 
	{
        cout << "Not matched" << endl;
    }
    return 0;
}
*/

8587 行编辑程序

/*8587 行编辑程序
Description 利用栈编写简单的行编辑程序:接受用户从终端输入的程序或数据
在输入过程中,允许用户输入出差错,并在发现有误时可以及时更正。
例如:当用户发现刚刚键入的一个字符是错的时,可以补进一个退格符“#”,以表示前一个字符无效;
如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符“@”,以表示当前行中的字符均无效。
例如:假设从终端接受了这样两行字符: whli##ilr#e (s#*s) outcha@putchar(*s=#++); 
则实际有效的是下列两行: while (*s) putchar(*s++); 
输入格式
第一行:第一个字符为输入文本的行数n;
第二行至第n行:每行均为一串字符,其间可以含有“#”和“@”符号,以回车键结束本行的输入;
输出格式
输出第一至第n行的内容如下:
第一行:第一行从终端输入的有效字符。
第二行:第二行从终端输入的有效字符。
…… ……
第n行:第n行从终端输入的有效字符。
输入样例
2
defne##ine OK 1
typp cila@type int element
输出样例
define OK 1
type int element
*/

// 定义字符类型
typedef char SElemType;
// 引入头文件
#include"malloc.h" 
#include"stdio.h"
#include"math.h"
#include"stdlib.h" // exit()
// 定义常量
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
// 定义状态类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
// 定义栈的初始分配量和分配增量
#define STACK_INIT_SIZE 10 // 存储空间初始分配量
#define STACKINCREMENT 2 // 存储空间分配增量
// 定义顺序栈结构体
struct SqStack
{
    SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
    SElemType *top; // 栈顶指针
    int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈

// 构造一个空栈S
Status InitStack(SqStack &S)
{ 
    S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if (!S.base) exit(ERROR);
    S.top = S.base;
    S.stacksize = STACK_INIT_SIZE;
    return OK;
}

// 若栈S为空栈,则返回TRUE,否则返回FALSE
Status StackEmpty(SqStack S)
{ 
    if (S.top == S.base) return TRUE;
    else return FALSE;
}

// 把S置为空栈
Status ClearStack(SqStack &S)
{ 
    S.top = S.base;
    return OK;
}

// 销毁栈S,S不再存在
Status DestroyStack(SqStack &S)
{ 
    free(S.base);
    S.base = NULL;
    S.top = NULL;
    S.stacksize = 0;
    return OK;
}

// 插入元素e为新的栈顶元素
Status Push(SqStack &S, SElemType e)
{ 
    if (S.top - S.base >= S.stacksize) {
        S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
        if (!S.base) exit(ERROR);
        S.top = S.base + S.stacksize;
        S.stacksize += STACKINCREMENT;
    }
    *S.top++ = e;
    return OK;
}

// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status Pop(SqStack &S, SElemType &e)
{ 
    if (S.top == S.base) return ERROR;
    e = *--S.top;
    return OK;
}

// 从栈底到栈顶依次对栈中每个元素调用函数visit()。
// 一旦visit()失败,则操作失败
Status StackTraverse(SqStack S, Status(*visit)(SElemType))
{ 
    while (S.top > S.base)
        visit(*S.base++);
    printf("\n");
    return OK;
}

// visit函数
Status visit(SElemType c)
{
    printf("%c", c);
    return OK;
}

// 利用字符栈s,从终端接收一行并送至调用过程的数据区。算法3.2
void LineEdit()
{ 
    SqStack s;
    char ch, c;
    int n, i;
    InitStack(s);
    scanf("%d", &n);
    ch = getchar();
    for (i = 1; i <= n; i++)
    {
        ch = getchar();
        while (ch != '\n')
        {
            switch (ch)
            {
            case '#': Pop(s, c);
                break; // 仅当栈非空时退栈
            case '@': ClearStack(s);
                break; // 重置s为空栈
            default: Push(s, ch); // 有效字符进栈
            }
            ch = getchar(); // 从终端接收下一个字符
        }
        StackTraverse(s, visit); // 将从栈底到栈顶的栈内字符输出
        ClearStack(s); // 重置s为空栈
    }
    DestroyStack(s);
}

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

8588 表达式求值

/*8588 表达式求值
顺序栈的基本操作如下:
利用栈编写表达式求值程序:输入含有“+”、“-”、“*”、“/”四则运算的表达式
其中负数要用(0-正数)表示,并以=结束。要求输出表达式的值(两运算符号的优先关系见教材表3.1)。
输入格式
第一行:一个算术表达式
输出格式
第一行:算术表达式的值
输入样例
3*(9-7)=
输出样例
6*/
#include<iostream>//表达式求值    
#include<cstring>
#include<cstdio>
#include<stack>
using namespace std;
 
stack<char> opter;    //运算符栈
stack<double> opval;  //操作数栈
 
int Index(char theta)   //获取theta所对应的索引
{
	int index = 0;
	switch (theta)
	{
		case '+':
			index = 0;
			break;
		case '-':
			index = 1;
			break;
		case '*':
			index = 2;
			break;
		case '/':
			index = 3;
			break;
		case '(':
			index = 4;
			break;
		case ')':
			index = 5;
			break;
		case '=':
			index = 6;
		default:
			break;
	}
	return index;
}
 
char getPriority(char theta1, char theta2)   //获取theta1与theta2之间的优先级
{
	const char priority[][7] =     //算符间的优先级关系
	{
		{ '>','>','<','<','<','>','>' },/*     +   -   *   /   (   )   #      */
		{ '>','>','<','<','<','>','>' },/*     +   -   *   /   (   )   #      */
		{ '>','>','>','>','<','>','>' },/*     +   -   *   /   (   )   #      */
		{ '>','>','>','>','<','>','>' },/*     +   -   *   /   (   )   #      */
		{ '<','<','<','<','<','=','0' },/*     +   -   *   /   (   )   #      */
		{ '>','>','>','>','0','>','>' },/*     +   -   *   /   (   )   #      */
		{ '<','<','<','<','<','0','=' },/*     +   -   *   /   (   )   #      */
	};
	int index1 = Index(theta1);
	int index2 = Index(theta2);
	return priority[index1][index2];
}
 
double calculate(double b, char theta, double a)   //计算b 符号 a
{
	switch (theta)
	{
		case '+':
			return b + a;
		case '-':
			return b - a;
		case '*':
			return b * a;
		case '/':
			return b / a;
		default:
			break;
	}
}
 
double Answer()   //表达式求值
{
	opter.push('=');      //首先将'='入运算符栈opter
	int counter = 0;      //添加变量counter表示有多少个数字相继入栈,实现多位数的四则运算
	char c = getchar();
	while (c != '=' || opter.top() != '=')   //终止条件
	{
		if (isdigit(c))   //如果c在'0'~'9'之间,isdigit判断是否是数字,直接调用C++函数
		{
			if (counter == 1)//counter==1表示上一字符也是数字,所以要合并,比如11*11,要算11,而不是单独的1和1
			{
				double t = opval.top();
				opval.pop();
				opval.push(t * 10 + (c - '0'));
				counter = 1;
			}
			else
			{
				opval.push(c - '0'); //将c对应的数值入数字栈opval
				counter++;
			}
			c = getchar();
		}
		else//运算符 
		{
			counter = 0;   //counter置零
			switch (getPriority(opter.top(), c))   //获取运算符栈opter栈顶元素与c之间的优先级,用'>','<','='表示
			{
				case '<':               //<则将c入栈opter
					opter.push(c);
					c = getchar();
					break;
				case '=':/*   =将opter栈顶元素弹出,
						用于括号的处理  */
					opter.pop();
					c = getchar();
					break;
				case '>':               //>则计算
					char theta = opter.top();
					opter.pop();//符号
					double a = opval.top();
					opval.pop();//数字a
					double b = opval.top();
					opval.pop();//数字b
					opval.push(calculate(b, theta, a));//推入计算结果
			}
		}
	}
	return opval.top();   //返回opval栈顶元素的值
}
 
int main()
{
	double ans = Answer();
	cout << ans;
	return 0;
}

/
// The program reads a string containing a mathematical expression and evaluates it using a stack-based algorithm. 
// The algorithm supports the operators +, -, *, / and parentheses. 
// The program outputs the result of the expression.
#include <iostream>
#include <stack>
#include <cstring>
using namespace std;

stack<int> num; // 存放数字的栈
stack<char> op; // 存放运算符的栈

int priority(char c) 
{ // 定义运算符优先级
    if (c == '+' || c == '-') 
		return 1;
    if (c == '*' || c == '/') 
		return 2;
    return 0;
}

int main() 
{
    string s;
    cin >> s;
    int len = s.size();
    for (int i = 0; i < len; i++) 
	{
        if (s[i] >= '0' && s[i] <= '9') 
		{ // 如果是数字
            int j = i, sum = 0;
            while (j < len && s[j] >= '0' && s[j] <= '9') 
			{ // 将整个数字读入
                sum = sum * 10 + s[j] - '0';
                j++;
            }
            num.push(sum); // 将数字压入栈
            i = j - 1; // 更新 i 的值
        } 
		else if (s[i] == '(') 
		{ // 如果是左括号
            op.push(s[i]); // 将左括号压入栈
        } 
		else if (s[i] == ')') 
		{ // 如果是右括号
            while (op.top() != '(') 
			{ // 不断取出栈顶元素,直到遇到左括号
                int b = num.top(); 
				num.pop(); // 取出数字
                int a = num.top(); 
				num.pop();
                if (op.top() == '+') 
					num.push(a + b); // 计算并将结果压入栈
                else if (op.top() == '-') 
					num.push(a - b);
                else if (op.top() == '*') 
					num.push(a * b);
                else 
					num.push(a / b);
                op.pop(); // 将运算符弹出栈
            }
            op.pop(); // 将左括号弹出栈
        } 
		else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') 
		{
			// 如果是运算符
            while (!op.empty() && op.top() != '(' && priority(op.top()) >= priority(s[i])) 
			{ // 如果栈不为空且栈顶不是左括号且栈顶运算符优先级不小于当前运算符
                int b = num.top(); 
					num.pop(); // 取出数字
                int a = num.top(); 
					num.pop();
                if (op.top() == '+') 
					num.push(a + b); // 计算并将结果压入栈
                else if (op.top() == '-') 
					num.push(a - b);
                else if (op.top() == '*') 
					num.push(a * b);
                else 
					num.push(a / b);
                op.pop(); // 将运算符弹出栈
            }
            op.push(s[i]); // 将当前运算符压入栈
    	}
	}
    while (!op.empty()) 
	{ // 如果还有运算符
        int b = num.top(); 
			num.pop(); // 取出数字
        int a = num.top(); 
			num.pop();
        if (op.top() == '+') 
			num.push(a + b); // 计算并将结果压入栈
        else if (op.top() == '-') 
			num.push(a - b);
        else if (op.top() == '*') 
			num.push(a * b);
        else 
			num.push(a / b);
        op.pop(); // 将运算符弹出栈
    }
    cout << num.top() << endl; // 输出最终结果
    return 0;
}
*/

8590 队列的应用——银行客户平均等待时间

/*用队列实现: 
某银行有一个客户办理业务站,在一天内随机地有客户到达,
设每位客户的业务办理时间是某个范围内的值。设只有一个窗口,一位业务人员,要求程序模拟统计在
一天时间内,所有客户的平均等待时间。
模拟数据按客户到达的先后顺序依次由键盘输入,对应每位客户有两个数据,到达时刻和需要办理业务的时间。
输入格式
第一行:一天内的客户总人数n
第二行:第一个客户的到达时刻和需要办理业务的时间
第三行:第二个客户的到达时刻和需要办理业务的时间
……
第n行:第n - 1个客户的到达时刻和需要办理业务的时间
第n + 1行:第n 个客户的到达时刻和需要办理业务的时间
输出格式
第一行:所有客户的平均等待时间(精确到小数点后2位)
输入样例
3
1 3
2 1
3 5
输出样例
1.33*/
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <queue>
#define OK 1
#define ERROR 0
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int QElemType;
#define MAXQSIZE 100 // 最大队列长度(对于循环队列,最大队列长度要减1)

using namespace std;

queue<QElemType> Q;

int main()
{
    double res = 0;//等待时间
    int leave;//离开时间
    int stay;//等待时间
    int n;
    scanf("%d",&n);//n个客户
    int a,b;
    scanf("%d %d",&a,&b);//第一个客户的到达时间和办理业务的时间
    Q.push(0);//第一个客户的等待时间为0
    leave=a+b;//离开时间=到达时间+办理时间
    for(int k=0; k<n-1; k++)
    {
        scanf("%d %d",&a,&b);//下一个客户的到达时间和办理时间
        stay=leave-a;//等待时间=上一个客户的离开时间-该客户的到达时间
        //这里需要注意stay小于0的情况
        if(stay<0)//如果上一个客户走了,下一个客户还没来
        {
            stay=0;//那么当前客户的等待时间为0
            leave=a+b;//离开时间=到达时间+办理时间
        }
        else
        {
            leave=leave+b;//否则,离开时间=上一个客户的离开时间+当前客户的办理时间
        }
        Q.push(stay);//把等待时间写进队列
    }
    double total = 0;
    if(Q.empty())
        printf("The Queue is Empty!");  //请填空
    else
    {
        while(!Q.empty())     //请填空
        {
            total+=Q.front();
            Q.pop();
        }
    }
    res=total/(n);
    printf("%.2f",res);
    return 0;
}

/*
#include <cstdio>
#include <iostream>
#include <cstdlib>
#define OK 1
#define ERROR 0
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int QElemType;
#define MAXQSIZE 100 // 最大队列长度(对于循环队列,最大队列长度要减1)
 
using namespace std;
 
typedef struct
{
    QElemType *base; // 初始化的动态分配存储空间
    int front; // 头指针,若队列不空,指向队列头元素
    int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue; 
 
Status InitQueue(SqQueue &Q)
{
// 构造一个空队列Q,该队列预定义大小为MAXQSIZE
// 请补全代码
    Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
    Q.front=Q.rear=0;
    return OK;
}
 
Status EnQueue(SqQueue &Q,QElemType e)
{
// 插入元素e为Q的新的队尾元素
// 请补全代码
    if((Q.rear+1)%MAXQSIZE==Q.front)
    {
        return ERROR;
    }
    Q.base[Q.rear]=e;
    Q.rear=(Q.rear+1)%MAXQSIZE;
    return OK;
}
 
Status DeQueue(SqQueue &Q, QElemType &e)
{
// 若队列不空, 则删除Q的队头元素, 用e返回其值, 并返回OK; 否则返回ERROR
// 请补全代码
    if(Q.rear==Q.front)
        return ERROR;
    e=Q.base[Q.front];
    Q.front=(Q.front+1)%MAXQSIZE;
    return OK;
}
 
Status GetHead(SqQueue Q, QElemType &e)
{
// 若队列不空,则用e返回队头元素,并返回OK,否则返回ERROR
// 请补全代码
    if(Q.rear==Q.front)
        return ERROR;
    e=Q.base[Q.front];
    return OK;
}
 
int QueueLength(SqQueue Q)
{
// 返回Q的元素个数
// 请补全代码
    return abs(Q.front-Q.rear);
}
 
double QueueTraverse(SqQueue Q)
{
// 若队列不空,则从队头到队尾依次输出各个队列元素,并返回OK;否则返回ERROR.
    int i;
    double total = 0;
    i=Q.front;
    if(i==Q.rear)
		printf("The Queue is Empty!");  //请填空
    else
    {
        while(i!=Q.rear)     //请填空
        {
            // cout << Q.base[i];
            total+=Q.base[i];
            i+=1;
        }
    }
    // cout << total << endl;
    return total;
}
 
int main()
{
    double res;//等待时间
    int leave;//离开时间
    int stay;//等待时间
    SqQueue Q;
    InitQueue(Q);//初始化
    int n;
    scanf("%d",&n);//n个客户
    int a,b;
    scanf("%d %d",&a,&b);//第一个客户的到达时间和办理业务的时间
    EnQueue(Q,0);//第一个客户的等待时间为0
    leave=a+b;//离开时间=到达时间+办理时间
    for(int k=0; k<n-1; k++)
    {
        scanf("%d %d",&a,&b);//下一个客户的到达时间和办理时间
        stay=leave-a;//等待时间=上一个客户的离开时间-该客户的到达时间
        //这里需要注意stay小于0的情况
        if(stay<0)//如果上一个客户走了,下一个客户还没来
        {
            stay=0;//那么当前客户的等待时间为0
            leave=a+b;//离开时间=到达时间+办理时间
        }
        else
        {
            leave=leave+b;//否则,离开时间=上一个客户的离开时间+当前客户的办理时间
        }
        EnQueue(Q,stay);//把等待时间写进队列
    }
    res=QueueTraverse(Q)/(n);
    printf("%.2f",res);
    return 0;
}*/

18937 阿克曼(Ackmann)函数

/*18937 阿克曼(Ackmann)函数
阿克曼(Ackmann)函数A(m,n)中,m,n定义域是非负整数(m≤3,n≤10),函数值定义为:
输入格式
输入m和n。
输出格式
函数值。
输入样例
2 3
输出样例
9
*/

#include <stdio.h>
#include <iostream>
using namespace std;
int Ackmann(int m,int n)
{
	if(m==0)
		return n+1;
	else if(n==0)
		return Ackmann(m-1,1);
	else return Ackmann(m-1,Ackmann(m,n-1));
}

int main()
{
	int m,n;
	cin>>m>>n;
	if(m>3||m<0||n>10||n<0)
		return 0;
	cout<<Ackmann(m,n);
	return 0;
}

18938 汉诺塔问题

/*18938 汉诺塔问题
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。
大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
由于条件是一次只能移动一个盘,且不允许大盘放在小盘上面,所以64个盘的移动次数是:18,446,744,073,709,551,615
这是一个天文数字,若每一微秒可能计算(并不输出)一次移动,那么也需要几乎一百万年。
我们仅能找出问题的解决方法并解决较小N值时的汉诺塔,但很难用计算机解决64层的汉诺塔。
假定圆盘从小到大编号为1, 2, ...
输入格式
输入为一个整数(小于20)后面跟三个单字符字符串。
整数为盘子的数目,后三个字符表示三个杆子的编号。
输出格式
输出每一步移动盘子的记录。一次移动一行。
每次移动的记录为例如 a->3->b 的形式,即把编号为3的盘子从****a杆移至b杆****。
输入样例
2 a b c
输出样例
a->1->c
a->2->b
c->1->b*/
#include <stdio.h>

using namespace std;

void hanoi(int n,char a,char b,char c)//****a杆移至b杆****
{
	if(n==1)
	{
		printf("%c->%d->%c\n",a,n,b);
	}
	else
	{
		hanoi(n-1,a,c,b);
		printf("%c->%d->%c\n",a,n,b);
		hanoi(n-1,c,b,a);
	}	
} 

int main()
{
	int n;
	char a,b,c;
	scanf("%d %c %c %c",&n,&a,&b,&c);
	if(n<=0||n>=20)
		return 0;
	hanoi(n,a,b,c);
	return 0;
}

汉诺塔问题 A-C

#include <iostream>
using namespace std;

int count = 0;

void hanoi(int n, char A, char B, char C) //****a杆移至c杆****
{
    if (n == 1) 
	{ // 如果只有一个盘子
        cout << "Move disk " << n << " from " << A << " to " << C << endl; 
		// 直接从A移动到C
        count++; // 移动次数加1
    } 
	else 
	{
        hanoi(n - 1, A, C, B); // 将n-1个盘子从A移动到B
        cout << "Move disk " << n << " from " << A << " to " << C << endl; 
		// 将第n个盘子从A移动到C
        count++; // 移动次数加1
        hanoi(n - 1, B, A, C); // 将n-1个盘子从B移动到C
    }
}
3
int main() 
{
    int n;
    cout << "Enter the number of disks: "; // 输入盘子数
    cin >> n;
    hanoi(n, 'A', 'B', 'C'); // 将n个盘子从A移动到C
    cout << "Total moves: " << count << endl; // 输出移动次数
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值