C语言函数与算法

ASCⅡ码

十进制 十六进制 字符
9 9
10 A
32 20 空格
48 30 0
57 39 9
65 41 A
90 5A Z
97 61 a
122 7A z

常用函数

交换

void swap(int *a,int *b)	{int temp=*a;*a=*b;*b=temp;}//记得传入的是指针

快速幂

int quickpow(int a,int b) //a的b次方
{
    int r=1,base=a;
    while(b!=0)
    {
        if(b&1) r*=base;
        base*=base;
        b>>=1;
    }
    return r;
}

全排列

int n,book[10],a[10];
void dfs(int x)//当前输入第x位 
{
	int i;
	if(x==n+1)
	{
		for(i=1;i<=n;i++)
			printf("%d ",a[i]);
		printf("\n");
	}
	else
	{
		for(i=1;i<=n;i++)
		{
			if(book[i]==0)
			{
				a[x]=i;
				book[i]=1;
				dfs(x+1);
				book[i]=0;
			}
		}
	}
}
int main()
{
	scanf("%d",&n);
	dfs(1);
	return 0;
}

蔡勒公式

计算哪年哪月哪日是星期几。

int Zeller(int y,int m,int d)//年、月、日
{
	int w;
	if(m<3)	y--,m+=12;
	int c=y/100;
	if(y<1582||(y==1582&&m<10)||(y==1582&&m==10&&d<=4))
		w=(y%100)+(y%100)/4+c/4-2*c+13*(m+1)/5+d+2;
	else
		w=(y%100)+(y%100)/4+c/4-2*c+13*(m+1)/5+d-1;
	w=((w%7)+7)%7;
	if(w==0)	w=7;
	return w;
}

逆波兰表达式

算式转为后缀表达式

struct Stack
{
	int type;//type==0 digit  type==1 signal
	int num;//012345 +-*/()
} s[1005],n[1005];
int ps=0,pn=0;
int read(char c)
{
	if(c=='+')	return 0;
	else if(c=='-') return 1;
	else if(c=='*') return 2;
	else if(c=='/') return 3;
	else if(c=='(') return 4;
	else if(c==')') return 5;
}
int main()
{
	char tmp;
	int t,ifnum=0,i;
	while(scanf("%c",&tmp)!=EOF)
	{
		if(isdigit(tmp)&&ifnum==1)
		{
			t=t*10+tmp-'0';
		}
		else if(isdigit(tmp))
		{
			t=tmp-'0';
			ifnum=1;
		}
		else
		{
			if(ifnum==1)//是数字,输出到n
			{
				pn++;
				n[pn].type=0;
				n[pn].num=t;
				ifnum=0;
			}
			if(tmp=='(')//是(, 入栈s
			{
				ps++;
				s[ps].type=1;
				s[ps].num=5;
			}
			else if(tmp=='+'||tmp=='-'||tmp=='*'||tmp=='/')
			{
				while(1)
				{
					if(ps==0||(s[ps].type==1&&s[ps].num==5))//栈为空或栈顶为(,入栈
					{
						ps++;
						s[ps].type=1;
						s[ps].num=read(tmp);
						break;
					}
					else if(s[1].type==1&&s[ps].num/2>=read(tmp)/2)//栈顶运算符优先级大,栈顶出栈到n
					{
						pn++;
						n[pn]=s[ps];
						ps--;
					}
					else//栈顶运算符优先级小,入栈
					{
						ps++;
						s[ps].type=1;
						s[ps].num=read(tmp);
						break;
					}
				}
			}
			else if(tmp==')')//出栈,直到遇见(
			{
				while(!(s[ps].type==1&&s[ps].num==5))
				{
					pn++;
					n[pn]=s[ps];
					ps--;
				}
				ps--;// (出栈
			}
			else if(tmp=='=')//都出栈
			{
				while(ps>0)
				{
					pn++;
					n[pn]=s[ps];
					ps--;
				}
				break;
			}
		}
	}
	for(i=1; i<=pn; i++)
	{
		if(n[i].type==0)	printf("%d",n[i].num);
		else
		{
			switch(n[i].num)
			{
				case 0:
					printf("+");
					break;
				case 1:
					printf("-");
					break;
				case 2:
					printf("*");
					break;
				case 3:
					printf("/");
					break;
			}
		}
	}
	return 0;
}

数学类

最小公约数

int gcd(int a,int b)	{return a%b==0?b:gcd(b,a%b);}

判断质数

bool isprime(int x)
{
	int tmp=floor(sqrt(x)+0.5);
	for(int i=2;i<=tmp;i++)
		if(x%i==0)	return 0;
	return 1;
}

生成质数表

