yxc算法课程笔记

这里写目录标题

    • 快速排序
    • 堆排序
    • 归并排序
    • 大数加法
    • 大数减法
    • 大数乘法
    • 大数除法
    • 二维前缀和
    • 二维差分
    • 双指针求最长不重复子串
    • 区间合并
    • kmp算法
    • trie树插入并查询单词
    • 并查集实现1.判断两个元素是否属于同一个集合2.将两个集合合并
    • DFS和BFS
    • DFS实现全排列
    • DFS实现八皇后
    • BFS求走出迷宫的最短路径(左上走到右下)
  • 质数
    • 质数的判定:o(sqrt(n)复杂度)
    • 短除法
    • 给一串数,筛选其中的质数
    • 快速幂
      • 简单快速幂

快速排序

#include 
void quicksort(int *a,int begin,int end){
	if(begin>end) return;
		int i=begin,j=end,x=a[begin],k;
		while(i<j){
			while(i<j&&a[j]>=x){
				j--;
			}
			while(i<j&&a[i]<=x){
				i++;
			}
			k=a[i];
			a[i]=a[j];
			a[j]=k;
		}
		a[begin]=a[i];
		a[i]=x;
		quicksort(a,0,i-1);
		quicksort(a,i+1,end);
	
}
//10 1 1239 10283 018923 8102 8 90 8 11 2
int main(){
	int n,a[1000];
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	quicksort(a,0,n-1);
	for(int i=0;i<n;i++)
	{
		printf("%d ",a[i]);
	}
}

堆排序

#include 
#include 
int a[1000];
int n,size;
void down(int x){
	int t=x;
	if(a[t]>a[2*x]&&2*x<=n) t=2*x;
	if(a[t]>a[2*x+1]&&(2*x+1)<=n) t=2*x+1; 
	if(t!=x){
		int k;
		k=a[t];
		a[t]=a[x];
		a[x]=k;
		down(t);
	}
}
//5 1 2 3 1 2
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}//输入 
	for(int i=n/2;i>0;i--){
		down(i);
	}//建初堆
	int size=n;
	while(size--){
		printf("%d ",a[1]); 
		 a[1]=a[n];
		 n--;
		 down(1);
	}//堆排序 
} 

归并排序

#include 
void mergesort(int *a,int begin,int end){
	if(begin>=end) return ;
	int mid=(begin+end)/2;
	int tem[1000];//容器 
	mergesort(a,begin,mid);
	mergesort(a,mid+1,end);
	int i=begin,j=mid+1,k=0;
	while(i<=mid&&j<=end){
		if(a[i]<=a[j]){
			tem[k++]=a[i++];
		}	
		else {
			tem[k++]=a[j++];
		}
	} 
	while(i<=mid){
		tem[k++]=a[i++];
	} 
	while(j<=end){
		tem[k++]=a[j++];
	}
	for(i=begin,j=0;i<=end;i++,j++){
		a[i]=tem[j];
	}
}
//10 1 1239 1028  12333 89089 97987  655 656 56 8
int main(){
	int n,a[1000];
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	mergesort(a,0,n-1);
	for(int i=0;i<n;i++)
	{
		printf("%d ",a[i]);
	}
}

大数加法

#include 
#include 
int main(){
	char a[100];
	char b[100];
	int c[100];
	scanf("%s",a);
	scanf("%s",b);
	int count=0, flag=0;
	char s;
	for(int i=0, j=strlen(a)-1;i<=j;i++,j--){
		s=a[i];
		a[i]=a[j];
		a[j]=s;
	}
	for(int i=0, j=strlen(b)-1;i<=j;i++,j--){
		s=b[i];
		b[i]=b[j];
		b[j]=s;
	}	
	for(int i=0;i<strlen(a)||i<strlen(b);i++){
		if(i<strlen(a)) flag=flag+(a[i]-'0');
		if(i<strlen(b)) flag=flag+(b[i]-'0');
		if(flag>=10){
			c[i]=flag%10;
			flag=1;		
		}
		if(flag<10) {
			c[i]=flag;
			flag=0;	
		}
		count++;
	}
	for(int i=count-1;i>=0;i--){
		printf("%d",c[i]);
	}
}

