【笔记】数据结构04

文章目录


稀疏矩阵内容参考
强连通文章

稀疏矩阵压缩存储三元组表示

将非零元素所在的行、列以及它的值构成一个三元组(i,j,v),然后再按某种规律存储这些三元组

【行下标,列下标,值】

【i,j,v】

除了记录非零元素的10字节,还需要1字节空间用于记录矩阵的行数,列数及非零元素个数

c 复制代码
typedef struct{
	ElemType val;//元素值
	int i,//元素所在行
		j;//元素所在列
}TriMat;

稀疏矩阵转三元组

c 复制代码
//统计非0元个数
int countValNot0(ElemType A[][MaxSize],int m,int n){
	int count=0;
	for(int i=0;i<m;++i){
		for(int j=0;j<n;++j){
			if(A[i][j] != 0){
				count++;
			}
		}
	}
	return count;
}
c 复制代码
//稀疏矩阵转三元组表示
TriMat* matToTriMat(ElemType A[][MaxSize],int m,int n){
	//统计非0元个数
	int count = countValNot0(A,m,n);
	//申请存储空间
	TriMat *trimat = (TriMat*)malloc(sizeof(TriMat)*(count+1));

	//用三元组存储洗漱矩阵
	//下标0:记录非0元个数,原矩阵总行数,总列数
	triMat[0].val = count;
	triMat[0].i = m;
	triMat[0].j = n;

	int index = 1;
	for(int i=0;i<m;i++){
		for(int j=0;j<n;++j){
			if(A[i][j]!=0){
				triMat[index].val = A[i][j];
				triMat[index].j= j;
				triMat[index].i = i;
			}
		}
	}
	reuurn triMat;
}

表达式笔记参考
Begin to change
一只平平无奇

栈的应用

  1. 递归调用
  2. 子程序调用
  3. 表达式求值

前缀表达式

前缀表达式求值

1.从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,

2.弹出栈顶的两个数(先弹出左操作数,后弹出右操作数),用运算符对它们做相应的计算(栈顶元素 op 次顶元素),

3.并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果

c 复制代码
//两数的四则运算
double value(double op1,double op2,char ch){
    switch (ch) {
        case '+': return op1+op2;break;
        case '-': return op1-op2;break;
        case '*': return op1*op2;break;
        case '/': return (op1*1.0)/op2;break;
    }
}
//前缀表达式求值
double calculate(char* str){
	stack<char> s;
	//将表达式倒序;
	int i = 0;
	while(str[i]!='\0'){
		s.push(str[i]);
		++i;
	}
	stack<double> result;
	while(!s.empty()){
		char temp = s.top();
		s.pop();
		if(result.empty()||temp>='0'&&temp<='9'){
			result.push(temp-'0');
		}else{
			
		}
	}
}

中缀表达式

(1) 先计算括号内,后计算括号外;

(2) 在无括号或同层括号内,先乘除运算,后加减运算,即乘除运算的优先级高于加减运算的优先级;

(3) 同一优先级运算,从左向右依次进行。

  1. 设置两个栈,一个数字栈numStack,用于存储表达式中涉及到的数字,operatorStack用于存储表达式中涉及到的运算符
  2. 逐个字符分析表达式,直到全部字符都已分析完
    • 若当前字符为数字,则判断是否后续字符也为数字,若为数字则进行拼接,直到下一个数字为运算符为止,此时将拼接好的多位数字压入数字栈中。(如果已经是最后一个字符则直接压入栈)
    • 若当前字符为算数运算符
      1. 如果运算符栈为空则直接压入栈中
      2. 运算符不为空,则对运算符优先级进行判断
        1. 如果当前运算符优先级大于等于栈顶运算符则直接压入栈中
        2. 如果优先级低于栈顶运算符,则,从数字栈中取出两个数据,将当前栈顶运算符弹出进行运算,将结果压入数字栈中,将当前运算符压入运算符栈中。
  3. 此时数字与运算符都已经压入栈中,此时运算符栈中均为优先级相同的运算符,需要进行收尾操作,如果运算符栈不为空,则依次从数字栈中弹出两个数据,与当前栈顶的运算符进行运算。将结果压入数字栈中。最后数字栈中的数字就是所要求解的结果
c 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#define maximum 100000
 
typedef struct//数字栈 
{
    float data[maximum];
    int top;
}number;
 
typedef struct//字符栈 
{
    char data[maximum];
    int top;
}sign;
 
void InitNumber(number *stack);//初始化数字栈 
void GetTopNumber(number stack, float *e);//获取栈顶元素 
void PushNumber(number *stack, float e);//进栈 
void PopNumber(number *stack, float *e);//出栈 
 
void InitSign(sign *stack);
void GetTopSign(sign stack, char *e);
void PushSign(sign *stack, char e);
void PopSign(sign *stack, char *e);
 