int v[MAX_N],prime[MAX_N],m;//v[]存一个数最小质因子
void primes(int n)
{
	memset(v,0,sizeof(v));
	m=0;
	for(int i=2;i<=n;i++)
	{
		if(v[i]==0)//i是质数
		{
			v[i]=i;
			prime[++m]=i;
		}
		//给当前的数i乘上一个质因子
		for(int j=1;j<=m;j++)
		{
			if(prime[j]>v[i]||prime[j]>n/i)	break;	//i有比prime[j]更小的质因子,或者超出n的范围
			v[i*prime[j]]=prime[j];					//prime[j]是合数i*prime[j]的最小质因子
		}
	}
	for(int i=1;i<=m;i++)	printf("%d ",prime[i]);
}

求逆元

void exgcd(long long a,long long b,long long& d,long long &x,long long &y)
{
    if(!b) {d=a;x=1;y=0;}
    else{exgcd(b,a%b,d,y,x);y-=x*(a/b);}
}
long long inv(long long a, long long p)//a是要求逆元的数,p是模数
{
    long long d,x,y;
    exgcd(a,p,d,x,y);
    return d==1?(x+p)%p:-1;
}

矩阵

矩阵乘法

//n×m矩阵*m×p矩阵
for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
		for(int k=1;k<=p;k++)
			c[i][k]+=a[i][j]*b[j][k];

矩阵乘法求斐波那契数列第n项

#define N 2
//(f[i]  ) (1 1) (f[i-1])
//(f[i-1])=(1 0)*(f[i-2])
struct node
{
	long long g[N+1][N+1];
}f,res;
long long n,p;
void matrixmultiply(node &x,node &y,node &z)//z=x+y 
{
	memset(z.g,0,sizeof(z.g));
	for(int i=1;i<=N;i++)
	{
		for(int j=1;j<=N;j++)
			if(x.g[i][j])
			{
				for(int k=1;k<=N;k++)
				{
					z.g[i][k]+=x.g[i][j]*y.g[j][k];
					z.g[i][k]%=p;
				}
			}
	} 
}
void matrixquickpow(int k)//矩阵快速幂 
{
	node tmp=f,t;
	while(k)
	{
		if(k&1)	{matrixmultiply(res,tmp,t);res=t;}
		matrixmultiply(tmp,tmp,t);tmp=t;
		k>>=1;
	}
}
long long solve()
{
	if(n<=2)	return 1;
	matrixquickpow(n-2);//算前面系数矩阵的n-2次方 
	long long ret=res.g[1][1]+res.g[2][1];//求f[i] 
	ret%=p;
	return ret;
}
int main()
{
	scanf("%lld%lld",&n,&p);//第n个数,模p
    //系数矩阵
	f.g[1][1]=1;
	f.g[1][2]=1;
	f.g[2][1]=1;
	f.g[2][2]=0;
	//构造单位矩阵
	for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
			if(i==j)	res.g[i][j]=1;
			else		res.g[i][j]=0;
	long long ans=solve();
	printf("%lld",ans);
	return 0;
}

求矩阵的秩(高斯-若尔当消元法)

int t,n,m,i,j,k,tmp,rank,x;
double a[maxn][maxn],b[maxn][maxn],Tmp;
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++)
	for(j=1; j<=m; j++)
		scanf("%lf",&a[i][j]);
if(n<m)//如果n<m将矩阵转置
{
	for(i=1; i<=n; i++)
		for(j=1; j<=m; j++)
			b[j][i]=a[i][j];
	tmp=n,n=m,m=tmp;
	for(i=1; i<=n; i++)
		for(j=1; j<=m; j++)
			a[i][j]=b[i][j];
}
rank=0;
for(i=1; i<=m; i++)
{
	//将所有行该列中绝对值最大的那个元素所在的行交换到第i行以减少浮点误差
	x=i;
	for(j=i+1; j<=n; j++)
		if(fabs(a[j][i])>fabs(a[x][i]))
			x=j;
	if(fabs(a[x][i])<1e-2)	continue;//该列全为0,跳过 
	rank++;
	if(x!=i)
		for(j=1; j<=m; j++)
			Tmp=a[i][j],a[i][j]=a[x][j],a[x][j]=Tmp;
	for(j=1; j<=m; j++)
		if(i^j)a[i][j]/=a[i][i];
	a[i][i]=1;
	
	for(j=1; j<=n; j++)
	{
		if(j==i)	continue;
		for(k=1; k<=m; k++)
		{
			if(k==i)	continue;
			a[j][k]-=a[j][i]*a[i][k];
		}
		a[j][i]=0;
	}
}
printf("%d",rank);

高精度

字符数组转整型数组

void array_char_to_int(char a[],int b[])
{
	int len=(int)strlen(a);
	for(int i=0;i<len;i++)	b[len-i]=a[i]-'0';
}

高精加高精

void add_HH(int a[],int b[])	//记得为lena,lenb赋值
{
	int x=0;//进位 
	lenc=1;
	while(lenc<=lena||lenc<=lenb)
	{
		c[lenc]=a[lenc]+b[lenc]+x;
		x=c[lenc]/10;
		c[lenc]%=10;
		lenc++;
	}
	c[lenc]=x;
	if(c[lenc]==0)	lenc--;//处理最高位 
}

高精加低精

void add_HL(int a[],int b)
{
	int x=0,t,i;//t为低精度当前位 
	for(i=1;i<=lena||b>0;i++)
	{
		t=b%10;
		b/=10;
		c[i]=a[i]+t+x;
		x=c[i]/10;
		c[i]%=10;
	}
	lenc=i-1;
}

高精减高精

void subtract_HH(int a[],int b[])
{
	int i=1;
	while(i<=lena||i<=lenb)
	{
		if(a[i]<b[i])
		{
			a[i]+=10;
			a[i+1]--;
		}
		c[i]=a[i]-b[i];
		i++;
	}
	lenc=i;
	while((c[lenc]==0)&&(lenc>1))	lenc--;//去除高位的0 
}

判断是否为小数减大数

void subtract_cmp(char a[],char b[])
{
	if(strlen(a)<strlen(b)||(strlen(a)==strlen(b)&&strcmp(a,b)<0))
	{
		strcpy(temp,a);//将a复制给temp,temp是中间数组
		strcpy(a,b);
		strcpy(b,temp);
		printf("-");
	}
}

高精乘高精