大数减法

大数减法
#include 
#include 
int  compare(char a[],char b[]){
	int i=0;
	if(strlen(a)>strlen(b)){
		return 1;
	}
	if(strlen(a)<strlen(b)){
		return 0;
	}
	if(strlen(a)==strlen(b)){
		while(i<strlen(a)){
			if(a[i]>b[i]){
				return 1;
			}
			if(a[i]<b[i]){
				return 0;
			}
			if(a[i]==b[i]){
				i++;
			}
		}
		return 1; 
	}
}
void div(char *a,char *b,int *c)
{
	int flag=0,i=0;
	while(i<strlen(a)){
		if(i<strlen(b)){
			flag=a[i]-flag;
			flag-=b[i];
			if(flag<0){
				flag+=10;
				c[i]=flag%10;
				flag=1;
				i++;
			}
			else{
				c[i]=flag;
				flag=0;
				i++;
			}
		}
		else{
			if(flag==0){
				c[i]=a[i]-'0';
				i++;
			}
			if(flag==1){
				c[i]=a[i]-flag-'0';
				flag--;
				i++;
			}
		}
	}
}
int main(){
	char a[1000];
	char b[1000];
	int c[1000];
	int k;
	memset(a,0,1000);
	memset(b,0,1000);
	memset(c,0,1000);
	scanf("%s",a);
	scanf("%s",b);
	for(int i=0,j=strlen(a)-1;i<j;i++,j--){
		k=a[i];
		a[i]=a[j];
		a[j]=k;
	}
	for(int i=0,j=strlen(b)-1;i<j;i++,j--){
		k=b[i];
		b[i]=b[j];
		b[j]=k;
	}
	if(compare(a,b)==1){
		div(a,b,c);
		int flag2=0;
		for(int i=strlen(a)-1;i>=0;i--){
			if(c[i]!=0){
				flag2=1;
			}
			if(flag2==0){
				
			}
			if(flag2==1)
			{
				printf("%d",c[i]);
			}
		}
	}
	else{
		div(b,a,c);
		printf("-");
		int flag2=0;
		for(int i=strlen(b)-1;i>=0;i--){
			
				if(c[i]!=0){
				flag2=1;
			}
			if(flag2==0){
				
			}
			if(flag2==1)
			{
				printf("%d",c[i]);
			}
		}
	}
}

大数乘法

大数乘法
#include 
#include 

void mul(char *a,int x,int *b)
{
	int flag=0,i=0;
	while(i<strlen(a)){ 
			flag+=(a[i]-'0')*x;
			if(flag>=10){
				b[i]=flag%10;
				flag/=10;
				i++;
			}
			else{
				b[i]=flag;
				flag=0;
				i++;
			}
		}
	if(flag!=0){
		b[strlen(a)]=flag;
		for(int i=strlen(a);i>=0;i--){
			printf("%d",b[i]);
		}	
	}
	else{
		for(int i=strlen(a)-1;i>=0;i--){
			printf("%d",b[i]);
		}
	}
}

int main(){
	char a[1000];
	int b[1000];
	int x,k;
	scanf("%s",a);
	scanf("%d",&x);
	for(int i=0,j=strlen(a)-1;i<j;i++,j--){
		k=a[i];
		a[i]=a[j];
		a[j]=k;
	}
	mul(a,x,b);
}

大数除法

大数除法
#include 
#include 

void div(char *a,int x,int *b)
{
	int flag=0,i=0;
	while(i<strlen(a)){ 
			flag=flag*10+a[i]-'0';
			if(x>flag){
				b[i]=0;
				i++;
			} 
			else{
				b[i]=flag/x;
				flag=flag%x;
				i++;
			}
		}
		int flag2=0;
		for(int i=0;i<strlen(a);i++){
			if(b[i]==0){

			}
			if(b[i]>0){
				flag2=1;
				printf("%d",b[i]);
			}
			
		}
		printf("\n");
		if(flag!=0){
			printf("余数为%d"); 
		}
	
}

int main(){
	char a[1000];
	int b[1000];
	int x,k;
	scanf("%s",a);
	scanf("%d",&x);
	div(a,x,b);
}

二维前缀和

二维前缀和
#include 
#include 
int main(){
	int a[100][100];
	int s[100][100];
	memset(a,0,10000);
	memset(s,0,10000);
	int m,n;
	scanf("%d %d",&m,&n);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			scanf("%d",&a[i][j]);
			s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
		}
	}
	int x1,y1,x2,y2;
	scanf("%d %d %d  %d",&x1,&y1,&x2,&y2);
	printf("%d",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);
}

二维差分

二维差分
#include 
#include 
int main(){
	int a[100][100];
	int s[100][100];
	int m,n;
	scanf("%d %d",&m,&n);
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			scanf("%d",&s[i][j]);
			a[i][j]=s[i][j]-s[i-1][j]-s[i][j-1]+s[i-1][j-1];
		}
	}
	int x1,y1,x2,y2,c;
	scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&c);
	a[x1][y1]+=c;
	a[x1][y2+1]-=c;
	a[x2+1][y1]-=c;
	a[x2+1][y2+1]+=c;
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
			printf("%d ",a[i][j]);
		}
		printf("\n");
	}
	
}

双指针求最长不重复子串


#include 
#include 

int maxx(int x,int y){
	if(x>=y){
		return x;
	}
	else{
		return y;
	}
}

int main(){
	int a[1000];
	int flag[1000];
	memset(flag,0,1000);
	int n,i,j,res=0;
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	for(i=0,j=0;i<n;i++){
		flag[a[i]]++;
		if(flag[a[i]]>1){
			j=i;
			memset(flag,0,1000);
			flag[a[i]]++;
		}
		res=maxx(res,i-j+1);
	}
	printf("%d",res);
}

区间合并

#include 
#include  
int main(){
	int n;
	scanf("%d",&n);
	int a[100];
	int b[100];
	int flag[100];
	memset(flag,0,100);
	int k;
	for(int i=0;i<n;i++){
		scanf("%d %d",&a[i],&b[i]); 
	}
	for(int i=0;i<n-1;i++){
		for(int j=0;j<n-i-1;j++){
			if(a[j]>a[j+1]){
				k=a[j];
				a[j]=a[j+1];
				a[j+1]=k;
				
				k=b[j];
				b[j]=b[j+1];
				b[j+1]=k;
			}
		}
	}
	for(int i=1;i<n;i++){
		if(flag[i]==0){
				if(a[i]<=b[i-1]){
				flag[i]=1;
				if(b[i]>=b[i-1]){
					b[i-1]=b[i];
				}
				else {
					
				}
			}
			else{
				
			}
		}
		
		
	}
	for(int i=0;i<n;i++){
		if(flag[i]==0){
			printf("%d %d\n",a[i],b[i]);
		}
		
		
	}
}

kmp算法

#include 
#include 



void Next(char *string,int *next){
	int i=1,j=0;
	next[1]=0;
	while(i<strlen(string)){
		if(j==0||string[i]==string[j]){
			i++;
			j++;	
			next[i]=j;
		}
		else{
			j=next[j];
		}		
	}
}

int find(char *string,char *pattern,int pos)
{
	int i=1,j=1;
	int next[1000];
	Next(pattern,next);
	while(i<=strlen(string)&&j<=strlen(pattern)){
		if(j==0||string[i-1]==pattern[j-1]){//当从pattern【0】开始存时要减一,若pattern或者string【0】存的是长度时则不减
			i++;
			j++;
		}
		else{
			j=next[j];
		}
	}
	if(j>strlen(pattern)){
		return i-strlen(pattern);
	}
		return -1;
}



