数据结构---第二章案例分析

案例分析与实现

数制的转换

分析:将一个十进制整数 N 转换为八进制数时,在计算过程中,把 N 与 8 求余得到的八进制数的各位依次进栈,计算完毕后将栈中的八进制数依次出栈输出,输出结果就是待求得的八进制数。

算法步骤
  • 初始化一个空栈S

  • 当十进制数N非零时, 循环执行以下操作:

    1. 把 N 与 8 求余得到的八进制数压入栈 S;
    2. N更新为N与8的商。
  • 当栈S 非空时,循环执行以下操作

    1. 弹出栈顶元素e;
    2. 输出 e。
#include<iostream>
using namespace std;
#define  MAXSIZE  100
typedef struct
{
	int* base;
	int* top;
	int  stacksize;
}SqStack;

void InitStack(SqStack& S)
{
	S.base = new int[MAXSIZE];
	if (!S.base) exit;
	S.top = S.base;
	S.stacksize = MAXSIZE;
}

int DestroyStack(SqStack& S)
{
	delete S.base;
	S.base = NULL;
	S.top = NULL;
	S.stacksize = 0;
	return 0;
}

int StackEmpty(SqStack S)
{
	if (S.top == S.base)
		return 1;
	else
		return 0;
}

int Push(SqStack& S, int e)
{
	if (S.top - S.base == S.stacksize) return 0;
	*S.top= e;
	S.top++;
	return 1;
}

int Pop(SqStack& S, int& e)
{
	if (S.top == S.base)
		return 0;
	S.top--;
	e = *S.top;
	return 1;
}

void conversion()
{
	int i;
	int e;
	SqStack s;
	InitStack(s);
	cout<<"请输入一个整数:";
	 cin>> i;
	while (i)
	{
		Push(s, i% 8);
		i = i/ 8;
	}
	cout<<"转换后的八进制为:";
	while (!StackEmpty(s))
	{
		Pop(s, e);
		cout << e;
	}
	cout << endl;
	DestroyStack(s);
}

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

image-20220119141028074

括号匹配的检验

分析:借助一个栈, 每当读入一个左括号, 则直接入栈,等待相匹配的同类右括号;每当读入一个右括号,若与当前栈顶的左括号类型相同, 则二者匹配,将栈顶的左括号出栈,直到表达式扫描完毕,还要考虑括号不匹配出错的情况。

算法步骤
  • 初始化一个空栈S。

  • 设置一标记性变量 flag, 用来标记匹配结果以控制循环及返回结果, 1表示正确匹配, 0表示错误匹配, flag 初值为 1。

  • 扫描表达式,依次读入字符ch, 如果表达式没有扫描完毕或 flag 非零, 则循环执行以下操作:

    1. 若 ch是左括号"[" 或"("' 则将其压入栈;
    2. 若 ch是右括号")"' 则根据当前栈顶元素的值分情况考虑:若栈非空且栈顶元素是 "(",则正确匹配, 否则错误匹配, flag 置为 0;
    3. 若 ch是右括号"]"' 则根据当前栈顶元素的值分情况考虑:若栈非空且栈顶元素是"["'则正确匹配, 否则错误匹配, flag 置为 0。
  • 退出循环后, 如果栈空且 flag 值为1则匹配成功, 返回 true, 否则返回 false。

    #include<iostream>
    using namespace std;
    #define TRUE 1
    #define FALSE 0
    #define OK 1
    #define ERROR 0
    #define MAXSIZE 100
    typedef int Status; 
    typedef char SElemType;
    typedef struct 
        {
            SElemType* base;
            SElemType* top;
            int stacksize;
        }SqStack;
    
    Status InitStack(SqStack &S)
        {
            S.base = new char[MAXSIZE];
            if (!S.base)exit;
            S.top = S.base;
            S.stacksize = MAXSIZE;
            return OK;
        }
    
    Status DestroyStack(SqStack &S)
        {
            delete S.base;
            S.base = NULL;
            S.top = NULL;
            S.stacksize = 0;
            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) return 0;
            *S.top = e;
            S.top++;
            return OK;
    Status GetTop(SqStack S, SElemType* e)
        {
        
            if (S.top == S.base)
            {
                return FALSE;
            }
            else
            {
                *e = *(S.top - 1);
                return OK;
            }
        }
    Status Pop(SqStack &S, SElemType &e)
        {
            
            if (S.top == S.base)
            {
                cout << "栈为空";
                return ERROR;
            }
            S.top--;
            e = *S.top;
            return OK;
        }
    
    Status StackTraverse(const SqStack * S)
        {
            SElemType* p = S->base;
            if (S->base == S->top)
            {
                cout << "栈为空";
                return FALSE;
            }
            while (p != S->top)
            {
                cout<< *p++;
            }
            cout << endl;
            return OK;
        }
    
    Status BracketMatch(SqStack &S, const char* string)
    {
            const char* flag = string;
            SElemType e;
            InitStack(S);
            while (*flag != '\0')
            {
                switch (*flag)
                {
                case '(':
                case '[':
                case '{':
                    Push(S, *flag);
                    break;
                case ')':
                    if (FALSE == GetTop(S, &e))
                        return FALSE;
                    if (e == '(')
                    {
                        if (ERROR == Pop(S, e))
                            return FALSE;
                    }
                    else
                        return FALSE;
                    break;
                case ']':
                    if (FALSE == GetTop(S, &e))
                        return FALSE;
                    if (e == '[')
                    {
                        if (ERROR == Pop(S, e))
                            return FALSE;
                    }
                    else
                        return FALSE;
                    break;
                case '}':
                    if (FALSE == GetTop(S, &e))
                        return FALSE;
                    if (e == '{')
                    {
                        if (ERROR == Pop(S, e))
                            return FALSE;
                    }
                    else
                        return FALSE;
                    break;
                default:;
                }
                flag++;
            }
            if (!StackEmpty(S)) 
                return FALSE;
            return TRUE;
        }
     int main()
        {
            char String[6];
            SqStack stack;
            if (!String)
            {
                cout<<"分配内存失败."<<'\n';
                return 0;
            }
            while (1)
            {
                cout<<"请输入一行含括号的表达式(输入#退出):";
                for (int i = 0; i < 5; i++)
                    cin >> String[i];
                if (String[0] == '#')
                    break;
                if (TRUE == BracketMatch(stack, String))
                {
                    cout << "匹配成功!" << endl;
                }
                else
                {
                    cout << "匹配失败!" << endl;
                }
            }
            return 0;
        }
    

    image-20220119154735374