void multiply_HH(int a[],int b[])
{
	int x;//进位 
	for(int i=1;i<=lena;i++)
	{
		x=0;
		for(int j=1;j<=lenb;j++)
		{
			c[i+j-1]=a[i]*b[j]+x+c[i+j-1];//当前乘积+上次乘积进位+原数
			x=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
		c[i+lenb]=x;
	}
	lenc=lena+lenb;
	while(c[lenc]==0&&lenc>1)	lenc--;//删除前导0 
}

高精乘低精

void multiply_HL(int a[],int b)
{
	int t,x;//进位 
	for(int i=1;i<=lena;i++)
	{
		int j;
		x=0;t=b;
		for(j=1;t;j++)
		{
			c[i+j-1]=a[i]*(t%10)+x+c[i+j-1];//当前乘积+上次乘积进位+原数
			x=c[i+j-1]/10;
			c[i+j-1]%=10;
			t/=10;
		}
		lenb=j-1;
		c[i+lenb]=x;
	}
	lenc=lena+lenb;
	while(c[lenc]==0&&lenc>1)	lenc--;//删除前导0
}

高精除以高精

char a1[1005],b1[1005];
int a[1005],b[1005],c[1005];
//a[0],b[0]存长度
void array_char_to_int(char a[],int b[])
{
	int len=(int)strlen(a);
	for(int i=0;i<len;i++)	b[len-i]=a[i]-'0';
}
int compare(int a[],int b[])//比较a[],b[]大小,a>b返回1 
{
	int i;
	if(a[0]>b[0])	return 1;
	if(a[0]<b[0])	return -1;
	for(i=a[0];i>0;i--)//从高位到低位比较
	{
		if(a[i]>b[i])	return 1;
		if(a[i]<b[i])	return -1;
	}
	return 0;
}
void subtract(int a[],int b[])//a=a-b
{
	int flag=compare(a,b);
	if(flag==0)	{a[0]=0;return;}
	else if(flag==1)
	{
		for(int i=1;i<=a[0];i++)
		{
			if(a[i]<b[i])
			{
				a[i+1]--;
				a[i]+=10;
			}
			a[i]-=b[i];
		}
		while(a[0]>0&&a[a[0]]==0)	a[0]--;//去0
		return;
	}
}
void numcpy(int a[],int b[],int det)//复制a[]到b[]从det开始的地方 
{
	for(int i=1;i<=a[0];i++)	b[i+det-1]=a[i];
	b[0]=a[0]+det-1; 
}
void divide_HH(int a[],int b[],int c[])
{
	int i,tmp[1005];
	c[0]=a[0]-b[0]+1;
	for(i=c[0];i>0;i--)
	{
		memset(tmp,0,sizeof(tmp));
		numcpy(b,tmp,i);
		while(compare(a,tmp)>=0)	{c[i]++;subtract(a,tmp);}
	}
	while(c[0]>0&&c[c[0]]==0)	c[0]--;
	return;
}
int main()
{
	gets(a1);
	gets(b1);
	a[0]=(int)strlen(a1);
	b[0]=(int)strlen(b1);
	array_char_to_int(a1,a);
	array_char_to_int(b1,b);
	divide_HH(a,b,c);
	for(int i=c[0];i>=1;i--)	printf("%d",c[i]);//商 
	printf("\n");
	for(int i=a[0];i>=1;i--)	printf("%d",a[i]);//余数 
	return 0;
}

高精除以低精

void divide_HL(int a[],int b)
{
	int x=0;
	for(int i=lena;i>=1;i--)
	{
		c[i]=(x*10+a[i])/b;
		x=(x*10+a[i])%b;
	}
	//x就是余数 
	lenc=lena;
	while(c[lenc]==0&&lenc>1)	lenc--;//删除前导0
}

y/x保留到小数点后len位

void divide_decimal(int y,int x,int len)
{
	printf("%d",y/x);
	y%=x;
	if(y==0)	return;
	printf(".");
	while(len--)
	{
		y*=10;
		printf("%d",y/x);
		y%=x;
		if(y==0)	return;
	}
}

qsort和bsearch

int类型

int cmp_int(const void* _a,const void* _b)	//参数格式固定,bsearch与qsort的函数一致
{
    int* a=(int*)_a;    //强制类型转换
    int* b=(int*)_b;
    return *a-*b;		//升序
    //return *b-*a;		//降序
    //(有时候范围会超int!!!)
}

qsort(ArrayName,size,sizeof(ArrayName[0]),cmp_int);	//从0开始,一共排size个

int key;
//key是要找的数,要为key赋值;从0开始找,一共查找size个数
int *p=(int*)bsearch(&key,ArrayName,size,sizeof(int),cmp_int);
//若找到key,*p返回找到的数的值(即key);若未找到,返回空指针NULL;p-ArrayName可以算出下标值b

double类型

int cmp_double(const void* _a,const void* _b)	//参数格式固定
{
    double* a=(double*)_a;    //强制类型转换
    double* b=(double*)_b;
	return *a>*b?1:-1;		//升序 
	//return *a>*b?-1:1;	//降序 
}

qsort(ArrayName,size,sizeof(ArrayName[0]),cmp_double);

char类型

int cmp_char(const void* _a,const void* _b)  //参数格式固定
{
    char* a=(char*)_a;    //强制类型转换
    char* b=(char*)_b;
    return *a-*b;		//升序
    //return *b-*a;		//降序
}

qsort(ArrayName,size,sizeof(ArrayName[0]),cmp_char);	//从0开始,一共排size个

char[]类型

int cmp_string(const void* _a,const void* _b)		//要定义二维字符数组
{
    char* a=(char*)_a;		//强制类型转换
    char* b=(char*)_b;
    return strcmp(a,b);		//字典序 
}

qsort(ArrayName,size,sizeof(ArrayName[0]),cmp_string);

struct类型

int cmp_struct(const void *_a ,const void *_b)	//Note为结构体名
{ 
	struct Note *a=(struct Note *)_a; 
	struct Note *b=(struct Note *)_b; 
	//return a->x-b->x;		//升序
	//return b->x-a->x;		//降序 
	
	//双关键字排序 
	//if(a->x!=b->x) 	return a->x-b->x; 	//第一关键字升序 
	//else 			return b->y-a->y;	//第二关键字降序 
} 

qsort(结构体变量名,size,sizeof(结构体变量名[0]),cmp_struct);

int key;
//key是要找的数,要为key赋值;从0开始找,一共查找size个数
Note *p=(Note*)bsearch(&key,StructName,size,sizeof(StructName[0]),cmp_struct);
//若找到key,*p返回找到的数的值(即key);若未找到,返回空指针NULL;p-StructName可以算出下标值
//如:StructName[p-StructName].element

快读快写

快读

inline int read()
{
    int x=1,y=0;
    char ch=getchar();
    //为避免输入数字之前的空格造成影响
    while(ch<'0'||ch>'9'){if(ch=='-') x=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){y=y*10+ch-'0';ch=getchar();}
    return x*y;
}

快写

inline void write(int n)
{
    if(n<0) putchar('-'),n*=-1;
    if(n>9) write(n/10);
    putchar(n%10+'0');
}

进制转换

char array[40]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

任意进制转十进制(低精)

//仅支持2~10进制转化为10进制
int todecimalism_L(int x,int p)//x:要转的数  p:进制数 
{
	int ans=0,w=1;
	while(x!=0)
	{
		ans+=(x%10)*w;
		x/=10;
		w*=p;
	}
	return ans;
}

十进制转任意进制(低精)

void toanyradix_L(int x,int p)
{
	if(x!=0)
	{
		toanyradix(x/p,p);
		printf("%c",array[x%p]);
	}
}
//注意特判0!!!

任意进制转任意进制(高精)

char a1[10005];
int a[10005],c[10005],lena,lenc,oldbase,newbase;
void array_char_to_int(char a[],int b[])
{
	int len=(int)strlen(a);
	for(int i=0;i<len;i++)
	{
		if(isdigit(a[i]))	b[len-i]=a[i]-'0';
		else if(isupper(a[i]))	b[len-i]=a[i]-'A'+10;
	}
}
int divide_HL(int a[],int oldbase,int newbase)
{
	int x=0;
	for(int i=lena;i>=1;i--)
	{
		c[i]=(x*oldbase+a[i])/newbase;
		x=(x*oldbase+a[i])%newbase;
	}
	//x就是余数 
	lenc=lena;
	while(c[lenc]==0&&lenc>1)	lenc--;//删除前导0
	memcpy(a,c,sizeof(c));
	lena=lenc;
	return x;
}
void anyradix_H(int a[],int oldbase,int newbase)
{
	if(lena>=2||(lena==1&&a[1]!=0))
	{
		int x=divide_HL(a,oldbase,newbase);
		anyradix_H(a,oldbase,newbase);
		printf("%c",array[x]);
	}
}
int main()
{
	scanf("%s%d%d",a1,&oldbase,&newbase);
	array_char_to_int(a1,a);
	lena=(int)strlen(a1);
	anyradix_H(a,oldbase,newbase);
}

深搜广搜

struct Note
{
	int x;
	int y;
}q[100001];
int startx,starty,endx,endy,N;
short next[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
bool result,book[105][105];
bool map[105][105];
void bfs(int m,int n)
{
	int head=1,tail=1;
	q[1].x=m,q[1].y=n;
	tail++;
	while(tail>head)
	{
		for(int i=0;i<=3;i++)
		{
			int nx=q[head].x+next[i][0];
			int ny=q[head].y+next[i][1];
			if(map[nx][ny]==0&&book[nx][ny]==0&&nx>=0&&nx<N&&ny>=0&&ny<N)
			{
				book[nx][ny]=1;
				q[tail].x=nx;
				q[tail].y=ny;
				tail++;
				if(nx==endx&&ny==endy)
				{
					result=1;
					break;
				}
			}
		}
		if(result==1)	break;
		head++;
	}
	return;
}
void dfs(int x,int y)
{
	if(result==1)	return;
	if(x==endx&&y==endy)
	{
		result=1;
		return;
	}
	for(int i=0;i<=3;i++)
	{
		int nx=x+next[i][0];
		int ny=y+next[i][1];
		if(map[nx][ny]==0&&book[nx][ny]==0&&nx>=0&&nx<n&&ny>=0&&ny<n)
		{
			book[nx][ny]=1;
			dfs(nx,ny);
		}
	}
	return;
}
int main()
{
	char c;
	cin>>N;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		{
			cin>>c;
			if(c=='#')	map[i][j]=1;//障碍
			else		map[i][j]=0;
		}
	cin>>startx>>starty>>endx>>endy;
	result=0;
	memset(book,0,sizeof(book));
	book[startx][starty]=1;
    dfs(startx,starty);
	bfs(startx,starty);
	if(result==0)	cout<<"NO"<<endl;
	else			cout<<"YES"<<endl;
	return 0;
}

排序

冒泡排序

for(i=n-1;i>=1;i--)//对1~n排序
{
    book=1;
    for(j=1;j<=i;j++)
        if(a[j]>a[j+1])
        {
            swap(&a[j],&a[j+1]);
            book=0;
        }
	if(book==1)	break;
}

快速排序

void quicksort(int left,int right)
{
	int i,j,mid,temp;
	i=left,j=right;
	mid=a[(left+right)/2];//基准数
	do
	{
		//升序
		while(a[i]<mid)	i++;
		while(a[j]>mid)	j--;
		//降序
		//while(a[i]>mid)	i++;
		//while(a[j]<mid)	j--;
		if(i<=j)
		{
			temp=a[i],a[i]=a[j],a[j]=temp;
			i++,j--;
		}
	}while(i<=j);
	if(left<j)	quicksort(left,j);
	if(i<right)	quicksort(i,right);
}

归并排序

void msort(int s,int t)
{
	if (s==t)	return;
	int mid=(s+t)/2;
	msort(s,mid);
	msort(mid+1,t);
	int i=s,j=mid+1,k=s;
	while(i<=mid&&j<=t)
	{
		if (a[i]<=a[j])
		{
			r[k]=a[i];
			k++,i++;
		}
		else
		{
			r[k]=a[j];
			k++,j++;
			ans+=mid-i+1;//统计逆序对
		}
	}
	while(i<=mid)
	{
		r[k]=a[i];
		k++,i++;
	}
	while(j<=t)
	{
		r[k]=a[j];
		k++,j++;
	}
	for (i = s; i <=t; i++)	a[i]=r[i];
}

图论

并查集

int getf(int v)
{
    if(f[v]==v)	return v;
    f[v]=getf(f[v]);
    return f[v];
}
int merge(int u,int v)
{
    int t1,t2;
    t1=getf(u);
    t2=getf(v);
    if(t1!=t2)
    {
        f[t2]=t1;
        return 1;//合并成功
    }
    return 0;//本来就是一个团伙,不用合并
}

最小生成树

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,tot=0,k=0;//n端点总数,m边数,tot记录最终答案,k已经连接了多少边 
int fat[200010];//记录集体老大 
struct node
{
	int from,to,dis;//结构体储存边 
}edge[200010];
bool cmp(const node &a,const node &b)//sort排序(当然你也可以快排) 
{
	return a.dis<b.dis;
}
int father(int x)//找集体老大,并查集的一部分 
{
	if(fat[x]!=x)
	return father(fat[x]);
	else return x;
}
void unionn(int x,int y)//加入团体,并查集的一部分 
{
	fat[father(y)]=father(x);
}
int main()
{
	scanf("%d%d",&n,&m);//输入点数,边数 
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].dis);//输入边的信息 
	}
	for(int i=1;i<=n;i++) fat[i]=i;//自己最开始就是自己的老大 (初始化) 
	sort(edge+1,edge+1+m,cmp);//按权值排序(kruskal的体现) 
	for(int i=1;i<=m;i++)//从小到大遍历 
	{
		if(k==n-1) break;//n个点需要n-1条边连接 
		if(father(edge[i].from)!=father(edge[i].to))//假如不在一个团体 
		{
			unionn(edge[i].from,edge[i].to);//加入 
			tot+=edge[i].dis;//记录边权 
			k++;//已连接边数+1 
		}
	}
	printf("%d",tot);
	return 0;
}