int main(){
	char string[1000];
	char pattern[1001];
		
	scanf("%s %s",string,pattern);
		int flag=find(string,pattern,1);
		printf("%d",flag);
		
	}

trie树插入并查询单词

#include 
#include 
int flag[100][26];
char txt[100]; 
int count[100];
int idx=0;//下标 
void insert(char *txt){
	int p=0,u;
	scanf("%s",txt);
	for(int i=0;i<strlen(txt);i++){
		u=txt[i]-'a';
		if(flag[p][u]==0){
			flag[p][u]=++idx;
			p=flag[p][u];
		}
		else{
			p=flag[p][u];
		}
	}
	count[p]++;
}

void search(char *txt){
	int p=0,u;
	scanf("%s",txt);
	for(int i=0;i<strlen(txt);i++){
		u=txt[i]-'a';
		if(flag[p][u]==0) {
			printf("无");return;
		}
		p=flag[p][u];
	}
	printf("%d",count[p]);
	return;
	
}
int main(){
	memset(flag,0,2600);
	memset(count,0,100);
	int n;
	scanf("%d",&n); 
	for(int i=0;i<n;i++){
		insert(txt);
	}
	search(txt);
} 

并查集实现1.判断两个元素是否属于同一个集合2.将两个集合合并

#include 
#include 
int p[10];
int size[10];
int find(int x){
	if(x!=p[x]){
		p[x]=find(p[x]);
	}
	return p[x];
}
void merge(int n,int m){
	p[find(n)]=find(m);
	size[m]+=size[n];
}
int main(){
	
	for(int i=0;i<10;i++){
		p[i]=i;	
		size[i]=1;
	}
	printf("合并三次:\n");
	for(int i=0;i<3;i++){
		int n,m;
		scanf("%d %d",&n,&m);
		merge(n,m);
	}
	int x,y;
	scanf("%d %d",&x,&y);
	if(find(x)==find(y)){
		printf("在同一个集合中 集合大小为%d",size[find(x)]);
	}
	else{
		printf("不在同一个集合");
	}
} 

DFS和BFS

BFS搜索具有最短性(每条边的权值是1时),即搜索到的点是离自己最近的点
但是DFS搜索不具有最短性

DFS实现全排列

#include 
#include 
int n;
int flag[100];
int path[100];

void dfs(int x){
	if(x==n){
		for(int i=0;i<n;i++){
			printf("%d ",path[i]);
		}
		printf("\n");
		return;
	}
	else{
		for(int i=1;i<=n;i++)
		{
				if(flag[i]==0){
				flag[i]=1;
				path[x]=i;
				dfs(x+1);
				flag[i]=0;
			}
		}
	}
}

int main(){
	scanf("%d",&n);
	memset(flag,0,100);
	dfs(0); 
}

DFS实现八皇后

#include 
#include 
int n,sum=0;
int col[100],dg[100],udg[100];
int path[100][100];

void dfs(int x){//依次遍历每一行 
	if(x==n){
		sum++; 
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				printf("%d ",path[i][j]);
			}
			printf("\n");	
		}
		printf("\n");
		return;
	}
	else{
		for(int i=0;i<n;i++)
		{
				if(col[i]==0&&dg[x+i]==0&&udg[n-x+i]==0){//i=-x+b,b=x+i    i=x+b,b=i-x,但是因为数组下标不能为负数,所以加一个n 
				col[i]=dg[x+i]=udg[i-x+n]=1;
				path[x][i]=1;
				dfs(x+1);
				path[x][i]=0;
				col[i]=dg[x+i]=udg[n-x+i]=0;
			}
		}
	}
}

int main(){
	scanf("%d",&n);
	dfs(0); 
	printf("%d",sum);
}

BFS求走出迷宫的最短路径(左上走到右下)

#include 
#include 

typedef struct node{
	int x;
	int y;
}node;

