文章目录
稀疏矩阵内容参考
强连通文章
稀疏矩阵压缩存储三元组表示
将非零元素所在的行、列以及它的值构成一个三元组(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.弹出栈顶的两个数(先弹出左操作数,后弹出右操作数),用运算符对它们做相应的计算(栈顶元素 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) 同一优先级运算,从左向右依次进行。
- 设置两个栈,一个数字栈numStack,用于存储表达式中涉及到的数字,operatorStack用于存储表达式中涉及到的运算符
- 逐个字符分析表达式,直到全部字符都已分析完
- 若当前字符为数字,则判断是否后续字符也为数字,若为数字则进行拼接,直到下一个数字为运算符为止,此时将拼接好的多位数字压入数字栈中。(如果已经是最后一个字符则直接压入栈)
- 若当前字符为算数运算符
- 如果运算符栈为空则直接压入栈中
- 运算符不为空,则对运算符优先级进行判断
- 如果当前运算符优先级大于等于栈顶运算符则直接压入栈中
- 如果优先级低于栈顶运算符,则,从数字栈中取出两个数据,将当前栈顶运算符弹出进行运算,将结果压入数字栈中,将当前运算符压入运算符栈中。
- 此时数字与运算符都已经压入栈中,此时运算符栈中均为优先级相同的运算符,需要进行收尾操作,如果运算符栈不为空,则依次从数字栈中弹出两个数据,与当前栈顶的运算符进行运算。将结果压入数字栈中。最后数字栈中的数字就是所要求解的结果
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();
}