部分库、函数用法

sscanf

int sscanf(const char *str, const char *format, ...)

// 用法一:取指定长度的字符串
sscanf("12345","%4s",str);  	// 取字符的前4位 str:"1234"
// 用法二:格式化时间
sscanf("2013/02/13 14:55:34","%d/%d/%d %d:%d:%d",&year,&month,&day,&hour,&minute,&second);  
// 用法三:读入字符串
sscanf("12345","%s",str); 
// 用法四:%*d 和 %*s 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)
sscanf("12345acc","%*d%s",str);		// str:"acc"
sscanf("12345abc","%d%*s",&num);	// num:12345
// 用法五:取到指定字符为止的字符串。如在下例中,取遇到'+'为止字符串。
sscanf("12345+acc","%[^+]",str);  
// 用法六:取到指定字符集为止的字符串。
sscanf("eihbu","%[e-m]",str); 				// 取e-m之间的字符,若不是终止读入 str:"eih"
sscanf("bvccbuaa","%[b|c|v]",str);			// 取b,c或v,若不是则中止 str:"bvccb"
sscanf("12345+acc","%[^+]",str);			// 取遇到'+'为止的字符串 str:"12345"
sscanf("12345+acc121","%[^a-z]",str);		// 取遇到小写字母为止的字符串 str:"12345+"
sscanf(c,"%5s-%*[a-f] %[A-D]_*%[s|d|l]",str1,str2,str3);	//str1:"12345" str2:"ABCD" str3:"sd"