void Calculate(number *stack, char e);
 
number Num;
sign sig;
char expression[maximum];
	
int main()
{
    gets(expression);
    int length;
    length=strlen(expression);
    int i;
    float en,n;
    char es;
    InitNumber(&Num);
    InitSign(&sig);
    for (i=0;i<length;i++)
    {
        if(expression[i]>='0'&&expression[i]<='9')
        {
            n=expression[i]-'0';//字符型转换为整型 
            while (expression[i+1]!='\0')
            {
                if (expression[i+1]>='0'&&expression[i+1]<='9') 
                {
                    n=n*10+expression[i+1]-'0';
                    ++i;
                }
                else break;
            }
            PushNumber(&Num,n);
        }
        else if (expression[i]=='+'||expression[i]=='-'||expression[i]=='*'||expression[i]=='/'||expression[i]=='^'||expression[i]=='('||expression[i]==')')
        {
            switch (expression[i])
            {
            case '+':
                if(sig.data[sig.top-1]!='+'&&sig.data[sig.top-1]!='-'&&sig.data[sig.top-1]!='*'&&sig.data[sig.top-1]!='/'&&sig.data[sig.top-1]!='^')
                //与栈顶元素的优先级相比较, 高于时入栈,此处判断是否入栈。 
                    PushSign(&sig,'+');
                else
                {
                    while (sig.top>0&&sig.data[sig.top-1]!='(')//如果栈不为空切不为左括号,则出栈 
                    {
                        PopSign(&sig,&es);
                        Calculate(&Num,es);
                    }
                    PushSign(&sig,'+');
                }
                break;
            case '-':
                if(sig.data[sig.top-1]!='+'&&sig.data[sig.top-1]!='-'&&sig.data[sig.top-1]!='*'&&sig.data[sig.top-1]!='/'&&sig.data[sig.top-1]!='^')
                    PushSign(&sig,'-');
                else
                {
                    while (sig.top>0&&sig.data[sig.top-1]!='(')
                    {
                        PopSign(&sig,&es);
                        Calculate(&Num,es);
                    }
                    PushSign(&sig,'-');
                }
                break;
            case '*':
                if(sig.data[sig.top-1]!='*'&&sig.data[sig.top-1]!='/'&&sig.data[sig.top-1]!='^')
                    PushSign(&sig,'*');
                else
                {
                    while (sig.top>0&&sig.data[sig.top-1]!='(')
                    {
                        PopSign(&sig,&es);
                        Calculate(&Num,es);
                    }
                    PushSign(&sig,'*');
                }
                break;
            case '/':
                if(sig.data[sig.top-1]!='*'&&sig.data[sig.top-1]!='/'&&sig.data[sig.top-1]!='^')
                    PushSign(&sig,'/');
                else
                {
                    while (sig.top>0&&sig.data[sig.top-1]!='(')
                    {
                        PopSign(&sig,&es);
                        Calculate(&Num,es);
                    }
                    PushSign(&sig,'/');
                }
                break;
            case '^':
                if(sig.data[sig.top-1]!='^')
                    PushSign(&sig,'^');
                else
                {
                    while (sig.top>0&&sig.data[sig.top-1]!='(')
                    {
                        PopSign(&sig,&es);
                        Calculate(&Num,es);
                    }
                    PushSign(&sig,'^');
                }
            case '(':
                PushSign(&sig,'(');
                break;
            case ')':
                while (sig.data[sig.top-1]!='(')
                {
                    PopSign(&sig,&es);
                    Calculate(&Num,es);
                }
                PopSign(&sig,&es);
            }
        }
    }
    while (sig.top>0)
    {
        PopSign(&sig,&es);
        Calculate(&Num,es);
    }
    GetTopNumber(Num,&en);
    printf("%.0f\n",en);
    return 0;
}
 
void InitNumber(number *stack)
{
    stack->top=0;
}
 
void GetTopNumber(number stack, float *e)
{
    if(stack.top==0) return;
    else *e=stack.data[stack.top-1];
}
 
void PushNumber(number *stack, float e)
{
    if(stack->top>=maximum) return;
    else stack->data[stack->top++]=e;
}
 
void PopNumber(number *stack, float *e)
{
    if(stack->top==0) return;
    else *e=stack->data[--stack->top];
}
 
void InitSign(sign *stack)
{
    stack->top=0;
}
 
void GetTopSign(sign stack, char *e)
{
    if(stack.top==0) return;
    else *e=stack.data[stack.top-1];
}
 
void PushSign(sign *stack, char e)
{
    if(stack->top>=maximum) return;//栈满 
    else 
	{
		stack->data[stack->top]=e;
		stack->top++;
	}
}
 
void PopSign(sign *stack, char *e)
{
    if(stack->top==0) return;
    else *e=stack->data[--stack->top];
}
 