int i,j,m,n;
int a[100][100];
node b[100];
int flag[100][100];
//m=2 n=3
//0 1 0
//0 0 0
//2 3 0 1 0 0 0 0
void bfs(){
	int tt=0,hh=0;
	node k,p;
	k.x=0;
	k.y=0;
	flag[0][0]=0;
	b[0]=k;
	while(tt<=hh){
		k=b[tt++];
		if(a[k.x-1][k.y]==0&&k.x-1>=0&&flag[k.x-1][k.y]==-1){
			flag[k.x-1][k.y]=flag[k.x][k.y]+1;
			p.x=k.x-1;
			p.y=k.y;
			b[++hh]=p;
			printf("1 ");
		}
		if(a[k.x+1][k.y]==0&&k.x+1<m&&flag[k.x+1][k.y]==-1){
			flag[k.x+1][k.y]=flag[k.x][k.y]+1;
			p.x=k.x+1;
			p.y=k.y;
			b[++hh]=p;
			printf("2 ");
		}
		if(a[k.x][k.y-1]==0&&k.y-1>=0&&flag[k.x][k.y-1]==-1){
			flag[k.x][k.y-1]=flag[k.x][k.y]+1;
			p.x=k.x;
			p.y=k.y-1;
			b[++hh]=p;
			printf("3 ");
		}
		if(a[k.x][k.y+1]==0&&k.y+1<n&&flag[k.x][k.y+1]==-1){
			flag[k.x][k.y+1]=flag[k.x][k.y]+1;
			p.x=k.x;
			p.y=k.y+1;
			b[++hh]=p;
			printf("4 ");
		}
	}
	printf("值:%d",flag[m-1][n-1]) ;
}

int main(){
	memset(flag,-1,10000); 
	scanf("%d %d",&m,&n);
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			scanf("%d",&a[i][j]);
		}
	}
	bfs(); 
}
//m=2 n=3
//0 1 0
//0 0 0
//2 3 0 1 0 0 0 0

质数

质数的判定:o(sqrt(n)复杂度)

for(int i=2;i<n/i;i++){
	if(n%i==0){
		printf("不是质数");
	}
}

短除法

时间复杂度在log2n和根号n之间
i不可能取到合数,因为在这之前肯定有此和数的质因子,然后if n/=i就可以进行排除保证每次进入if里的都是质数,while(n!=i)的目的是防止当n是合数时,就会直接将此合数输出

#include 
#include 
#include 
int main(){
	int n;
	scanf("%d",&n);
	for(int i=2;i<sqrt(n);i++){
		if(n%i==0){
			while(n!=i){
				if(n%i==0){
					printf("%d ",i);
					n/=i;
				}
				else{
					break;
				}
			}
		}
	}
	printf("%d",n);
}

给一串数,筛选其中的质数

将每个质数翻倍,翻倍出来的数一定不是质数

#include 
#include 
#include 
int main(){
	int flag[100000];
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		flag[i]=1;
	}
//	memset(flag,0,1000);
	for(int i=2;i<=sqrt(n);i++){
		if(flag[i]==1){
			for(int j=2*i;j<=n;j+=i){
				flag[j]=0;
			}
		}
	}
	for(int i=2;i<=n;i++){
		if(flag[i]==1){
			printf("%d  ",i);
		}
	}
}

快速幂

简单快速幂

#include 
#include 
#include 
int qpow(int a, int n)
{
    if (n == 0)
        return 1;
    else if (n % 2 == 1)
        return qpow(a, n - 1) * a;
    else
    {
        int temp = qpow(a, n / 2);
        return temp * temp;
//		//这个temp变量是必要的,
//		因为如果不把值记录下来,
//		直接写成qpow(a, n /2)*qpow(a, n /2),
//		那会计算两次a的2/n次方,整个算法就退化为了 O(n)。
    }
}
int main(){
	int a,b,i,j,x,y;
	scanf("%d %d",&x,&y);
 	printf("%d",qpow(x,y));
} 

你可能感兴趣的:(C语言,算法,c语言,排序算法)