string.h

memset(intArray,num,sizeof(intArray))//赋值0:0	0x3f3f3f3f:无穷大(相加不会溢出)	127:无穷大		128:无穷小

char a[105],b[105];
int n;
char *p,c;
strcat(a,b);		//将b追加到a后
strncat(a,b,n);		//将b的前n位追加到a后
strcpy(a,b);		//将b复制到a
strncpy(a,b,n);		//将b的前n位复制到a
printf("%d",strncmp(a,b,n));	//比较a和b的前n位
puts(b);
p=strchr(a,c);		//查找字符c在a中第一次出现的位置(p=a中第一个c的地址)
p=strrchr(a,c);		//查找字符c在a中最后一次出现的位置(p=a中最后一个c的地址)
p=strstr(a,b);		//查找子串b首次出现的位置(p=a中第一个子串b的第一个字符的地址)
//strchr例:
p=a;
while((p=strchr(p,c))!=NULL)
{
	printf("%d ",p-a); //下标
	p++;
}
//strstr例:
p=a;
while((p=strstr(p,b))!=NULL)
{
	printf("%d ",p-a); //下标
	p+=strlen(b);
}

atoi、atof

char a[105];int n;double f;
n=atoi(a);//将数字字符串转化为int类型(遇到非数字则中止) 
f=atof(a);//将数字字符串转化为double类型(遇到非数字则中止(第一个小数点除外)) 

time.h

/*
clock_t clock( void ); 这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数。
clock_t是一个长整形数 
系统常量:#define CLOCKS_PER_SEC 1000

struct tm
{  
	int tm_sec; 		 秒 – 取值区间为[0,59] 
	int tm_min; 		 分 - 取值区间为[0,59]   
	int tm_hour; 		 时 - 取值区间为[0,23]  
	int tm_mday; 		 一个月中的日期 - 取值区间为[1,31] 
	int tm_mon; 		 月份(从一月开始,0代表一月) - 取值区间为[0,11] 
	int tm_year; 		 年份,其值等于实际年份减去1900 
	int tm_wday; 		 星期 – 取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 
	int tm_yday; 		 从每年的1月1日开始的天数 – 取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 
	int tm_isdst; 		 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。
};
time_t是一个长整型数。用time_t表示的时间(日历时间)是从一个时间点
(例如:1970年1月1日0时0分0秒)到此时的秒数。

将日历时间(一个用time_t表示的整数)转换为我们平时看到的把年月日时分秒分开显示的时间格式tm: 
struct tm * gmtime(const time_t *timer);  
struct tm * localtime(const time_t * timer); 

我们可以通过time()函数来获得日历时间(Calendar Time),其原型为:
time_t time(time_t * timer); 

我们可以通过asctime()函数和ctime()函数将时间以固定的格式显示出来,
两者的返回值都是char*型的字符串。返回的时间格式为: 
星期几 月份 日期 时:分:秒 年\n\0  
例如:Wed Jan 02 02:03:55 1980\n\0 
其中/n是一个换行符,/0是一个空字符,表示字符串结束。下面是两个函数的原型: 
char * asctime(const struct tm * timeptr);  
char * ctime(const time_t *timer); 
其中asctime()函数是通过tm结构来生成具有固定格式的保存时间信息的字符串,
而ctime()是通过日历时间来生成时间字符串。这样的 话,
asctime()函数只是把tm结构对象中的各个域填到时间字符串的相应位置就行了,
而ctime()函数需要先参照本地的时间设置,把日历时间转 化为本地时间,然后再生成格式化后的字符串。

我们可以使用mktime()函数将用tm结构表示的时间转化为日历时间。其函数原型如下: 
time_t mktime(struct tm * timeptr); 

*/
#include<cstdio>
#include<ctime>
int main()
{
	//printf("%d",sizeof(long));
	int i=10000000;
	clock_t start,finish;
	start=clock();
	while(i--)
	finish=clock();
	printf("%ld",finish-start);
	
	
	time_t timer;
	struct tm *p;
	timer=time(&timer);//或 timer=time(NULL)
	p=gmtime(&timer);
	printf("%d",p->tm_hour);
	
	
	
	struct tm t;
	//struct tm *p;
	time_t t_of_day;
	t.tm_year=2020-1900;
	t.tm_mon=9;
	t.tm_mday=28;
	t.tm_hour=8;
	t.tm_min=45;
	t.tm_sec=1;
	t_of_day=mktime(&t);
	p=gmtime(&t_of_day);
	printf("今天是星期:%d\n",p->tm_wday);
	printf(ctime(&t_of_day));
	return 0;
}
/*
例 :
下面的例子可以计算出1997年7月1日是星期几: 

#include "time.h"  
#include "stdio.h"  
#include "stdlib.h"  
int main(void)  
{  
	struct tm t;  
	time_t t_of_day;  
	t.tm_year=1997-1900;  
	t.tm_mon=6;  
	t.tm_mday=1;  
	t.tm_hour=0;  
	t.tm_min=0;  
	t.tm_sec=1;  
	t.tm_isdst=0;  
	t_of_day=mktime(&t);  
	printf(ctime(&t_of_day));  
	return 0;  
}  
运行结果:  
Tue Jul 01 00:00:01 1997  
现在注意了,有了mktime()函数,是不是我们可以操作现在之前的任何时间呢?
你可以通过这种办法算出1945年8月15号是星期几吗?答案是否定的。
因为这个时间在1970年1月1日之前,所以在大多数编译器中,这样的程序虽然可以编译通过,但运行时会异常终止。 
*/

随机数

#include<stdlib.h>
#include<time.h>

srand(time(NULL)); 
int t=rand();	// 0~32767

多线程

#include<stdio.h>
#include<windows.h>
DWORD /*WINAPI*/fun(LPVOID pM)
{
	//printf("%d",GetCurrentThreadId());
	for(int i=1;;i++)
	{
		Sleep(1000);
		printf("bbb\n");
	}
	return 0;
}
int main()
{
	printf("多线程");
	HANDLE handle=CreateThread(NULL,0,fun,NULL,0,NULL);
	for(int i=1;;i++)
	{
		Sleep(1000);
		printf("aaa\n");
	}
	WaitForSingleObject(handle,INFINITE);
	return 0; 
}

终端

颜色

#include<stdio.h>
#include<windows.h>
void SetColor(unsigned short ForeColor=7,unsigned short BackGroundColor=0)
{
	HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle,ForeColor+BackGroundColor*0x10);
}
int main()
{
	for(int i=0;i<=16;i++)
	{
		SetColor(0,i);
		printf("                      \n");	
	}
	return 0;
}