void Calculate(number *stack, char e)// 计算结果 
{
    float num1,num2,result;
    PopNumber(stack, &num2);
    PopNumber(stack, &num1);
    switch (e)
    {
        case '+':
            result=num1+num2;
            PushNumber(stack,result);
            break;
        case '-':
            result=num1-num2;
            PushNumber(stack,result);
            break;
        case '*':
            result=num1*num2;
            PushNumber(stack,result);
            break;
        case '/':
            if (num2==0) printf("表达式错误!");
            else
            {
                result=num1/num2;
                PushNumber(stack,result);
                break;
            }
        case '^':
            result=pow(num1,num2);
            PushNumber(stack,result);
            break;
    }
}

后缀表达式

c 复制代码
//规定优先级
int level(char s){
	if(s=='+'||s=='-')
		return 1;
	else if(s=='*'||s=='/')
		return 2;
	return 3;
}
c 复制代码
//四则运算
double value(double op1,double op2,char ch){
	switch(ch){
		case '+':return op1+op2;break;
		case '-':return op1-op2;break;
		case '*':return op1*op2;break;
		
	}
}
c 复制代码
//中缀表达式求职
double calculate_infix(char* str){
	//数字栈
	stack<double> number_stack;
	//符号栈
	stack<char> symbol_stack;
	for(int i=0;str[i]!='\0';++i){
		//如果扫描到数字
		if(number_stack.empty()||str[i]>='0'&&str[i]<='9'){number_stack.push(str[i]-'0');}
		//------------------------如果扫描到运算符-------------------
		else if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'){
					   
		//如果当前运算符的优先级>栈顶符号优先级,则直接进栈
		if(symbol_stack.empty()||level(str[i])>level(symbol_stack.top()))
			symbol_stack.push(str[i]);
			//如果当前运算符的优先级<=栈顶符号的优先级
		else{
		  //依次弹出优先级高于或等于当前符号的所有符号,并同时弹出数字栈中的两个数字作为操作数。注意先后顺序。
		  	while(!symbol_stack.empty()&&level(symbol_stack.top())>=level(str[i])){
				double op2 = number_stack.top();
				number_stack.pop();
				double op1 = number_stack.top();
				number_stack.pop();
				//将计算结果压入数字栈
				number_stack.push(value(op1,op2,symbol_stack.top()));
				//符号出栈
				symbol_stack.pop();
			}
			symbol_stack.push(str[i]);
			//最后把当前符号入栈
		}
			
		}
		//-----------------如果扫描到界限符-------------------
		else{
			if(str[i]=='(')
                symbol_stack.push(str[i]);
            else {
				 //遇到右括号')'依次弹出符号栈内运算符,和数字栈内的两个运算符,做计算,直到遇到左括号'('为止
				  while(symbol_stack.top()!='('){
                    double op2=number_stack.top();
                    number_stack.pop();
                    double op1=number_stack.top();
                    number_stack.pop();
                    //将计算结果压入数字栈
                    number_stack.push(value(op1,op2,symbol_stack.top()));
                    //符号出栈
                    symbol_stack.pop();
                }
                symbol_stack.pop();
			}
		}
	}
	 //将符号栈所有运算符出栈,与数字栈剩余数字做运算
    while(!symbol_stack.empty()){
        double op2=number_stack.top();
        number_stack.pop();
        double op1=number_stack.top();
        number_stack.pop();
        //将计算结果压入数字栈
        number_stack.push(value(op1,op2,symbol_stack.top()));
        //符号出栈
        symbol_stack.pop();
    }
    return number_stack.top();
}

相关推荐
cuisidong19977 分钟前
5G学习笔记三之物理层、数据链路层、RRC层协议
笔记·学习·5g
乌恩大侠9 分钟前
5G周边知识笔记
笔记·5g
咔叽布吉1 小时前
【论文阅读笔记】CamoFormer: Masked Separable Attention for Camouflaged Object Detection
论文阅读·笔记·目标检测
johnny2331 小时前
《大模型应用开发极简入门》笔记
笔记·chatgpt
亦枫Leonlew1 小时前
微积分复习笔记 Calculus Volume 1 - 4.7 Applied Optimization Problems
笔记·数学·微积分·1024程序员节
小肥象不是小飞象2 小时前
(六千字心得笔记)零基础C语言入门第八课——函数(上)
c语言·开发语言·笔记·1024程序员节
星LZX2 小时前
WireShark入门学习笔记
笔记·学习·wireshark
努力变厉害的小超超3 小时前
ArkTS中的组件基础、状态管理、样式处理、class语法以及界面渲染
笔记·鸿蒙
wheeldown7 小时前
【数据结构】选择排序
数据结构·算法·排序算法
aloha_7898 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot