算法

中缀表达式

中缀 -> 前缀

【例】

//后缀表达方式
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/qq_44797733/article/details/106093658?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_utm_term~default-0.no_search_link&spm=1001.2101.3001.4242.1

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

 

posted @ 2022-10-26 19:39  fw_48925  阅读(123)  评论(0)    收藏  举报