算法
中缀表达式
中缀 -> 前缀
【例】
//后缀表达方式
35,15,+,80,70,-,*,20,/
//中缀表达方式
(((35+15)*(80-70))/20)=25
//前缀表达方式
/,*,+,35,15,-,80,70, 20
【口算方法】
第一步:加括号
((a+(b*c))-(d+e))
第二步:移动符号
前缀:把运算符号移动到对应的括号前面:-( +(a *(bc)) +(de))
把括号去掉:-+a*bc+de
后缀:把运算符号移动到对应的括号后面:((a(bc)* )- (de)+ )-
把括号去掉:abc*-de+-
【编程实现(堆栈)】
中缀 -> 前缀
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
(2) 从右至左扫描中缀表达式;
(3) 遇到操作数时,将其压入S2;
(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) S1为空或 ")"——入栈;
(4-2) 优先级比栈顶运算符的较高或相等——入栈;
(4-3) 将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
(6) 重复步骤(2)至(5),直到表达式的最左边;
(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2元素并输出。
中缀 -> 后缀
(1) 初始化两个栈:运算符栈S1和储存中间结果的队列S2;
(2) 从左至右扫描中缀表达式;
(3) 遇到操作数时,将其压入S2;
(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) S1为空或栈顶"("——入栈;
(4-2) 优先级比栈顶高——入栈
(4-3) 比栈顶低或相同,弹出S1栈顶元素并压入到S2中,再次转到(4-1);
(6) 重复步骤(2)至(5),直到表达式的最右边;
(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2中元素并输出
参考博客:https://www.cnblogs.com/tech-bird/p/3971555.html
kmp
NEX数组
int nex[maxn] = { 0 };
//why? 在get_nex里面新建nex,然后作为Int*返回,段错误。为什么呢?int* nex=get_nex(t); printf("%d",nex[1]); 段错误。
void get_nex(string t)
{
memset(nex, 0, sizeof(int) * t.size());
int i = 0, j = -1;
nex[i] = j;
while (i < t.size() - 1)
{
if (j == -1 || t[i] == t[j])
nex[++i] = ++j;
else
j = nex[j];
}
}
int nex[100];
void GetNex(string a)
{
memset(nex, 0, sizeof(nex));
int i = 0, j = -1;
nex[0] = -1;
nex[1] = 0;
while (i < a.size())
{
if (j == -1 || a[i] == a[j])
nex[++i] = ++j;
else
j = nex[j];
}
}
NEXVAL数组
i是从[0,length],这个好理解。
j是next[i]
nexval数组求解方法:
nexval[0]=0;
其他:nexval[i]的值是看s[i]和s[j],即在i处的字母和next[i]处的字母一不一样,一样就相信next[i]处的next,不一样就相信i处的next。
int nexval[100];
void GetNexval(string a)
{
memset(nexval, 0, sizeof(nexval));
int i, j;
nexval[1] = 0;
for (i = 1; i < a.size(); i++)
{
if (a[i] == a[nex[i]])
nexval[i] = nexval[nex[i]];
else
nexval[i] = nex[i];
}
}
主函数
string a, b;
cin >> a >> b;
GetNex(b);
GetNexval(b);
int j = 0, k = 0, flag = 0;
while (j < a.size())
{
if (k == -1 || a[j] == b[k])
{
j++;
k++;
if (k >= b.size())
{
cout << j - b.size() << endl;
flag = 1;
break;
}
}
else
{
k = nex[k];
}
}
if (flag == 0)
cout << "not find!" << endl;
qsort在结构体中的运用
【注意】qsort函数包含在<stdlib.h>的头文件里
一、对int类型数组排序
int num[100];
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}
qsort(num,100,sizeof(num[0]),cmp);
二、对char类型数组排序(同int类型)
char word[50];
int cmp( const void *a , const void *b )
{
return *(char *)a - *(int *)b;
}
qsort(word,100,sizeof(word[0]),cmp);
三、对double类型数组排序
double in[100];
int cmp( const void *a , const void *b )
{
return *(double *)a > *(double *)b ? 1 : -1;
}
qsort(in,100,sizeof(in[0]),cmp);
四、对结构体一级排序
struct In
{
double data;
int other;
}s[100]
//按照data的值从小到大将结构体排序,关于结构体内的排序关键数据data的类型可以很多种,参考上面的例子写
int cmp( const void *a ,const void *b)
{
return (*(struct In *)a).data > (*(struct In *)b).data ? 1 : -1;
}
qsort(s,100,sizeof(s[0]),cmp);
五、对结构体二级排序
struct In
{
int x;
int y;
}s[100];
//按照x从小到大排序,当x相等时按照y从大到小排序
int cmp( const void *a , const void *b )
{
struct In *c = (In *)a;
struct In *d = (In *)b;
if(c->x != d->x) return c->x - d->x;
else return d->y - c->y;
}
qsort(s,100,sizeof(s[0]),cmp);
六、对结构体三级排序(都是从小到大)
#include<stdlib.h>
typedef struct item
{
int num,length,width;
};
int comp(const void *p1,const void *p2)
{
struct item *c=(item*)p1;
struct item *d=(item*)p2;
if(c->num!=d->num)
{
return d->num<c->num?1:-1;
}
else if(c->length!=d->length&&c->num==d->num)
return d->length<c->length?1:-1;
else return d->width<c->width?1:-1;
}
item ss[1200];
qsort(ss,n,sizeof(ss[0]),comp);
七、对字符串进行排序
struct In
{
int data;
char str[100];
}s[100];
//按照结构体中字符串str的字典顺序排序
int cmp ( const void *a , const void *b )
{
return strcmp( (*(In *)a)->str , (*(In *)b)->str );
}
qsort(s,100,sizeof(s[0]),cmp);
sort
头文件是<algorithm>
【函数】
sort(first,end,cmp);//排序
sort_stable(first,end,cmp);//稳定排序
partial_sort(first,last,search_last,cmp);//部分排序
stable_partition(first,last,search_last,cmp);//稳定部分排序
partial_sort_copy(a.first,a.last,b.first,b.last);//部分排序后拷贝
is_sorted(first,last);//判断一系列元素是否有序
is_sorted_until(first,last,cmp);返回第一个无序元素的指针
nth_element(first,sort_last,search_last);//默认求区间第k小
【nth_element要求第k大】
其实根本不是个问题,前面几个函数怎么处理就怎么处理(比较函数),只是想有个总结。
法一:转化成求第n-k+1小,此时下标应该是n - k。
法二:结尾cmp=greater<T>();
法三:使用逆序迭代器
【注意】比较函数规则与堆相反
cmp=greater<T>(),大;反之则小。
【比较函数】
法一:结构体外比较函数(优先队列)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
typedef struct node
{
int a, b;
node(int c, int d)
{
this->a = c;
this->b = d;
}
}node;
struct cmp
{
bool operator()(node o1, node o2)
{
if (o1.a == o2.a)
return o1.b > o2.b;
return o1.a > o2.a;
}
};
int main()
{
int i, j, k;
priority_queue<node,vector<node>,cmp>q;
q.push(node(2, 1));
q.push(node(2, 2));
q.push(node(1, 2));
q.push(node(1, 3));
while (q.size())
{
node t = q.top();
q.pop();
cout << t.a << " " << t.b << endl;
}
}
法二:结构体内比较函数
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
typedef struct node
{
int a, b;
node(int c, int d)
{
this->a = c;
this->b = d;
}
bool operator<(const node k) const
{
if (k.a == a)
return k.b < b;
return k.a < a;
}
}node;
int main()
{
int i, j, k;
priority_queue<node>q;
q.push(node(2, 1));
q.push(node(2, 2));
q.push(node(1, 2));
q.push(node(1, 3));
while (q.size())
{
node t = q.top();
q.pop();
cout << t.a << " " << t.b << endl;
}
}
法三:结构体内定义(vector使用sort函数)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
typedef struct node
{
int a, b;
node(int c, int d)
{
this->a = c;
this->b = d;
}
bool operator<(const node k) const
{
if (k.a == a)
return k.b > b;
return k.a > a;
}
}node;
int main()
{
int i, j, k;
vector<node>v;
v.push_back(node(2, 1));
v.push_back(node(2, 2));
v.push_back(node(1, 2));
v.push_back(node(1, 3));
sort(v.begin(), v.end());
for (int i = 0; i < v.size(); i++)
{
cout << v[i].a << " " << v[i].b << endl;
}
}
需要注意的是什么呢
三种方法的要达成一样的效果,第一种得是大于号,第二种operator得是小于号,第三种得是大于号。
不过其实不用记,做题的时候测试一下就行了。
gcd最大公约数:
递归的法一
int gcd(int x, int y)
{ if (y)
return gcd(y, x%y);
return x;
}
普通的法二
#最大公因数普通算法
int gcd(int m,int n)
{
if (m<n)
swap(m,n);
while(m%n)
{
int r=m%n;
m=n;
n=r;
}
return n;
}
感觉会忘的法三
int gcd(int x, int y)
{
while(y^=x^=y^=x%=y);
return x;
}
质因子拆分
法一
刚开始不知道为什么这样写,连个判断质数与否的函数都没有,怎么叫质因子拆分。
原因:他是从最小的2开始取余,把2取尽了,才继续往上。比如如果x=18能被6整除,6不是质数,为什么结果里没有6。因为x在循环i=2的时候就已经变成9,循环i=3的时候就已经变成9÷3÷3=1。不再有能被6除的余地了。
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
const int N = 100;
map<int, int> mp; //记录每个质因子的次数
int a[N]; //记录质因子
int index = 0;
void cal(int x)
{
for (int i = 2; i <= x / i; i++)
{
if (x % i == 0)
{
a[index++] = i;//记录因子
}
while (x % i == 0)
{
mp[i]++;//因子个数加一
x /= i;//x除以该因子
}
}
if (x > 1) a[index++] = x, mp[x]++;//可能最后一个没有算上,特殊判断一下
}
int main()
{
int n;
cin >> n;
cal(n);
for (int i = 0; i < index; i++)
{
cout << a[i] << " " << mp[a[i]] << endl;
}
}
法二
不用map也行,直接用a数组储存。a数组下标代表因子,值代表次数,非因子值初始化为0就行了。最后输出检索非0值。
//见文字说明,代码割了
参考:
https://blog.csdn.net/weixin_30911809/article/details/97949158?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163607889116780265486154%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163607889116780265486154&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-97949158.pc_search_result_control_group&utm_term=%E8%B4%A8%E5%9B%A0%E5%AD%90%E6%8B%86%E5%88%86&spm=1018.2226.3001.4187
https://blog.csdn.net/yang8627/article/details/83311114?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163607850816780366548729%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163607850816780366548729&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-83311114.pc_search_result_control_group&utm_term=%E6%9C%80%E5%A4%A7%E5%85%AC%E7%BA%A6%E6%95%B0gcd&spm=1018.2226.3001.4187

浙公网安备 33010602011771号