时间和空间复杂度都是O(n),从头到尾依次扫描每个字符,并存储"[""(",匹配成功则出栈,所以栈所占空间不超过n

表达式求值

分析:任何一个表达式都是由操作数(常数和被说明为变量或常量的标识符)、运算符(算术运算符、关系运算符和逻辑运算符 )、界限符(左右括号和表达式结束符)。其中运算符和界限符统称算符,按照运算规则,先乘除后加减,从左算到右,先括号内再括号外来进行运算,这里为了实现优先算法可以使用两个工作栈,一个称做OPTR,用以寄存运算符;另一个称作OPND, 用以寄存操作数或运算结果。

算法步骤
  • 初始化OPTR栈和OPND栈,将表达式起始符"#"压入OPTR栈。

  • 扫描表达式,读入第一个字符ch, 如果表达式没有扫描完毕至"#"或OPTR的栈顶元素不为"#"时,则循环执行以下操作:

    1. 若ch不 是运算符,则压入OPND栈,读入下一字符ch;
    2. 若ch是运算符,则根据OPTR的栈顶元素和ch的优先级比较结果,做不同的处理:
      • 若是小于,则ch压入OPTR栈,读入下一字符ch;
      • 若是大于,则弹出OPTR栈顶的运算符,从OPND栈弹出两个数, 进行相应运算,结果压入OPND栈;
      • 若是等于,则OPTR的栈顶元素是 "(" 且ch是")"'这时弹出OPTR栈顶的 "(",相当于括号匹配功,然后读入下一字符ch。
  • OPND栈顶元素即为表达式求值结果,返回此元素。

Status In(ElemType c) //判断输入的算符是否符合规则
{
	if (c == '+' || c == '-' || c == '*' || c == '/' || c == '#' || c == '(' || c == ')' || c == '[' || c == ']')
		return 1;
	else
		return 0;
}
char Compare(ElemType a, ElemType b) //判断运算符栈的栈顶元素a和读入元素b的优先级 
{
	if (a == '+' || a == '-') 
	{
		if (b == '+' || b == '-' || b == '>' || b == '#' || b == ')' || b == ']')
			return '>';
		else return '<';
	}
	if (a == '*' || a == '/') 
	{
		if (b == '(' || b == '[')
			return '<';
		else return '>';
	}
	if (a == '(') 
	{
		if (b == ')')
			return '=';
		else return '<';
	}
	if (a == '[') 
	{
		if (b == ']')
			return '=';
		else return '<';
	}
	if (a == '#') 
	{
		if (b == '#')
			return '=';
		else return '<';
	}
}
ElemType Operate(ElemType a, ElemType x, ElemType b) //进行运算的函数 
{
	switch (x) {
	case '+':
		return a + b;
	case '-':
		return a - b;
	case '*':
		return a * b;
	case '/':
		return a / b;
	}
}