隐藏光标

void hidden_cursor()
{
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cci;
	GetConsoleCursorInfo(hOut,&cci);
	cci.bVisible=0;
	SetConsoleCursorInfo(hOut,&cci);
}

光标位置

void SetPos(int x,int y)
{
    COORD coord;
    coord.X=y;
    coord.Y=x;
    SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );
}

TCP

client

#include<stdio.h>
#include<windows.h>
SOCKET clientSocket;
int count=0;
void jieshou()
{
	char recvBuff[1024];
	int r;
	while(1)
	{
		r = recv(clientSocket,recvBuff,1023,NULL);
		if(r>0)
		{
			recvBuff[r]=0;
			printf("%s\n",recvBuff);
		}
	}
}
int main()
{
	//1 请求协议版本 
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);
	if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
	{
		printf("请求协议版本失败\n");
		return -1;
	}

	//2 创建socket
	clientSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(SOCKET_ERROR == clientSocket)
	{
		printf("创建socket失败!\n");
		WSACleanup();
		return -2;
	}
	else printf("创建socket成功\n");
	
	//3 获取服务器协议地址族
	SOCKADDR_IN addr = {0};
	addr.sin_family = AF_INET;//协议版本
	addr.sin_addr.S_un.S_addr = inet_addr("10.135.94.10");
	addr.sin_port = htons(10086);//0~65535   用10000左右的端口 
	
	//4 连接服务器
	int r = connect(clientSocket,(struct sockaddr*)&addr,sizeof(addr));
	if(r==-1)
	{
		printf("连接服务器失败\n");
		return -3;
	}
	else	printf("连接服务器成功\n");
	
	//5 通信
	char buff[1024];
	CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)jieshou,NULL,NULL,NULL);
	while(1)
	{
		memset(buff, 0, 1024);
		printf("输入你想说的:");
		scanf("%s",buff);
		send(clientSocket,buff,strlen(buff),NULL);
	}
	return 0;
}

server

#include<stdio.h>
#include<windows.h>
SOCKADDR_IN cAddr = {0};
int len = sizeof(cAddr);
SOCKET clientSocket[1024];
int count=0;
void tongxin(int idx)
{
	char buff[1024];
	int r;
	while(1)
	{
		r = recv(clientSocket[idx],buff,1023,NULL);
		if(r>0)
		{
			buff[r]=0;
			printf("%d:%s\n",idx,buff);
			//广播数据 
			int i;
			for(i=0;i<count;i++)
			{
				send(clientSocket[i],buff,strlen(buff),NULL);
			}
		}
	}
}
int main()
{
	//1 请求协议版本 
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);
	if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
	{
		printf("请求协议版本失败\n");
		return -1;
	}

	//2 创建socket
	SOCKET serverSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(SOCKET_ERROR == serverSocket)
	{
		printf("创建socket失败!\n");
		WSACleanup();;
		return -2;
	}
	else printf("创建socket成功\n");
	
	//3 创建协议地址族
	SOCKADDR_IN addr = {0};
	addr.sin_family = AF_INET;//协议版本
	addr.sin_addr.S_un.S_addr = inet_addr("10.135.94.10");
	addr.sin_port = htons(10086);//0~65535   用10000左右的端口 
	
	//4 绑定
	int r = bind(serverSocket,(struct sockaddr*) &addr,sizeof(addr));
	if(r == -1)
	{
		printf("bind失败\n");
		closesocket(serverSocket);
		WSACleanup();
		return -3;
	}
	else	printf("bind成功\n");
	
	//5 监听
	r = listen(serverSocket,10);
	if(r == -1)
	{
		printf("listen失败\n");
		closesocket(serverSocket);
		WSACleanup();
		return -4;
	}
	else	printf("listen成功\n");
	
	//6 等待客户端连接
	while(1)
	{
		clientSocket[count] = accept(serverSocket, (struct sockaddr*) &cAddr, &len);
		if(SOCKET_ERROR == clientSocket[count])
		{
			printf("服务器宕机了\n");
			closesocket(serverSocket);
			WSACleanup();
			return -5;
		}
		else	printf("有客户端连接到服务器了:%s\n",inet_ntoa(cAddr.sin_addr));	
		
		CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)tongxin,(char*)count,NULL,NULL);
	
		
		count++;
	}
	
	//7 通信
	char buff[1024];
	while(1)
	{
		r = recv(clientSocket,buff,1023,NULL);
		if(r>0)
		{
			buff[r] = 0;
			printf("%s\n",buff);
		}
	} 
	return 0;
}

C语言函数与算法
https://shuusui.site/blog/2021/07/02/c/
作者
Shuusui
发布于
2021年7月2日
更新于
2021年7月2日
许可协议