时间空间复杂度均为O(n),从头到尾依次扫描,字符串的长度为n,将操作数和算符依次入栈,因为还会出栈,两个栈所占空间长度不会超过n

舞伴问题

分析:先入队的男士或女士先出队配成舞伴,因此设置两个队列分别存放男士和女士入队者。用数组记录男士和女士,然后依次扫描数组元素,根据性别决定是进入男队还是女队,构造完成后,将两队队头元素出队配成舞伴直至某队列为空,若有队伍剩余则作为下一轮第一个可获得舞伴者。

算法步骤
  • 初始化 Mdancers 队列和 Fdancers 队列。
  • 反复循环, 依次将跳舞者根据其性别插入 Mdancers 队列或 Fdancers 队列。
  • 当 Mdancers 队列和 Fdancers 队列均为非空时, 反复循环, 依次输出男女舞伴的姓名。
  • 如果 Mdancers 队列为空而 Fdancers 队列非空, 则输出 Fdancers 队列的队头女士的姓名。
  • 如果 Fdancers 队列为空而 Mdancers 队列非空, 则输出 Mdancers 队列的队头男士的姓名。
#include<iostream>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAXQSIZE 100
typedef int Status;
typedef char QElemType;
typedef struct
{
	char name[20];     
	char sex;          
}Person;

typedef struct
{
	Person* base;//队列中数据元素类型为Person 
	int front;            
	int rear;             
}SqQueue;

Status InitQueue(SqQueue& Q)
{
	Q.base = new Person[MAXQSIZE];
	if (!Q.base) exit; 
	Q.front = Q.rear = NULL;
	return 1;
}

Status EnQueue(SqQueue& Q, Person e)
{
	if ((Q.rear + 1) % MAXQSIZE == Q.front)
		return 0; 
	Q.base[Q.rear] = e; 
	Q.rear = (Q.rear + 1) % MAXQSIZE;
	return 1;
}

Status DeQueue(SqQueue& Q, Person& e) 
{
	if (Q.front == Q.rear) return ERROR; 
	e = Q.base[Q.front]; 
	Q.front = (Q.front + 1) % MAXQSIZE; 
	return 1;
} 

Person GetHead(SqQueue Q)  
{
	if (Q.front != Q.rear)        
		return Q.base[Q.front]; 
}

Status QueueEmpty(SqQueue& Q)
{
	if (Q.front == Q.rear) return OK;
	else return ERROR;
}

void DancePartner(Person dancer[], int num)//结构数组danccer中存放跳舞的男女,num是跳舞的人数 
{
	Person p;
	SqQueue Mdancers, Fdancers;
	InitQueue(Mdancers);          
	InitQueue(Fdancers);         
	for (int i = 0; i < num; i++)      
	{
		p = dancer[i];
		if (p.sex == 'F') EnQueue(Fdancers, p);  
		else EnQueue(Mdancers, p);           
	}
	cout << "The dancing partners are:\n";
	while (!QueueEmpty(Fdancers) && !QueueEmpty(Mdancers))
	{
		DeQueue(Fdancers, p);     
		cout << p.name<<"-";
		DeQueue(Mdancers, p);     
		cout << p.name<<endl;     
	}
	if (!QueueEmpty(Fdancers))  
	{
		p = GetHead(Fdancers);   
		cout << "The first woman to get a partner is:" << p.name << endl;
	}
	else if (!QueueEmpty(Mdancers))
	{
		p = GetHead(Mdancers);  
		cout << "The first man to get a partner is:" << p.name << endl;
	}
}

int main()
{
	SqQueue Mdancers, Fdancers;
	int n;
	Person dancer[MAXQSIZE];
	cout << "请输入跳舞的人数:";
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cout << "请输入第" << i << "舞者的名字:" << endl;
		cin >> dancer[i - 1].name;
		cout << "请输入第" << i << "个人的性别(F/M):" << endl;
		cin >> dancer[i - 1].sex;
		while (dancer[i - 1].sex != 'F' && dancer[i - 1].sex != 'M')
		{
			cout << "输入错误,请重新输入:\n";
			cout << dancer[i - 1].sex;
			cout << "请输入第" << i << "个人的性别(F/M):" << endl;
			cin >> dancer[i - 1].sex;
			break;
		}
	}
	DancePartner(dancer, n);
	return 0;
}

image-20220119170246120

时间空间复杂度均为O(n),从头到尾依次扫描,跳舞总人数为n,各自分别或进入女队或进入男队,两者之和不会超过n。

posted on 2022-02-06 20:05  眉目作山河  阅读(150)  评论(0编辑  收藏  举报

导航