这个文件必看啊 太好了
数学问题:
1.精度计算——大数阶乘
2.精度计算——乘法(大数乘小数)
3.精度计算——乘法(大数乘大数)
4.精度计算——加法
5.精度计算——减法
6.任意进制转换
7.最大公约数、最小公倍数
8.组合序列
9.快速傅立叶变换(FFT)
10.Ronberg算法计算积分
11.行列式计算
12.求排列组合数
13.求某一天星期几
字符串处理:
1.字符串替换
2.字符串查找
3.字符串截取
4.LCS—最大公共子串长度
5.LCS-生成最大公共子串
6.数字转化为字符
计算几何:
1.叉乘法求任意多边形面积
2.求三角形面积
3.两矢量间角度4.两点距离(2D、3D)
5.射向法判断点是否在多边形内部
6.判断点是否在线段上
7.判断两线段是否相交
8.判断线段与直线是否相交
9.点到线段最短距离
10.求两直线的交点
11.判断一个封闭图形是凹集还是凸集
12.Graham扫描法寻找凸包
13.求两条线段的交点
数论:
1.x的二进制长度
2.返回x的二进制表示中从低到高的第i位
3.模取幂运算
4.求解模线性方程
5.求解模线性方程组(中国余数定理)
6.筛法素数产生器
7.判断一个数是否素数
8.求子距阵最大和
9.求一个数每一位之和
10.质因数分解
11.高斯消元法解线性方程组
图论:
1.Prim算法求最小生成树
2.Dijkstra算法求单源最短路径
3.Bellman-ford算法求单源最短路径
4.Floyd算法求每对节点间最短路径
5.解欧拉图
排序/查找:
1.快速排序
2.希尔排序
3.选择法排序
4.二分查找
高精度运算专题:
1.本专题公共函数说明
2.高精度比较
3.高精度加法
4.高精度减法
5.高精度乘10
6.高精度乘单精度
7.高精度乘高精度
8.高精度除单精度
9.高精度除高精度
一、数学问题
1.精度计算——大数阶乘
语法:int result=factorial(int n);
参数:
n:n 的阶乘
返回值:阶乘结果的位数
注意:
本程序直接输出n!的结果,需要返回结果请保留long a[]
需要 math.h
源程序:
int factorial(int n)
{
long a[10000];
int i,j,l,c,m=0,w;
a[0]=1;
for(i=1;i<=n;i++)
{
c=0;
for(j=0;j<=m;j++)
{
a[j]=a[j]*i+c;
c=a[j]/10000;
a[j]=a[j]%10000;
}
if(c>0) {m++;a[m]=c;}
}
w=m*4+log10(a[m])+1;
printf("\n%ld",a[m]);
for(i=m-1;i>=0;i--) printf("%4.4ld",a[i]);
return w;
}
2.精度计算——乘法(大数乘小数)
语法:mult(char c[],char t[],int m);
参数:
c[]:被乘数,用字符串表示,位数不限
t[]:结果,用字符串表示
m:乘数,限定10以内
返回值:null
注意:
需要 string.h
源程序:
void mult(char c[],char t[],int m)
{
int i,l,k,flag,add=0;
char s[100];
l=strlen(c);
for (i=0;i<l;i++)
s[l-i-1]=c[i]-'0';
for (i=0;i<l;i++)
{
k=s[i]*m+add;
if (k>=10) {s[i]=k%10;add=k/10;flag=1;} else
{s[i]=k;flag=0;add=0;}
}
if (flag) {l=i+1;s[i]=add;} else l=i;
for (i=0;i<l;i++)
t[l-1-i]=s[i]+'0';
t[l]='\0';
}
3.精度计算——乘法(大数乘大数)
语法:mult(char a[],char b[],char s[]);
参数:
a[]:被乘数,用字符串表示,位数不限
b[]:乘数,用字符串表示,位数不限
t[]:结果,用字符串表示
返回值:null
注意:
空间复杂度为 o(n^2)
需要 string.h
源程序:
void mult(char a[],char b[],char s[])
{
int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0;
char result[65];
alen=strlen(a);blen=strlen(b);
for (i=0;i<alen;i++)
for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0');
for (i=alen-1;i>=0;i--)
{
for (j=blen-1;j>=0;j--) sum=sum+res[i+blen-j-1][j];
result[k]=sum%10;
k=k+1;
sum=sum/10;
}
for (i=blen-2;i>=0;i--)
{
for (j=0;j<=i;j++) sum=sum+res[i-j][j];
result[k]=sum%10;
k=k+1;
sum=sum/10;
}
if (sum!=0) {result[k]=sum;k=k+1;}
for (i=0;i<k;i++) result[i]+='0';
for (i=k-1;i>=0;i--) s[i]=result[k-1-i];
s[k]='\0';
while(1)
{
if (strlen(s)!=strlen(a)&&s[0]=='0')
strcpy(s,s+1);
else
break;
}
}
4.精度计算——加法
语法:add(char a[],char b[],char s[]);
参数:
a[]:被乘数,用字符串表示,位数不限
b[]:乘数,用字符串表示,位数不限
t[]:结果,用字符串表示
返回值:null
注意:
空间复杂度为 o(n^2)
需要 string.h
源程序:
void add(char a[],char b[],char back[])
{
int i,j,k,up,x,y,z,l;
char *c;
if (strlen(a)>strlen(b)) l=strlen(a)+2; else l=strlen(b)+2;
c=(char *) malloc(l*sizeof(char));
i=strlen(a)-1;
j=strlen(b)-1;
k=0;up=0;
while(i>=0||j>=0)
{
if(i<0) x='0'; else x=a[i];
if(j<0) y='0'; else y=b[j];
z=x-'0'+y-'0';
if(up) z+=1;
if(z>9) {up=1;z%=10;} else up=0;
c[k++]=z+'0';
i--;j--;
}
if(up) c[k++]='1';
i=0;
c[k]='\0';
for(k-=1;k>=0;k--)
back[i++]=c[k];
back[i]='\0';
}
5.精度计算——减法
语法:sub(char s1[],char s2[],char t[]);
参数:
s1[]:被减数,用字符串表示,位数不限
s2[]:减数,用字符串表示,位数不限
t[]:结果,用字符串表示
返回值:null
注意:
默认s1>=s2,程序未处理负数情况
需要 string.h
源程序:
void sub(char s1[],char s2[],char t[])
{
int i,l2,l1,k;
l2=strlen(s2);l1=strlen(s1);
t[l1]='\0';l1--;
for (i=l2-1;i>=0;i--,l1--)
{
if (s1[l1]-s2[i]>=0)
t[l1]=s1[l1]-s2[i]+'0';
else
{
t[l1]=10+s1[l1]-s2[i]+'0';
s1[l1-1]=s1[l1-1]-1;
}
}
k=l1;
while(s1[k]<0) {s1[k]+=10;s1[k-1]-=1;k--;}
while(l1>=0) {t[l1]=s1[l1];l1--;}
loop:
if (t[0]=='0')
{
l1=strlen(s1);
for (i=0;i<l1-1;i++) t[i]=t[i+1];
t[l1-1]='\0';
goto loop;
}
if (strlen(t)==0) {t[0]='0';t[1]='\0';}
}
6.任意进制转换
语法:conversion(char s1[],char s2[],char t[]);
参数:
s[]:转换前的数字
s2[]:转换后的数字
d1:原进制数
d2:需要转换到的进制数
返回值:null
注意:
高于9的位数用大写'A'~'Z'表示,2~16位进制通过验证
源程序:
void conversion(char s[],char s2[],long d1,long d2)
{
long i,j,t,num;
char c;
num=0;
for (i=0;s[i]!='\0';i++)
{
if (s[i]<='9'&&s[i]>='0') t=s[i]-'0'; else t=s[i]-'A'+10;
num=num*d1+t;
}
i=0;
while(1)
{
t=num%d2;
if (t<=9) s2[i]=t+'0'; else s2[i]=t+'A'-10;
num/=d2;
if (num==0) break;
i++;
}
for (j=0;j<i/2;j++)
{c=s2[j];s2[j]=s[i-j];s2[i-j]=c;}
s2[i+1]='\0';
}
7.最大公约数、最小公倍数
语法:resulet=hcf(int a,int b)、result=lcd(int a,int b)
参数:
a:int a,求最大公约数或最小公倍数
b:int b,求最大公约数或最小公倍数
返回值:返回最大公约数(hcf)或最小公倍数(lcd)
注意:
lcd 需要连同 hcf 使用
源程序:
int hcf(int a,int b)
{
int r=0;
while(b!=0)
{
r=a%b;
a=b;
b=r;
}
return(a);
}
lcd(int u,int v,int h)
{
return(u*v/h);
}
8.组合序列
语法:m_of_n(int m, int n1, int m1, int* a, int head)
参数:
m:组合数C的上参数
n1:组合数C的下参数
m1:组合数C的上参数,递归之用
*a:1~n的整数序列数组
head:头指针
返回值:null
注意:
*a需要自行产生
初始调用时,m=m1、head=0
调用例子:求C(m,n)序列:m_of_n(m,n,m,a,0);
源程序:
void m_of_n(int m, int n1, int m1, int* a, int head)
{
int i,t;
if(m1<0 || m1>n1) return;
if(m1==n1)
{
for(i=0;i<m;i++) cout<<a[i]<<' '; // 输出序列
cout<<'\n';
return;
}
m_of_n(m,n1-1,m1,a,head); // 递归调用
t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;
m_of_n(m,n1-1,m1-1,a,head+1); // 再次递归调用
t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;
}
9.快速傅立叶变换(FFT)
语法:kkfft(double pr[],double pi[],int n,int k,double fr[],double fi[],int
l,int il);
参数:
pr[n]:输入的实部
pi[n]:数入的虚部
n,k:满足n=2^k
fr[n]:输出的实部
fi[n]:输出的虚部
l:逻辑开关,0 FFT,1 ifFT
il:逻辑开关,0 输出按实部/虚部;1 输出按模/幅角
返回值:null
注意:
需要 math.h
源程序:
void kkfft(pr,pi,n,k,fr,fi,l,il)
int n,k,l,il;
double pr[],pi[],fr[],fi[];
{
int it,m,is,i,j,nv,l0;
double p,q,s,vr,vi,poddr,poddi;
for (it=0; it<=n-1; it++)
{
m=it; is=0;
for (i=0; i<=k-1; i++)
{j=m/2; is=2*is+(m-2*j); m=j;}
fr[it]=pr[is]; fi[it]=pi[is];
}
pr[0]=1.0; pi[0]=0.0;
p=6.283185306/(1.0*n);
pr[1]=cos(p); pi[1]=-sin(p);
if (l!=0) pi[1]=-pi[1];
for (i=2; i<=n-1; i++)
{
p=pr[i-1]*pr[1];
q=pi[i-1]*pi[1];
s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
pr[i]=p-q; pi[i]=s-p-q;
}
for (it=0; it<=n-2; it=it+2)
{
vr=fr[it]; vi=fi[it];
fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];
fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];
}
m=n/2; nv=2;
for (l0=k-2; l0>=0; l0--)
{
m=m/2; nv=2*nv;
for (it=0; it<=(m-1)*nv; it=it+nv)
for (j=0; j<=(nv/2)-1; j++)
{
p=pr[m*j]*fr[it+j+nv/2];
q=pi[m*j]*fi[it+j+nv/2];
s=pr[m*j]+pi[m*j];
s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
poddr=p-q; poddi=s-p-q;
fr[it+j+nv/2]=fr[it+j]-poddr;
fi[it+j+nv/2]=fi[it+j]-poddi;
fr[it+j]=fr[it+j]+poddr;
fi[it+j]=fi[it+j]+poddi;
}
}
if (l!=0)
for (i=0; i<=n-1; i++)
{
fr[i]=fr[i]/(1.0*n);
fi[i]=fi[i]/(1.0*n);
}
if (il!=0)
for (i=0; i<=n-1; i++)
{
pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);
if (fabs(fr[i])<0.000001*fabs(fi[i]))
{
if ((fi[i]*fr[i])>0) pi[i]=90.0;
else pi[i]=-90.0;
}
else
pi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;
}
return;
}
10.Ronberg算法计算积分
语法:result=integral(double a,double b);
参数:
a:积分上限
b:积分下限
function f:积分函数
返回值:f在(a,b)之间的积分值
注意:
function f(x)需要自行修改,程序中用的是sina(x)/x
需要 math.h
默认精度要求是1e-5
源程序:
double f(double x)
{
return sin(x)/x; //在这里插入被积函数
}
double integral(double a,double b)
{
double h=b-a;
double t1=(1+f(b))*h/2.0;
int k=1;
double r1,r2,s1,s2,c1,c2,t2;
loop:
double s=0.0;
double x=a+h/2.0;
while(x<b)
{
s+=f(x);
x+=h;
}
t2=(t1+h*s)/2.0;
s2=t2+(t2-t1)/3.0;
if(k==1)
{
k++;h/=2.0;t1=t2;s1=s2;
goto loop;
}
c2=s2+(s2-s1)/15.0;
if(k==2){
c1=c2;k++;h/=2.0;
t1=t2;s1=s2;
goto loop;
}
r2=c2+(c2-c1)/63.0;
if(k==3){
r1=r2; c1=c2;k++;
h/=2.0;
t1=t2;s1=s2;
goto loop;
}
while(fabs(1-r1/r2)>1e-5){
r1=r2;c1=c2;k++;
h/=2.0;
t1=t2;s1=s2;
goto loop;
}
return r2;
}
11.行列式计算
语法:result=js(int s[][],int n)
参数:
s[][]:行列式存储数组
n:行列式维数,递归用
返回值:行列式值
注意:
函数中常数N为行列式维度,需自行定义
源程序:
int js(s,n)
int s[][N],n;
{
int z,j,k,r,total=0;
int b[N][N];/*b[N][N]用于存放,在矩阵s[N][N]中元素s[0]的余子式*/
if(n>2)
{
for(z=0;z<n;z++)
{
for(j=0;j<n-1;j++)
for(k=0;k<n-1;k++)
if(k>=z) b[j][k]=s[j+1][k+1]; else
b[j][k]=s[j+1][k];
if(z%2==0) r=s[0][z]*js(b,n-1); /*递归调用*/
else r=(-1)*s[0][z]*js(b,n-1);
total=total+r;
}
}
else if(n==2)
total=s[0][0]*s[1][1]-s[0][1]*s[1][0];
return total;
}
12.求排列组合数
语法:result=P(long n,long m); / result=long C(long n,long m);
参数:
m:排列组合的上系数
n:排列组合的下系数
返回值:排列组合数
注意:
符合数学规则:m<=n
源程序:
long P(long n,long m)
{
long p=1;
while(m!=0)
{p*=n;n--;m--;}
return p;
}
long C(long n,long m)
{
long i,c=1;
i=m;
while(i!=0)
{c*=n;n--;i--;}
while(m!=0)
{c/=m;m--;}
return c;
}
13.求某一天星期几
语法:result=weekday(int N,int M,int d)
参数:
N,M,d:年月日,例如:2003,11,4
返回值:0:星期天,1星期一……
注意:
需要math.h
适用于1582年10月15日之后, 因为罗马教皇格里高利十三世在这一天启用新历法.
源程序:
int weekday(int N,int M,int d)
{
int m,n,c,y,w;
m=(M-2)%12;
if (M>=3) n=N;else n=N-1;
c=n/100;
y=n%100;
w=(int)(d+floor(13*m/5)+y+floor(y/4)+floor(c/4)-2*c)%7;
while(w<0) w+=7;
return w;
}
二、字符串处理
1.字符串替换
语法:replace(char str[],char key[],char swap[]);
参数:
str[]:在此源字符串进行替换操作
key[]:被替换的字符串,不能为空串
swap[]:替换的字符串,可以为空串,为空串表示在源字符中删除key[]
返回值:null
注意:
默认str[]长度小于1000,如否,重新设定设定tmp大小
需要 string.h
源程序:
void replace(char str[],char key[],char swap[])
{
int l1,l2,l3,i,j,flag;
char tmp[1000];
l1=strlen(str);
l2=strlen(key);
l3=strlen(swap);
for (i=0;i<=l1-l2;i++)
{
flag=1;
for (j=0;j<l2;j++)
if (str[i+j]!=key[j]) {flag=0;break;}
if (flag)
{
strcpy(tmp,str);
strcpy(&tmp[i],swap);
strcpy(&tmp[i+l3],&str[i+l2]);
strcpy(str,tmp);
i+=l3-1;
l1=strlen(str);
}
}
}
2.字符串查找
语法:result=strfind(char str[],char key[]);
参数:
str[]:在此源字符串进行查找操作
key[]:被查找的字符串,不能为空串
返回值:如果查找成功,返回key在str中第一次出现的位置,否则返回-1
注意:
需要 string.h
源程序:
int strfind(char str[],char key[])
{
int l1,l2,i,j,flag;
l1=strlen(str);
l2=strlen(key);
for (i=0;i<=l1-l2;i++)
{
flag=1;
for (j=0;j<l2;j++)
if (str[i+j]!=key[j]) {flag=0;break;}
if (flag) return i;
}
return -1;
}
3.字符串截取
语法:mid(char str[],int start,int len,char strback[])
参数:
str[]:操作的目标字符串
start:从第start个字符串开始,截取长度为len的字符
len:从第start个字符串开始,截取长度为len的字符
strback[]:截取的到的字符
返回值:0:超出字符串长度,截取失败;1:截取成功
注意:
需要 string.h
源程序:
int mid(char str[],int start,int len,char strback[])
{
int l,i,k=0;
l=strlen(str);
if (start+len>l) return 0;
for (i=start;i<start+len;i++)
strback[k++]=str[i];
strback[k]='\0';
return 1;
}
4.LCS-最大公共子串长度
语法:result=lcs_len(char *a, char *b);
参数:
a,b[]:根据a,b生成最大公共子串
返回值:最大公共子串的长度
注意:
需要 string.h
M、N是a,b数组的最大可能长度
如果不需要生成公共子串,c[M][N]不可设置为全局变量
源程序:
#define M 20
#define N 20
int c[M][N];
int lcs_len(char *a, char *b)
{
int m=strlen(a),n=strlen(b),i,j;
for(i=0;i<=m;i++) c[i][0]=0;
for(j=0;j<=n;j++) c[0][j]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(a[i-1]==b[j-1])
c[i][j]=c[i-1][j-1]+1;
else if(c[i-1][j]>c[i][j-1])
c[i][j]=c[i-1][j];
else
c[i][j]=c[i][j-1];
}
return c[m][n];
}
5.LCS-最大公共子串长度
语法:result=build_lcs(char s[], char *a, int blen, int clen);
参数:
*a:生成公共子串的字符串a,b中的a
s[]:接受返回结果的字符串数组
blen:生成公共子串的字符串a,b中的b的长度
clen:最大公共子串的长度,通过lcs_len函数求得
返回值:最大公共子串的长度
注意:
需要 string.h
需要lcs_len函数求clen并且生成c[M][N]
可通过result=build_lcs返回指针或者通过build_lcs(s,a,blen,clen),用s接受结果
源程序:
char *build_lcs(char s[], char *a, int blen, int clen)
{
int k=clen,alen=strlen(a),i,j;
s[k]='\0';
i=alen,j=blen;
while(k>0)
{
if(c[i][j]==c[i-1][j])
i--;
else if(c[i][j]==c[i][j-1])
j--;
else
{
s[--k]=a[i-1];
i--;j--;
}
}
return s;
}
6.数字转换为字符
语法:cstr(int k,char o[]);
参数:
k:转换的数字
o[]:存储转换结果的字符串
返回值:null
注意:
需要 math.h
源程序:
void cstr(int k,char o[])
{
int len,i,t;
len=log10(k)+1;
for (i=len;i>0;i--)
{
t=k%10;
k-=t;k/=10;
o[i-1]='0'+t;
}
o[len]='\0';
}
三、计算几何
1.叉乘法求任意多边形面积
语法:result=polygonarea(Point *polygon,int N);
参数:
*polygon:多变形顶点数组
N:多边形顶点数目
返回值:多边形面积
注意:
支持任意多边形,凹、凸皆可
多边形顶点输入时按顺时针顺序排列
源程序:
typedef struct {
double x,y;
} Point;
double polygonarea(Point *polygon,int N)
{
int i,j;
double area = 0;
for (i=0;i<N;i++) {
j = (i + 1) % N;
area += polygon[i].x * polygon[j].y;
area -= polygon[i].y * polygon[j].x;
}
area /= 2;
return(area < 0 ? -area : area);
}
2.求三角形面积
语法:result=area3(float x1,float y1,float x2,float y2,float x3,float y3);
参数:
x1~3:三角形3个顶点x坐标
y1~3:三角形3个顶点y坐标
返回值:三角形面积
注意:
需要 math.h
源程序:
float area3(float x1,float y1,float x2,float y2,float x3,float y3)
{
float a,b,c,p,s;
a=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
b=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));
c=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));
p=(a+b+c)/2;
s=sqrt(p*(p-a)*(p-b)*(p-c));
return s;
}
3.两矢量间角度
语法:result=angle(double x1, double y1, double x2, double y2);
参数:
x/y1~2:两矢量的坐标
返回值:两的角度矢量
注意:
返回角度为弧度制,并且以逆时针方向为正方向
需要 math.h
源程序:
#define PI 3.1415926
double angle(double x1, double y1, double x2, double y2)
{
double dtheta,theta1,theta2;
theta1 = atan2(y1,x1);
theta2 = atan2(y2,x2);
dtheta = theta2 - theta1;
while (dtheta > PI)
dtheta -= PI*2;
while (dtheta < -PI)
dtheta += PI*2;
return(dtheta);
}
4.两点距离(2D、3D)
语法:result=distance_2d(float x1,float x2,float y1,float y2);
参数:
x/y/z1~2:各点的x、y、z坐标
返回值:两点之间的距离
注意:
需要 math.h
源程序:
float distance_2d(float x1,float x2,float y1,float y2)
{
return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
float distance_3d(float x1,float x2,float y1,float y2,float z1,float z2)
{
return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)));
}
5.射向法判断点是否在多边形内部
语法:result=insidepolygon(Point *polygon,int N,Point p);
参数:
*polygon:多边形顶点数组
N:多边形顶点个数
p:被判断点
返回值:0:点在多边形内部;1:点在多边形外部
注意:
若p点在多边形顶点或者边上,返回值不确定,需另行判断
需要 math.h
源程序:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
typedef struct {
double x,y;
} Point;
int insidepolygon(Point *polygon,int N,Point p)
{
int counter = 0;
int i;
double xinters;
Point p1,p2;
p1 = polygon[0];
for (i=1;i<=N;i++) {
p2 = polygon[i % N];
if (p.y > MIN(p1.y,p2.y)) {
if (p.y <= MAX(p1.y,p2.y)) {
if (p.x <= MAX(p1.x,p2.x)) {
if (p1.y != p2.y) {
xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
if (p1.x == p2.x || p.x <= xinters)
counter++;
}
}
}
}
p1 = p2;
}
if (counter % 2 == 0)
return(OUTSIDE);
else
return(INSIDE);
}
6.判断点是否在线段上
语法:result=Pointonline(Point p1,Point p2,Point p);
参数:
p1、p2:线段的两个端点
p:被判断点
返回值:0:点在不在线段上;1:点在线段上
注意:
若p线段端点上返回1
需要 math.h
源程序:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
typedef struct {
double x,y;
} Point;
int FC(double x1,double x2)
{
if (x1-x2<0.000002&&x1-x2>-0.000002) return 1; else return 0;
}
int Pointonline(Point p1,Point p2,Point p)
{
double x1,y1,x2,y2;
x1=p.x-p1.x;
x2=p2.x-p1.x;
y1=p.y-p1.y;
y2=p2.y-p1.y;
if (FC(x1*y2-x2*y1,0)==0) return 0;
if ((MIN(p1.x,p2.x)<=p.x&&p.x<=MAX(p1.x,p2.x))&&
(MIN(p1.y,p2.y)<=p.y&&p.y<=MAX(p1.y,p2.y)))
return 1; else return 0;
}
7.判断两线段是否相交
语法:result=lineintersect(Point p1,Point p2,Point p3,Point p4);
参数:
p1~4:两条线段的四个端点
返回值:0:两线段不相交;1:两线段相交;2两线段首尾相接
注意:
p1!=p2;p3!=p4;
源程序:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
typedef struct {
double x,y;
} Point;
int lineintersect(Point p1,Point p2,Point p3,Point p4)
{
Point tp1,tp2,tp3;
if
((p1.x==p3.x&&p1.y==p3.y)||(p1.x==p4.x&&p1.y==p4.y)||(p2.x==p3.x&&p2.y==p3.y)||(p2.x==p4.x&&p2.y==p4.y))
return 2;
//快速排斥试验
if
((MIN(p1.x,p2.x)<=p3.x&&p3.x<=MAX(p1.x,p2.x)&&MIN(p1.y,p2.y)<=p3.y&&p3.y<=MAX(p1.y,p2.y))||
(MIN(p1.x,p2.x)<=p4.x&&p4.x<=MAX(p1.x,p2.x)&&MIN(p1.y,p2.y)<=p4.y&&p4.y<=MAX(p1.y,p2.y)))
;else return 0;
//跨立试验
tp1.x=p1.x-p3.x;
tp1.y=p1.y-p3.y;
tp2.x=p4.x-p3.x;
tp2.y=p4.y-p3.y;
tp3.x=p2.x-p3.x;
tp3.y=p2.y-p3.y;
if ((tp1.x*tp2.y-tp1.y*tp2.x)*(tp2.x*tp3.y-tp2.y*tp3.x)>=0) return 1;
else return 0;
}
8.判断线段与直线是否相交
语法:result=lineintersect(Point p1,Point p2,Point p3,Point p4);
参数:
p1、p2:线段的两个端点
p3、p4:直线上的两个点
返回值:0:线段直线不相交;1:线段和直线相交
注意:
如线段在直线上,返回 1
源程序:
typedef struct {
double x,y;
} Point;
int lineintersect(Point p1,Point p2,Point p3,Point p4)
{
Point tp1,tp2,tp3;
tp1.x=p1.x-p3.x;
tp1.y=p1.y-p3.y;
tp2.x=p4.x-p3.x;
tp2.y=p4.y-p3.y;
tp3.x=p2.x-p3.x;
tp3.y=p2.y-p3.y;
if ((tp1.x*tp2.y-tp1.y*tp2.x)*(tp2.x*tp3.y-tp2.y*tp3.x)>=0) return 1;
else return 0;
}
9.点到线段最短距离
语法:result=mindistance(Point p1,Point p2,Point q);
参数:
p1、p2:线段的两个端点
q:判断点
返回值:点q到线段p1p2的距离
注意:
需要 math.h
源程序:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
typedef struct {
double x,y;
} Point;
double mindistance(Point p1,Point p2,Point q)
{
int flag=1;
double k;
Point s;
if (p1.x==p2.x) {s.x=p1.x;s.y=q.y;flag=0;}
if (p1.y==p2.y) {s.x=q.x;s.y=p1.y;flag=0;}
if (flag)
{
k=(p2.y-p1.y)/(p2.x-p1.x);
s.x=(k*k*p1.x+k*(q.y-p1.y)+q.x)/(k*k+1);
s.y=k*(s.x-p1.x)+p1.y;
}
if (MIN(p1.x,p2.x)<=s.x&&s.x<=MAX(p1.x,p2.x))
return sqrt((q.x-s.x)*(q.x-s.x)+(q.y-s.y)*(q.y-s.y));
else
return
MIN(sqrt((q.x-p1.x)*(q.x-p1.x)+(q.y-p1.y)*(q.y-p1.y)),sqrt((q.x-p2.x)*(q.x-p2.x)+(q.y-p2.y)*(q.y-p2.y)));
}
10.求两直线的交点
语法:result=mindistance(Point p1,Point p2,Point q);
参数:
p1~p4:直线上不相同的两点
*p:通过指针返回结果
返回值:1:两直线相交;2:两直线平行
注意:
如需要判断两线段交点,检验k和对应k1(注释中)的值是否在0~1之间,用在0~1之间的那个求交点
源程序:
typedef struct {
double x,y;
} Point;
int linecorss(Point p1,Point p2,Point p3,Point p4,Point *p)
{
double k;
if ((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)==0) return 0;
if ((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x)==0&&
(p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x)==0) return 0;
k=((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y));
//k1=((p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y));
(*p).x=p1.x+k*(p2.x-p1.x);
(*p).y=p1.y+k*(p2.y-p1.y);
return 1;
}
11.判断一个封闭图形是凹集还是凸集
语法:result=convex(Point *p,int n);
参数:
*p:封闭曲线顶点数组
n:封闭曲线顶点个数
返回值:1:凸集;-1:凹集;0:曲线不符合要求无法计算
注意:
默认曲线为简单曲线:无交叉、无圈
源程序:
typedef struct {
double x,y;
} Point;
int convex(Point *p,int n)
{
int i,j,k;
int flag = 0;
double z;
if (n < 3)
return(0);
for (i=0;i<n;i++) {
j = (i + 1) % n;
k = (i + 2) % n;
z = (p[j].x - p[i].x) * (p[k].y - p[j].y);
z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);
if (z < 0)
flag |= 1;
else if (z > 0)
flag |= 2;
if (flag == 3)
return -1; //CONCAVE
}
if (flag != 0)
return 1; //CONVEX
else
return 0;
}
12.Graham扫描法寻找凸包
语法:Graham_scan(Point PointSet[],Point ch[],int n,int &len);
参数:
PointSet[]:输入的点集
ch[]:输出的凸包上的点集,按照逆时针方向排列
n:PointSet中的点的数目
len:输出的凸包上的点的个数
返回值:null
源程序:
struct Point{
float x,y;
};
float multiply(Point p1,Point p2,Point p0)
{
return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}
float distance(Point p1,Point p2)
{
return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
}
void Graham_scan(Point PointSet[],Point ch[],int n,int &len)
{
int i,j,k=0,top=2;
Point tmp;
for(i=1;i<n;i++)
if
((PointSet[i].y<PointSet[k].y)||((PointSet[i].y==PointSet[k].y)&&(PointSet[i].x<PointSet[k].x)))
k=i;
tmp=PointSet[0];
PointSet[0]=PointSet[k];
PointSet[k]=tmp;
for (i=1;i<n-1;i++)
{
k=i;
for (j=i+1;j<n;j++)
if ( (multiply(PointSet[j],PointSet[k],PointSet[0])>0) ||
((multiply(PointSet[j],PointSet[k],PointSet[0])==0)
&&(distance(PointSet[0],PointSet[j])<distance(PointSet[0],PointSet[k])))
)
k=j;
tmp=PointSet[i];
PointSet[i]=PointSet[k];
PointSet[k]=tmp;
}
ch[0]=PointSet[0];
ch[1]=PointSet[1];
ch[2]=PointSet[2];
for (i=3;i<n;i++)
{
while (multiply(PointSet[i],ch[top],ch[top-1])>=0) top--;
ch[++top]=PointSet[i];
}
len=top+1;
}
13.求两条线段的交点
语法:Result=IntersectPoint (Point p1,Point p2,Point p3,Point p4,Point &p);
参数:
P1~P4:两条线断4个端点
P:线段交点
返回值:如果两条线段平行无交点,返回 0,否则返回 1
源程序:
struct Point{
float x,y;
};
int IntersectPoint (Point p1,Point p2,Point p3,Point p4,Point &p)
{
float a,b,c,d,e,f;
a=p2.y-p1.y;
b=p1.x-p2.x;
c=p1.y*(p2.x-p1.x)+p1.x*(p2.y-p1.y);
d=p4.y-p3.y;
e=p3.x-p4.x;
f=p3.y*(p4.x-p3.x)+p1.x*(p4.y-p3.y);
if (a*e==b*d)
return 0;
else
{
p.x=(e*c-b*f)/(b*d-a*e);
p.y=(d*c-a*f)/(a*e-b*d);
return 1;
}
}
四、数论
1.x的二进制长度
语法:result=BitLength(int x);
参数:
x:测长的x
返回值:x的二进制长度
源程序:
int BitLength(int x)
{
int d = 0;
while (x > 0) {
x >>= 1;
d++;
}
return d;
}
2.返回x的二进制表示中从低到高的第i位
语法:result=BitAt(int x, int i);
参数:
x:十进制 x
i:要求二进制的第i位
返回值:返回x的二进制表示中从低到高的第i位
注意:
最低位为第一位
源程序:
int BitAt(int x, int i)
{
return ( x & (1 << (i-1)) );
}
3.模取幂运算
语法:result=Modular_Expoent(int a,int b,int n);
参数:
a、b、n:a^b mod n 的对应参数
返回值:a^b mod n 的值
注意:
需要BitLength和BitAt
源程序:
int Modular_Expoent(int a,int b,int n)
{
int i, y=1;
for (i = BitLength(b); i > 0; i--)
{
y = (y*y)%n;
if (BitAt(b,i) > 0)
y = (y*a)%n;
}
return y;
}
4.求解模线性方程
语法:result=modular_equation(int a,int b,int n);
参数:
a、b、n:ax=b (mod n) 的对应参数
返回值:方程的解
源程序:
int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by
{
int t,d;
if (b==0) {x=1;y=0;return a;}
d=ext_euclid(b,a %b,x,y);
t=x;
x=y;
y=t-a/b*y;
return d;
}
void modular_equation(int a,int b,int n)
{
int e,i,d;
int x,y;
d=ext_euclid(a,n,x,y);
if (b%d>0)
printf("No answer!\n");
else
{
e=(x*(b/d))%n;
for (i=0;i<d;i++)
printf("The %dth answer is : %ld\n",i+1,(e+i*(n/d))%n);
}
}
5.求解模线性方程组(中国余数定理)
语法:result=Modular_Expoent(int a,int b,int n);
参数:
B[]、W[]:a=B[] (mod W[]) 的对应参数
返回值:a 的值
注意:
其中W[],B[]已知,W[i]>0且W[i]与W[j]互质, 求a
源程序:
int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by
{
int t,d;
if (b==0) {x=1;y=0;return a;}
d=ext_euclid(b,a %b,x,y);
t=x;
x=y;
y=t-a/b*y;
return d;
}
int China(int B[],int W[],int k)
{
int i;
int d,x,y,a=0,m,n=1;
for (i=0;i<k;i++)
n*=W[i];
for (i=0;i<k;i++)
{
m=n/W[i];
d=ext_euclid(W[i],m,x,y);
a=(a+y*m*B[i])%n;
}
if (a>0) return a;
else return(a+n);
}
6.筛法素数产生器
语法:result=prime(int a[],int n);
参数:
a[]:用于返回素数的数组
n:产生n以内的素数,按升序放入a[]中
返回值:n以内素数的个数
注意:
其中W[],B[]已知,W[i]>0且W[i]与W[j]互质, 求a
源程序:
int prime(int a[],int n)
{
int i,j,k,x,num,*b;
n++;
n/=2;
b=new int[(n+1)*2];
a[0]=2;a[1]=3;num=2;
for(i=1;i<=2*n;i++)
b[i]=0;
for(i=3;i<=n;i+=3)
for(j=0;j<2;j++)
{
x=2*(i+j)-1;
while(b[x]==0)
{
a[num++]=x;
for(k=x;k<=2*n;k+=x)
b[k]=1;
}
}
return num;
}
7.判断一个数是否素数
语法:result=comp(int n);
参数:
n:判断n是否素数
返回值:素数返回1,否则返回0
源程序:
//传统方法
int comp(int n){
if(n<2)return 0;
if(n%2==0)return 0;
for(int i=3;i<=sqrt(n);i+=2) if(n%i==0) return 0;
return 1;
}
//大数素数判定,(1/4)^K出错概率
int powermod(int a,int b,int n)
{//get (a^b)%n
i64 d=1, t=a;
while(b>0){
if(t==1)return d;
if(b%2==1)d=(t*d)%n;
b/=2; t=(t*t)%n;
}
return d;
}
int isprime(int n,int k){
int a;
while(k--){
a=rand();
a%=n-3; a+=2;
if(powermod(k+2,n-1,n)!=1)return 0;
}
return 1;
}
8.求距阵最大和
语法:result=maxsum2(int n);
参数:
a:距阵
n,m:距阵行列数
返回值:一维,二维距阵最大和
源程序:
int a[101][101];
int maxsum(int a[],int n)//一维最大串
{
int sum=-10000000,b=0;
int i;
for(i=0;i<n;i++)
{
if (b>0)
b+=a[i];
else
b=a[i];
if(b>sum)
sum=b;
}
return sum;
}
int maxsum2(int m,int n)//二维最大串
{
int sum = -10000000;
int i,j,k,max;
int* b = new int[n+1];
for (i=0;i<m;i++)
{
for(k=0;k<n;k++)
b[k]=a[i][k];
max = maxsum(b,n);//第i列的一维最大串
if(max>sum)
sum=max;
for(j=i+1;j<m;j++)
{
for (k=0;k<=n;k++)b[k]+=a[j][k];
max = maxsum(b,n);//类似maxsum,通过每列相加求二维最大串
if(max>sum)sum=max;
}
}
delete []b;
return sum;
}
8.求一个数每一位相加之和
语法:result=digadd(int n)
参数:
n:待求数字
返回值:各数字之和
源程序:
int digadd(int n)
{
int i=0,k=0;
while(i=n%10,n/=10) k+=i;
return k+i;
}
10.质因数分解
语法:result=int reduce(int prime[],int pn,int n,int rest[])
参数:
Prime[]:素数表,至少需要达到sqrt(n)
pn:素数表的元素个数
N:待分解的数
Rest:分解结果,按照升序排列
返回值:分解因子个数
源程序:
int reduce(int prime[],int pn,int n,int rest[])
{
int i,k=0;
for(i=0;i<pn;i++)
{
if (n==1) break;
if (prime[i]*prime[i]>n) {rest[k++]=n;break;}
while(n%prime[i]==0)
{
n/=prime[i];
rest[k++]=prime[i];
}
}
return k;
}
11.高斯消元法解线性方程组
语法:gauss(int n,double ** a)
参数:
N:变量个数
Rest:变量系数行列式
源程序:
void gauss(int n,double **a)
{
int i, j, k;
double client, temp = 0.0;
for(k = 0; k < n - 1; k++)
for(i = k + 1; i < n; i++)
{
client = a[i][k]/a[k][k];
for(j = k + 1; j < n; j++)
a[i][j] = a[i][j] - client * a[k][j];
a[i][n] = a[j - 1][n] - client * a[k][n];
}
a[n - 1][n] = a[n - 1][n]/a[n - 1][n - 1];
for(i = n - 2; i >= 0; i--)
{
for (j = i + 1; j < n; j++)
temp += a[i][j] * a[j][n];
a[i][n] = (a[i][n] - temp) / a[i][i];
}
}
//打印
//for(i = 0; i < n; i++)
// printf("X%d = %lf\n", i + 1, a[i][n]);
五、图论
1.Prim算法求最小生成树
语法:prim(Graph G,int vcount,int father[]);
参数:
G:图,用邻接矩阵表示
vcount:表示图的顶点个数
father[]:用来记录每个节点的父节点
返回值:null
注意:
常数max_vertexes为图最大节点数
常数infinity为无穷大
源程序:
#define infinity 1000000
#define max_vertexes 5
typedef int Graph[max_vertexes][max_vertexes];
void prim(Graph G,int vcount,int father[])
{
int i,j,k;
int lowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes];
for (i=0;i<vcount;i++)
{
lowcost[i]=G[0][i];
closeset[i]=0;
used[i]=0;
father[i]=-1;
}
used[0]=1;
for (i=1;i<vcount;i++)
{
j=0;
while (used[j]) j++;
for (k=0;k<vcount;k++)
if ((!used[k])&&(lowcost[k]<lowcost[j])) j=k;
father[j]=closeset[j];
used[j]=1;
for (k=0;k<vcount;k++)
if (!used[k]&&(G[j][k]<lowcost[k]))
{ lowcost[k]=G[j][k];
closeset[k]=j; }
}
}
2.Dijkstra算法求单源最短路径
语法:result=Dijkstra(Graph G,int n,int s,int t, int path[]);
参数:
G:图,用邻接矩阵表示
n:图的顶点个数
s:开始节点
t:目标节点
path[]:用于返回由开始节点到目标节点的路径
返回值:最短路径长度
注意:
输入的图的权必须非负
顶点标号从0开始
用如下方法打印路径:
i=t;
while (i!=s)
{
printf("%d<--",i+1);
i=path[i];
}
printf("%d\n",s+1);
源程序:
int Dijkstra(Graph G,int n,int s,int t, int path[])
{
int i,j,w,minc,d[max_vertexes],mark[max_vertexes];
for (i=0;i<n;i++) mark[i]=0;
for (i=0;i<n;i++)
{ d[i]=G[s][i];
path[i]=s; }
mark[s]=1;path[s]=0;d[s]=0;
for (i=1;i<n;i++)
{
minc=infinity;
w=0;
for (j=0;j<n;j++)
if ((mark[j]==0)&&(minc>=d[j])) {minc=d[j];w=j;}
mark[w]=1;
for (j=0;j<n;j++)
if ((mark[j]==0)&&(G[w][j]!=infinity)&&(d[j]>d[w]+G[w][j]))
{ d[j]=d[w]+G[w][j];
path[j]=w; }
}
return d[t];
}
3.Bellman-ford算法求单源最短路径
语法:result=Bellman_ford(Graph G,int n,int s,int t,int path[],int success);
参数:
G:图,用邻接矩阵表示
n:图的顶点个数
s:开始节点
t:目标节点
path[]:用于返回由开始节点到目标节点的路径
success:函数是否执行成功
返回值:最短路径长度
注意:
输入的图的权可以为负,如果存在一个从源点可达的权为负的回路则success=0
顶点标号从0开始
用如下方法打印路径:
i=t;
while (i!=s)
{
printf("%d<--",i+1);
i=path[i];
}
printf("%d\n",s+1);
源程序:
int Bellman_ford(Graph G,int n,int s,int t,int path[],int success)
{
int i,j,k,d[max_vertexes];
for (i=0;i<n;i++) {d[i]=infinity;path[i]=0;}
d[s]=0;
for (k=1;k<n;k++)
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (d[j]>d[i]+G[i][j]) {d[j]=d[i]+G[i][j];path[j]=i;}
success=0;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (d[j]>d[i]+G[i][j]) return 0;
success=1;
return d[t];
}
4.Floyd-Warshall算法求每对节点间最短路径
语法:Floyd_Washall(Graph G,int n,Graph D,Graph P);
参数:
G:图,用邻接矩阵表示
n:图的顶点个数
D:D[i,j]表示从i到j的最短距离
P:P[i,j]表示从i到j的最短路径上j 的父节点
返回值:null
源程序:
void Floyd_Washall(Graph G,int n,Graph D,Graph P)
{
int i,j,k;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
{ D[i][j]=G[i][j];
P[i][j]=i; }
for (i=0;i<n;i++) { D[i][i]=0;P[i][i]=0; }
for (k=0;k<n;k++)
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (D[i][j]>D[i][k]+D[k][j])
{ D[i][j]=D[i][k]+D[k][j];
P[i][j]=P[k][j]; }
}
5.解欧拉图
语法:int Eular(int graph[8][8], int v, int *path)
参数:
graph:图,用邻接矩阵表示
v:图的顶点个数
path:D[i,j]表示从i到j的最短距离
注意:
此函数会删除图中的边
返回值:若找到欧拉回路则返回路径长度,否则返回-1
源程序:
int Eular(int graph[8][8], int v, int *path)
{
int start,a,b,count=0, deg,i;
int s[1000], sp=0;//栈,大小可根据需要改变
start=0;
while(true)
{
a=start;
s[sp++]=a;
for(b=-1,i=0;i<v;i++) if (graph[i][a]&& a!=i) {b=i;break;}
for(;b!=start&&b!=-1;)
{
s[sp++]=b;
graph[a][b]=graph[b][a]=0;
a=b;
for(b=-1,i=0;i<v;i++) if (graph[i][a]&& a!=i) {b=i;break;}
}
if (b==-1) return(-1);//若找不到Eular回路返回-1
s[sp++]=b;
graph[a][b]=graph[b][a]=0;
while(sp>0)
{
b=s[--sp];
for(i=0,deg=0;i<v;i++) if (graph[i][b]==1) {deg++; break;}
if (deg>0) break;
path[count++]=b;
}
if (sp==0) return(count);
start=b;
}
}
六、排序/查找
1.快速排序
语法:quicksort(int l,int r,int b[]);
参数:
l:排序上界,开始时l=0
r:排序下界,开始时r=数组元素个数
b[]:被排序的元素
返回值:null
注意:
输出升序序列
源程序:
void quicksort(int l,int r,int b[])
{
int i,j,x;
if(l>=r) return;
i=l;
j=r;
x=b[i];
while(i!=j)
{
while(b[j]>x&&j>i) j--;
if(i<j)
{
b[i]=b[j];
i++;
}
while(b[i]<x&&j>i)i++;
if(i<j)
{
b[j]=b[i];
j--;
}
}
b[i]=x;
quicksort(l,j-1,b);
quicksort(i+1,r,b);
}
2.希尔排序
语法:shellsort(int a[],int n);
参数:
n:数组元素个数
a[]:待排序数组
返回值:null
注意:
输出升序序列
源程序:
void shellsort(int a[],int n)
{
int i,j,g;
int temp,k;
g=n/2;
while(g!=0)
{
for(i=g+1;i<=n;i++)
{
temp=a[i];
j=i-g;
while(j>0)
{
k=j+g;
if(a[j]<=a[k])
j=0;
else
{
temp=a[j];a[j]=a[k];a[k]=temp;
}
j=j-g;
}
}
g=g/2;
}
}
3.选择法排序
语法:sort(int t[],int n);
参数:
t[]:待排序数组
n:数组t[]元素的个数
返回值:null
注意:
输出升序序列
小规模排序用
源程序:
void sort(int t[],int n)
{
int i,j,k,temp;
for (i=0;i<n;i++)
{
k=i;
for (j=i;j<n;j++) if (t[j]<t[k]) k=j;
temp=t[i];t[i]=t[k];t[k]=temp;
}
}
4.二分查找
语法:result=search_bin(int *t,int k);
参数:
t[]:待查找数组
k:查找关键字
返回值:如果k在t[]中存在,输出i:t[i]=k,否则输出-1
注意:
要求查找数组是有序升序序列
源程序:
int search_bin(int *t,int k)
{
int low=1,high=10,mid;
while (low<=high)
{
mid=(low+high)/2;
if (k==t[mid]) return mid;
else if (k<t[mid]) high=mid-1;
else low=mid+1;
}
return -1;
}
七、数据结构
1.顺序队列
源程序:
#define maxsize 100
typedef struct
{
int data[maxsize];
int front;
int rear;
} sqqueue;
int sqinit(sqqueue *p) //队列初始化
{
p->front=0;
p->rear=0;
return 1;
}
int enqueue(sqqueue *q, int e) //入队
{
if((q->rear+1)%maxsize==q->front)
return 0;
else
q->data[q->rear]=e;
q->rear=(q->rear+1)%maxsize;
return 1;
}
int dequeue(sqqueue *q) //出队
{
int e;
if (q->front==q->rear)
return 0;
e=q->data[q->front];
q->front=(q->front+1)%maxsize;
return e;
}
int empty(sqqueue *q) //判空
{
int v;
if (q->front==q->rear)
v=1;
else
v=0;
return v;
}
int gethead(sqqueue *q) //取得头元素
{
int e;
if (q->front==q->rear)
e=-1;
else
e=q->data[q->front];
return e;
}
void display(sqqueue *q) //显示所有元素
{
int s;
s=q->front;
printf("the sequeue is display:\n");
if (q->front==q->rear)
printf("the sequeue is empty!");
else
{
while(s<q->rear)
{
printf("->%d", q->data[s]);
s=(s+1)%maxsize;
}
printf("\n");
}
}
main(sqqueue *head) //函数使用样例
{
int n,i,m,x,y,select,xq;
printf("create a empty sequeue\n");
sqinit(head);
printf("please input the sequeue length:\n");
scanf("%d",&n);
for (i=0;i<n;i++)
{
printf("please input a sequeue value:\n");
scanf("%d",&m);
enqueue(head,m);
}
printf("head->rear:%d\n",head->rear);
printf("head->front:%d\n",head->front);
display(head);
printf("select 1 **** enqueue() \n");
printf("select 2 **** dequeue() \n");
printf("select 3 **** empty () \n");
printf("select 4 **** gethead() \n");
printf("select 5 **** display() \n");
printf("please select (1--5):");
scanf("%d",&select);
switch(select)
{
case 1:
{
printf("please input a value :\n ");
scanf("%d",&x);
enqueue(head,x);
display(head);
break;
}
case 2:
{
dequeue(head);
display(head);
break;
}
case 3:
{
if(empty(head))
printf("the sequeue is empty");
else
printf("the sequeue is full");
}
case 4:
{
y=gethead(head);
printf("output head value:%d\n",y);
break;
}
case 5:
{
display(head);
break;
}
}
}
}
2.顺序栈
源程序:
#define m 100
typedef struct
{
int stack[m];
int top;
} stackstru;
init(stackstru *s) /*装入栈*/
{
s->top=0;
return 1;
}
int push(stackstru *s,int x) /*入栈操作*/
{
if (s->top==m)
printf("the stack is overflow!\n");
else
{
s->top=s->top+1;
s->stack[s->top]=x;
}
}
void display(stackstru *s) /*显示栈所有数据*/
{
if(s->top==0)
printf("the stack is empty!\n");
else
{
while(s->top!=0)
{
printf("%d->",s->stack[s->top]);
s->top=s->top-1;
}
}
}
int pop(stackstru *s) /*出栈操作并返回被删除的那个记录*/
{
int y;
if(s->top==0)
printf("the stack is empty!\n");
else
{
y=s->stack[s->top];
s->top=s->top-1;
return y;
}
}
int gettop(stackstru *s) /*得到栈顶数*/
{
int e;
if(s->top==0)
return 0;
else
e=s->stack[s->top];
return e;
}
main(stackstru *p) //函数使用演示
{
int n,i,k,h,x1,x2,select;
printf("create a empty stack!\n");
init(p);
printf("input a stack length:\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("input a stack value:\n");
scanf("%d",&k);
push(p,k);
}
printf("select 1:display()\n");
printf("select 2:push()\n");
printf("select 3:pop()\n");
printf("select 4:gettop()\n");
printf("input a your select(1-4):\n");
scanf("%d",&select);
switch(select)
{
case 1:
{
display(p);
break;
}
case 2:
{
printf("input a push a value:\n");
scanf("%d",&h);
push(p,h);
display(p);
break;
}
case 3:
{
x1=pop(p);
printf("x1->%d\n",x1);
display(p);
break;
}
case 4:
{
x2=gettop(p);
printf("x2->%d",x2);
break;
}
}
}
3.链表
源程序:
# define null 0
typedef char ElemType; /* 字符型数据*/
typedef struct LNode
{
ElemType data;
struct LNode *next;
};
setnull(struct LNode **p);
int length (struct LNode **p);
ElemType get(struct LNode **p,int i);
void insert(struct LNode **p,ElemType x,int i);
int delete(struct LNode **p,int i);
void display(struct LNode **p);
main()
{
struct LNode *head,*q; /*定义静态变量*/
int select,x1,x2,x3,x4;
int i,n;
int m,g;
char e,y;
head=setnull(&head); /*建议链表并设置为空表*/
printf("请输入数据长度: ");
scanf("%d",&n);
for(i=1;i<n;i++);
{
printf("将数据插入到单链表中: ");
scanf("%d",&y);
insert(&head,y,i);} /*插入数据到链表*/
display(&head); /*显示链表所有数据*/
printf("select 1 求长度 length()\n");
printf("select 2 取结点 get()\n");
printf("select 3 求值查找 locate()\n");
printf("select 4 删除结点 delete()\n");
printf("input your select: ");
scanf("%d",&select);
switch(select)
{
case 1:
{
x1=length(&head);
printf("输出单链表的长度%d ",x1);
display(&head);
}break;
case 2:
{
printf("请输入要取得结点: ");
scanf("%d",&m);
x2=get(&head,m);
printf(x2);
display(&head);
}break;
case 3:
{
printf("请输入要查找的数据: ");
scanf("%d",&e);
x3=locate(&head,e);
printf(x3);
display(&head);
}break;
case 4:
{
printf("请输入要删除的结点: ");
scanf("%d",&g);
x4=delete(&head,g);
printf(x4);
display(&head);
}break;
}
}
}
setnull(struct LNode **p)
{
*p=null;
}
int length (struct LNode **p)
{
int n=0;
struct LNode *q=*p;
while (q!=null)
{
n++;
q=q->next;
}
return(n);
}
ElemType get(struct LNode **p,int i)
{
int j=1;
struct LNode *q=*p;
while (j<i&&q!=null)
{
q=q->next;
j++;
}
if(q!=null)
return(q->data);
else
printf("位置参数不正确!\n");
}
int locate(struct LNode **p,ElemType x)
{
int n=0;
struct LNode *q=*p;
while (q!=null&&q->data!=x)
{
q=q->next;
n++;
}
if(q==null)
return(-1);
else
return(n+1);
}
void insert(struct LNode **p,ElemType x,int i)
{
int j=1;
struct LNode *s,*q;
s=(struct LNode *)malloc(sizeof(struct LNode));
s->data=x;
q=*p;
if(i==1)
{
s->next=q;
p=s;
}
else
{
while(j<i-1&&q->next!=null)
{
q=q->next;
j++;
}
if(j==i-1)
{
s->next=q->next;
q->next=s;
}
else
printf("位置参数不正确!\n");
}
}
int delete(struct LNode **p,int i)
{
int j=1;
struct LNode *q=*p,*t;
if(i==1)
{
t=q;
*p=q->next;
}
else
{
while(j<i-1&&q->next!=null)
{
q=q->next;
j++;
}
if(q->next!=null&&j==i-1)
{
t=q->next;
q->next=t->next;
}
else
printf("位置参数不正确!\n");
}
if(t=null)
free(t);
}
void display(struct LNode **p)
{
struct LNode *q;
q=*p;
printf("单链表显示: ");
if(q==null)
printf("链表为空!");
else if (q->next==null)
printf("%c\n",q->data);
else
{
while(q->next!=null)
{
printf("%c->",q->data);
q=q->next;
}
printf("%c",q->data);
}
printf("\n");
}
4.链栈
源程序:
# define null 0
typedef struct stacknode
{
int data;
struct stacknode *next;
} stacklink;
typedef struct
{
stacklink *top;
int stacksize;
}stackk;
initlink(stackk *s)
{
s->top=(stacklink *)malloc(sizeof(stacklink));
s->top->data=0;
s->top->next=null;
}
int poplink(stackk *s)
{
stackk *p;int v;
if(s->top->next==null) printf("the stackis empty\n");
else
{
v=s->top->next->data;
p=s->top->next;
s->top=s->top->next;
}
free(p);
return v;
}
}
int pushlink(stackk *s,int x)
{
stackk *p;
p=(stacklink *)malloc(sizeof(stacklink));
p->data=x;
p->next=s->top->next;
s->top->next=p;
}
int gettop(stackk *s)
{
int e;
if(s==null) printf("the stack is empty!\n");
e=s->top->next->data;
return e;
}
display(stackk *s)
{
stackk *p;
p=s->top->next;
printf("display the stacklink:\n");
if (s->top=null) printf("the stacklink is empty!\n");
else
{
while(p)
{
printf("->%d",p->data);
p=p->next;
}
}
}
main(stacklink *p)
{
int n,k,i,select,h,x1,x2;
printf("create a empty stacklink!\n");
initlink(p);
printf("input a stacklink length:\n");
scanf("%d",&n);
for (i=1;i<=n;i++)
{printf("input a stacklink value:\n");
scanf("%d",&k);
pushlink(p,k);
}
printf("select 1:display()\n");
printf("select 2:pushlink()\n");
printf("select 3:poplink()\n");
printf("select 4:gettop()\n");
printf("input a your select(1-4):\n");
scanf("%d",&select);
switch(select)
{case 1:
{display(p);break;}
case 2:
{printf("input a push a value :\n");
scanf("%d",&h);
pushlink(p,h);
display(p);
break;}
case 3:
{x1=poplink(p);printf("x1->%d\n",x1);
display(p);
break;}
case 4:
{x2=gettop(p);printf("x2->%d",x2);
break;}
}
}
5.二叉树
源程序:
typedef struct bitnode
{
char data;
struct bitnode *lchild, *rchild;
}bitnode, *bitree;
void createbitree(t,n)
bitnode ** t;
int *n;
{
char x;
bitnode *q;
*n=*n+1;
printf("\n Input %d DATA:",*n);
x=getchar();
if(x!='\n') getchar();
if (x=='\n')
return;
q=(bitnode*)malloc(sizeof(bitnode));
q->data=x;
q->lchild=NULL;
q->rchild=NULL;
*t=q;
printf(" This Address is: %o, Data is: %c,\n Left Pointer is: %o,
Right Pointer is: %o",q,q->data,q->lchild,q->rchild);
createbitree(&q->lchild,n);
createbitree(&q->rchild,n);
return;
}
void visit(e)
bitnode *e;
{
printf(" Address: %o, Data: %c, Left Pointer: %o, Right Pointer:
%o\n",e,e->data,e->lchild,e->rchild);
}
void preordertraverse(t)
bitnode *t;
{
if(t)
{
visit(t);
preordertraverse(t->lchild);
preordertraverse(t->rchild);
return ;
}
else
return ;
}
void countleaf(t,c)
bitnode *t;
int *c;
{
if(t!=NULL)
{
if (t->lchild==NULL && t->rchild==NULL)
{*c=*c+1;
}
countleaf(t->lchild,c);
countleaf(t->rchild,c);
}
return;
}
int treehigh(t)
bitnode *t;
{
int lh,rh,h;
if(t==NULL)
h=0;
else
{
lh=treehigh(t->lchild);
rh=treehigh(t->rchild);
h=(lh>rh ? lh:rh)+1;
}
return h;
}
main()
{
bitnode *t; int count=0;
int n=0;
printf("\n Please input TREE Data:\n");
createbitree(&t,&n);
printf("\n This is TREE struct: \n");
preordertraverse(t);
countleaf(t,&count);
printf("\n This TREE has %d leaves ",count);
printf(" , High of The TREE is: %d\n",treehigh(t));
}
八、高精度运算专题
1.专题函数说明
说明:
本栏为本专题所有程序的公用部分,调用本专题任何一个程序必须加上本栏的代码
input/print为高精度数输入输出,调用格式为input(hp HightPoint,"123456")/print(hp
HighPoint)
本栏为纯C++代码
源程序:
#include <iostream>
using namespace std;
#define maxsize 100
struct hp
{
int len;
int s[maxsize+1];
};
void input(hp &a,string str)
{
int i;
while(str[0]=='0' && str.size()!=1)
str.erase(0,1);
a.len=(int)str.size();
for(i=1;i<=a.len;++i)
a.s[i]=str[a.len-i]-48;
for (i=a.len+1;i<=maxsize;++i)
a.s[i]=0;
}
void print(const hp &y)
{
int i;
for(i=y.len;i>=1;i--)
cout<<y.s[i];
cout<<endl;
}
2.高精度数比较
语法:int result=compare(const hp &a,const hp &b);
参数:
a,b:进行比较的高精度数字
返回值:比较结果,a>b返回正数,a=b返回0,a<b返回负数
源程序:
int compare(const hp &a,const hp &b)
{
int len;
if(a.len>b.len)
len=a.len;
else
len=b.len;
while(len>0 && a.s[len]==b.s[len]) len--;
if(len==0)
return 0;
else
return a.s[len]-b.s[len];
}
3.高精度数加法
语法:plus(const hp &a,const hp &b,hp &c);
参数:
a,b:进行加法的高精度数字
返回值:返回相加结果到c中
源程序:
void plus(const hp &a,const hp &b,hp &c)
{
int i,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
if(a.len>b.len) len=a.len;
else len=b.len;
for(i=1;i<=len;i++)
{
c.s[i]+=a.s[i]+b.s[i];
if(c.s[i]>=10)
{
c.s[i]-=10;
c.s[i+1]++;
}
}
if(c.s[len+1]>0) len++;
c.len=len;
}
4.高精度数减法
语法:subtract(const hp &a,const hp &b,hp &c);
参数:
a,b:进行减法的高精度数字,a是被减数,b是减数,不支持负数
返回值:返回结果到c中
源程序:
void subtract(const hp &a,const hp &b,hp &c)
{
int i,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
if(a.len>b.len) len=a.len;
else len=b.len;
for(i=1;i<=len;i++)
{
c.s[i]+=a.s[i]-b.s[i];
if(c.s[i]<0)
{
c.s[i]+=10;
c.s[i+1]--;
}
}
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
5.高精度乘10
语法:multiply10(hp &a);
参数:
a:进行乘法的高精度数字
返回值:返回结果到 a 中
源程序:
void multiply10(hp &a)
{
int i;
for(i=a.len;i>=1;i--)
a.s[i+1]=a.s[i];
a.s[1]=0;
a.len++;
while(a.len>1&&a.s[a.len]==0) a.len--;
}
6.高精度乘单精度
语法:multiply(const hp &a,int b,hp &c);
参数:
a:进行乘法的高精度数字
b:进行乘法的单精度数字
返回值:返回结果到 c 中
源程序:
void multiply(const hp &a,int b,hp &c)
{
int i,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
len=a.len;
for(i=1;i<=len;i++)
{
c.s[i]+=a.s[i]*b;
c.s[i+1]+=c.s[i]/10;
c.s[i]%=10;
}
len++;
while(c.s[len]>=10)
{
c.s[len+1]+=c.s[len]/10;
c.s[len]%=10;
len++;
}
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
7.高精度乘高精度
语法:multiplyh(const hp &a,const hp &b,hp &c);
参数:
a,b:进行乘法的高精度数字
返回值:返回结果到 c 中
源程序:
void multiplyh(const hp &a,const hp &b,hp &c)
{
int i,j,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
for(i=1;i<=a.len;i++)
for(j=1;j<=b.len;j++)
{
c.s[i+j-1]+=a.s[i]*b.s[j];
c.s[i+j]+=c.s[i+j-1]/10;
c.s[i+j-1]%=10;
}
len=a.len+b.len+1;
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
8.高精度除单精度
语法:divide(const hp &a,int b,hp &c,int &d);
参数:
a:进行除法的高精度数字
返回值:返回商到 c 中,余数到 d 中
源程序:
void divide(const hp &a,int b,hp &c,int &d)
{
int i,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
len=a.len;
d=0;
for(i=len;i>=1;i--)
{
d=d*10+a.s[i];
c.s[i]=d/b;
d%=b;
}
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
9.高精度除高精度
语法:divideh(const hp &a,const hp &b,hp &c,hp &d);
参数:
a,b:进行除法的高精度数字
返回值:返回商到 c 中,余数到 d 中
注意:
需要compare、multiply10、subtract
源程序:
void divideh(const hp &a,const hp &b,hp &c,hp &d)
{
hp e;
int i,len;
for(i=1;i<=maxsize;i++)
{
c.s[i]=0;
d.s[i]=0;
}
len=a.len;
d.len=1;
for(i=len;i>=1;i--)
{
multiply10(d);
d.s[1]=a.s[i];
while(compare(d,b)>=0)
{
subtract(d,b,e);
d=e;
c.s[i]++;
}
}
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
C++
#include<fstream.h>
ifstream filein("file.in");
ofstream fileout("file.out");
int main(){
int a,b;
filein>>a>>b;
fileout<<(a+b);
return 0;
}
C:
#include<stdio.h>
int main(){
freopen("file.in","r",stdin);
freopen("file.out","w",stdout);
int a,b;
scanf("%d%d",&a,&b);
printf("%d",a+b);
fclose(stdin); fclose(stdout);
return 0;
}
输入一开始就会说有N个Input Block,下面接着是N个Input Block。
如1526
Code:
cin >> n;
for( i=0 ; i<n ; i++ )
{
....
}
输入不说明有多少个Input Block,但以某个特殊输入为结束标志。
如1115
Code:
while( cin >> n && n != 0 )
{
....
}
输入不说明有多少个Input Block,以EOF为结束标志。
如1001
Code:
while( cin >> a >> b )
{
....
}
输入是一整行的字符串的
如1392
如果你用char buf[ 255 ]; 来保存的:
Code:
cin.getline( buf, 255 );
如果你用string buf;来保存的:
Code:
getline( cin , buf );
输出部分:
一个Input Block对应一个Output Block,Output Block之间没有空行。
如1001
Code:
{
...
cout << ans << endl;
}
一个Input Block对应一个Output Block,Output Block之间有空行。
如1152
Code:
int nCases = 0;
...
{
if ( nCases++ ) cout << endl;
...
cout << ans << endl;
}
一个Input Block对应一个Output Block,每个Output Block之后都有空行。
如1457
Code:
{
...
cout << ans << endl << endl; }
几何公式:
1.长方体
长方体的表面积=2×(a×b+b×c+c×a)
长方体的体积=a×b×c(这里a、b、c分别表示长方体的长、宽、高)。
2.正方体
正方体的表面
ACM小组内部预定函数
数学问题:
1.精度计算——大数阶乘
2.精度计算——乘法(大数乘小数)
3.精度计算——乘法(大数乘大数)
4.精度计算——加法
5.精度计算——减法
6.任意进制转换
7.最大公约数、最小公倍数
8.组合序列
9.快速傅立叶变换(FFT)
10.Ronberg算法计算积分
11.行列式计算
12.求排列组合数
13.求某一天星期几
字符串处理:
1.字符串替换
2.字符串查找
3.字符串截取
4.LCS—最大公共子串长度
5.LCS-生成最大公共子串
6.数字转化为字符
计算几何:
1.叉乘法求任意多边形面积
2.求三角形面积
3.两矢量间角度4.两点距离(2D、3D)
5.射向法判断点是否在多边形内部
6.判断点是否在线段上
7.判断两线段是否相交
8.判断线段与直线是否相交
9.点到线段最短距离
10.求两直线的交点
11.判断一个封闭图形是凹集还是凸集
12.Graham扫描法寻找凸包
13.求两条线段的交点
数论:
1.x的二进制长度
2.返回x的二进制表示中从低到高的第i位
3.模取幂运算
4.求解模线性方程
5.求解模线性方程组(中国余数定理)
6.筛法素数产生器
7.判断一个数是否素数
8.求子距阵最大和
9.求一个数每一位之和
10.质因数分解
11.高斯消元法解线性方程组
图论:
1.Prim算法求最小生成树
2.Dijkstra算法求单源最短路径
3.Bellman-ford算法求单源最短路径
4.Floyd算法求每对节点间最短路径
5.解欧拉图
排序/查找:
1.快速排序
2.希尔排序
3.选择法排序
4.二分查找
高精度运算专题:
1.本专题公共函数说明
2.高精度比较
3.高精度加法
4.高精度减法
5.高精度乘10
6.高精度乘单精度
7.高精度乘高精度
8.高精度除单精度
9.高精度除高精度
一、数学问题
1.精度计算——大数阶乘
语法:int result=factorial(int n);
参数:
n:n 的阶乘
返回值:阶乘结果的位数
注意:
本程序直接输出n!的结果,需要返回结果请保留long a[]
需要 math.h
源程序:
int factorial(int n)
{
long a[10000];
int i,j,l,c,m=0,w;
a[0]=1;
for(i=1;i<=n;i++)
{
c=0;
for(j=0;j<=m;j++)
{
a[j]=a[j]*i+c;
c=a[j]/10000;
a[j]=a[j]%10000;
}
if(c>0) {m++;a[m]=c;}
}
w=m*4+log10(a[m])+1;
printf("\n%ld",a[m]);
for(i=m-1;i>=0;i--) printf("%4.4ld",a[i]);
return w;
}
2.精度计算——乘法(大数乘小数)
语法:mult(char c[],char t[],int m);
参数:
c[]:被乘数,用字符串表示,位数不限
t[]:结果,用字符串表示
m:乘数,限定10以内
返回值:null
注意:
需要 string.h
源程序:
void mult(char c[],char t[],int m)
{
int i,l,k,flag,add=0;
char s[100];
l=strlen(c);
for (i=0;i<l;i++)
s[l-i-1]=c[i]-'0';
for (i=0;i<l;i++)
{
k=s[i]*m+add;
if (k>=10) {s[i]=k%10;add=k/10;flag=1;} else
{s[i]=k;flag=0;add=0;}
}
if (flag) {l=i+1;s[i]=add;} else l=i;
for (i=0;i<l;i++)
t[l-1-i]=s[i]+'0';
t[l]='\0';
}
3.精度计算——乘法(大数乘大数)
语法:mult(char a[],char b[],char s[]);
参数:
a[]:被乘数,用字符串表示,位数不限
b[]:乘数,用字符串表示,位数不限
t[]:结果,用字符串表示
返回值:null
注意:
空间复杂度为 o(n^2)
需要 string.h
源程序:
void mult(char a[],char b[],char s[])
{
int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0;
char result[65];
alen=strlen(a);blen=strlen(b);
for (i=0;i<alen;i++)
for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0');
for (i=alen-1;i>=0;i--)
{
for (j=blen-1;j>=0;j--) sum=sum+res[i+blen-j-1][j];
result[k]=sum%10;
k=k+1;
sum=sum/10;
}
for (i=blen-2;i>=0;i--)
{
for (j=0;j<=i;j++) sum=sum+res[i-j][j];
result[k]=sum%10;
k=k+1;
sum=sum/10;
}
if (sum!=0) {result[k]=sum;k=k+1;}
for (i=0;i<k;i++) result[i]+='0';
for (i=k-1;i>=0;i--) s[i]=result[k-1-i];
s[k]='\0';
while(1)
{
if (strlen(s)!=strlen(a)&&s[0]=='0')
strcpy(s,s+1);
else
break;
}
}
4.精度计算——加法
语法:add(char a[],char b[],char s[]);
参数:
a[]:被乘数,用字符串表示,位数不限
b[]:乘数,用字符串表示,位数不限
t[]:结果,用字符串表示
返回值:null
注意:
空间复杂度为 o(n^2)
需要 string.h
源程序:
void add(char a[],char b[],char back[])
{
int i,j,k,up,x,y,z,l;
char *c;
if (strlen(a)>strlen(b)) l=strlen(a)+2; else l=strlen(b)+2;
c=(char *) malloc(l*sizeof(char));
i=strlen(a)-1;
j=strlen(b)-1;
k=0;up=0;
while(i>=0||j>=0)
{
if(i<0) x='0'; else x=a[i];
if(j<0) y='0'; else y=b[j];
z=x-'0'+y-'0';
if(up) z+=1;
if(z>9) {up=1;z%=10;} else up=0;
c[k++]=z+'0';
i--;j--;
}
if(up) c[k++]='1';
i=0;
c[k]='\0';
for(k-=1;k>=0;k--)
back[i++]=c[k];
back[i]='\0';
}
5.精度计算——减法
语法:sub(char s1[],char s2[],char t[]);
参数:
s1[]:被减数,用字符串表示,位数不限
s2[]:减数,用字符串表示,位数不限
t[]:结果,用字符串表示
返回值:null
注意:
默认s1>=s2,程序未处理负数情况
需要 string.h
源程序:
void sub(char s1[],char s2[],char t[])
{
int i,l2,l1,k;
l2=strlen(s2);l1=strlen(s1);
t[l1]='\0';l1--;
for (i=l2-1;i>=0;i--,l1--)
{
if (s1[l1]-s2[i]>=0)
t[l1]=s1[l1]-s2[i]+'0';
else
{
t[l1]=10+s1[l1]-s2[i]+'0';
s1[l1-1]=s1[l1-1]-1;
}
}
k=l1;
while(s1[k]<0) {s1[k]+=10;s1[k-1]-=1;k--;}
while(l1>=0) {t[l1]=s1[l1];l1--;}
loop:
if (t[0]=='0')
{
l1=strlen(s1);
for (i=0;i<l1-1;i++) t[i]=t[i+1];
t[l1-1]='\0';
goto loop;
}
if (strlen(t)==0) {t[0]='0';t[1]='\0';}
}
6.任意进制转换
语法:conversion(char s1[],char s2[],char t[]);
参数:
s[]:转换前的数字
s2[]:转换后的数字
d1:原进制数
d2:需要转换到的进制数
返回值:null
注意:
高于9的位数用大写'A'~'Z'表示,2~16位进制通过验证
源程序:
void conversion(char s[],char s2[],long d1,long d2)
{
long i,j,t,num;
char c;
num=0;
for (i=0;s[i]!='\0';i++)
{
if (s[i]<='9'&&s[i]>='0') t=s[i]-'0'; else t=s[i]-'A'+10;
num=num*d1+t;
}
i=0;
while(1)
{
t=num%d2;
if (t<=9) s2[i]=t+'0'; else s2[i]=t+'A'-10;
num/=d2;
if (num==0) break;
i++;
}
for (j=0;j<i/2;j++)
{c=s2[j];s2[j]=s[i-j];s2[i-j]=c;}
s2[i+1]='\0';
}
7.最大公约数、最小公倍数
语法:resulet=hcf(int a,int b)、result=lcd(int a,int b)
参数:
a:int a,求最大公约数或最小公倍数
b:int b,求最大公约数或最小公倍数
返回值:返回最大公约数(hcf)或最小公倍数(lcd)
注意:
lcd 需要连同 hcf 使用
源程序:
int hcf(int a,int b)
{
int r=0;
while(b!=0)
{
r=a%b;
a=b;
b=r;
}
return(a);
}
lcd(int u,int v,int h)
{
return(u*v/h);
}
8.组合序列
语法:m_of_n(int m, int n1, int m1, int* a, int head)
参数:
m:组合数C的上参数
n1:组合数C的下参数
m1:组合数C的上参数,递归之用
*a:1~n的整数序列数组
head:头指针
返回值:null
注意:
*a需要自行产生
初始调用时,m=m1、head=0
调用例子:求C(m,n)序列:m_of_n(m,n,m,a,0);
源程序:
void m_of_n(int m, int n1, int m1, int* a, int head)
{
int i,t;
if(m1<0 || m1>n1) return;
if(m1==n1)
{
for(i=0;i<m;i++) cout<<a[i]<<' '; // 输出序列
cout<<'\n';
return;
}
m_of_n(m,n1-1,m1,a,head); // 递归调用
t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;
m_of_n(m,n1-1,m1-1,a,head+1); // 再次递归调用
t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;
}
9.快速傅立叶变换(FFT)
语法:kkfft(double pr[],double pi[],int n,int k,double fr[],double fi[],int
l,int il);
参数:
pr[n]:输入的实部
pi[n]:数入的虚部
n,k:满足n=2^k
fr[n]:输出的实部
fi[n]:输出的虚部
l:逻辑开关,0 FFT,1 ifFT
il:逻辑开关,0 输出按实部/虚部;1 输出按模/幅角
返回值:null
注意:
需要 math.h
源程序:
void kkfft(pr,pi,n,k,fr,fi,l,il)
int n,k,l,il;
double pr[],pi[],fr[],fi[];
{
int it,m,is,i,j,nv,l0;
double p,q,s,vr,vi,poddr,poddi;
for (it=0; it<=n-1; it++)
{
m=it; is=0;
for (i=0; i<=k-1; i++)
{j=m/2; is=2*is+(m-2*j); m=j;}
fr[it]=pr[is]; fi[it]=pi[is];
}
pr[0]=1.0; pi[0]=0.0;
p=6.283185306/(1.0*n);
pr[1]=cos(p); pi[1]=-sin(p);
if (l!=0) pi[1]=-pi[1];
for (i=2; i<=n-1; i++)
{
p=pr[i-1]*pr[1];
q=pi[i-1]*pi[1];
s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
pr[i]=p-q; pi[i]=s-p-q;
}
for (it=0; it<=n-2; it=it+2)
{
vr=fr[it]; vi=fi[it];
fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];
fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];
}
m=n/2; nv=2;
for (l0=k-2; l0>=0; l0--)
{
m=m/2; nv=2*nv;
for (it=0; it<=(m-1)*nv; it=it+nv)
for (j=0; j<=(nv/2)-1; j++)
{
p=pr[m*j]*fr[it+j+nv/2];
q=pi[m*j]*fi[it+j+nv/2];
s=pr[m*j]+pi[m*j];
s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
poddr=p-q; poddi=s-p-q;
fr[it+j+nv/2]=fr[it+j]-poddr;
fi[it+j+nv/2]=fi[it+j]-poddi;
fr[it+j]=fr[it+j]+poddr;
fi[it+j]=fi[it+j]+poddi;
}
}
if (l!=0)
for (i=0; i<=n-1; i++)
{
fr[i]=fr[i]/(1.0*n);
fi[i]=fi[i]/(1.0*n);
}
if (il!=0)
for (i=0; i<=n-1; i++)
{
pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);
if (fabs(fr[i])<0.000001*fabs(fi[i]))
{
if ((fi[i]*fr[i])>0) pi[i]=90.0;
else pi[i]=-90.0;
}
else
pi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;
}
return;
}
10.Ronberg算法计算积分
语法:result=integral(double a,double b);
参数:
a:积分上限
b:积分下限
function f:积分函数
返回值:f在(a,b)之间的积分值
注意:
function f(x)需要自行修改,程序中用的是sina(x)/x
需要 math.h
默认精度要求是1e-5
源程序:
double f(double x)
{
return sin(x)/x; //在这里插入被积函数
}
double integral(double a,double b)
{
double h=b-a;
double t1=(1+f(b))*h/2.0;
int k=1;
double r1,r2,s1,s2,c1,c2,t2;
loop:
double s=0.0;
double x=a+h/2.0;
while(x<b)
{
s+=f(x);
x+=h;
}
t2=(t1+h*s)/2.0;
s2=t2+(t2-t1)/3.0;
if(k==1)
{
k++;h/=2.0;t1=t2;s1=s2;
goto loop;
}
c2=s2+(s2-s1)/15.0;
if(k==2){
c1=c2;k++;h/=2.0;
t1=t2;s1=s2;
goto loop;
}
r2=c2+(c2-c1)/63.0;
if(k==3){
r1=r2; c1=c2;k++;
h/=2.0;
t1=t2;s1=s2;
goto loop;
}
while(fabs(1-r1/r2)>1e-5){
r1=r2;c1=c2;k++;
h/=2.0;
t1=t2;s1=s2;
goto loop;
}
return r2;
}
11.行列式计算
语法:result=js(int s[][],int n)
参数:
s[][]:行列式存储数组
n:行列式维数,递归用
返回值:行列式值
注意:
函数中常数N为行列式维度,需自行定义
源程序:
int js(s,n)
int s[][N],n;
{
int z,j,k,r,total=0;
int b[N][N];/*b[N][N]用于存放,在矩阵s[N][N]中元素s[0]的余子式*/
if(n>2)
{
for(z=0;z<n;z++)
{
for(j=0;j<n-1;j++)
for(k=0;k<n-1;k++)
if(k>=z) b[j][k]=s[j+1][k+1]; else
b[j][k]=s[j+1][k];
if(z%2==0) r=s[0][z]*js(b,n-1); /*递归调用*/
else r=(-1)*s[0][z]*js(b,n-1);
total=total+r;
}
}
else if(n==2)
total=s[0][0]*s[1][1]-s[0][1]*s[1][0];
return total;
}
12.求排列组合数
语法:result=P(long n,long m); / result=long C(long n,long m);
参数:
m:排列组合的上系数
n:排列组合的下系数
返回值:排列组合数
注意:
符合数学规则:m<=n
源程序:
long P(long n,long m)
{
long p=1;
while(m!=0)
{p*=n;n--;m--;}
return p;
}
long C(long n,long m)
{
long i,c=1;
i=m;
while(i!=0)
{c*=n;n--;i--;}
while(m!=0)
{c/=m;m--;}
return c;
}
13.求某一天星期几
语法:result=weekday(int N,int M,int d)
参数:
N,M,d:年月日,例如:2003,11,4
返回值:0:星期天,1星期一……
注意:
需要math.h
适用于1582年10月15日之后, 因为罗马教皇格里高利十三世在这一天启用新历法.
源程序:
int weekday(int N,int M,int d)
{
int m,n,c,y,w;
m=(M-2)%12;
if (M>=3) n=N;else n=N-1;
c=n/100;
y=n%100;
w=(int)(d+floor(13*m/5)+y+floor(y/4)+floor(c/4)-2*c)%7;
while(w<0) w+=7;
return w;
}
二、字符串处理
1.字符串替换
语法:replace(char str[],char key[],char swap[]);
参数:
str[]:在此源字符串进行替换操作
key[]:被替换的字符串,不能为空串
swap[]:替换的字符串,可以为空串,为空串表示在源字符中删除key[]
返回值:null
注意:
默认str[]长度小于1000,如否,重新设定设定tmp大小
需要 string.h
源程序:
void replace(char str[],char key[],char swap[])
{
int l1,l2,l3,i,j,flag;
char tmp[1000];
l1=strlen(str);
l2=strlen(key);
l3=strlen(swap);
for (i=0;i<=l1-l2;i++)
{
flag=1;
for (j=0;j<l2;j++)
if (str[i+j]!=key[j]) {flag=0;break;}
if (flag)
{
strcpy(tmp,str);
strcpy(&tmp[i],swap);
strcpy(&tmp[i+l3],&str[i+l2]);
strcpy(str,tmp);
i+=l3-1;
l1=strlen(str);
}
}
}
2.字符串查找
语法:result=strfind(char str[],char key[]);
参数:
str[]:在此源字符串进行查找操作
key[]:被查找的字符串,不能为空串
返回值:如果查找成功,返回key在str中第一次出现的位置,否则返回-1
注意:
需要 string.h
源程序:
int strfind(char str[],char key[])
{
int l1,l2,i,j,flag;
l1=strlen(str);
l2=strlen(key);
for (i=0;i<=l1-l2;i++)
{
flag=1;
for (j=0;j<l2;j++)
if (str[i+j]!=key[j]) {flag=0;break;}
if (flag) return i;
}
return -1;
}
3.字符串截取
语法:mid(char str[],int start,int len,char strback[])
参数:
str[]:操作的目标字符串
start:从第start个字符串开始,截取长度为len的字符
len:从第start个字符串开始,截取长度为len的字符
strback[]:截取的到的字符
返回值:0:超出字符串长度,截取失败;1:截取成功
注意:
需要 string.h
源程序:
int mid(char str[],int start,int len,char strback[])
{
int l,i,k=0;
l=strlen(str);
if (start+len>l) return 0;
for (i=start;i<start+len;i++)
strback[k++]=str[i];
strback[k]='\0';
return 1;
}
4.LCS-最大公共子串长度
语法:result=lcs_len(char *a, char *b);
参数:
a,b[]:根据a,b生成最大公共子串
返回值:最大公共子串的长度
注意:
需要 string.h
M、N是a,b数组的最大可能长度
如果不需要生成公共子串,c[M][N]不可设置为全局变量
源程序:
#define M 20
#define N 20
int c[M][N];
int lcs_len(char *a, char *b)
{
int m=strlen(a),n=strlen(b),i,j;
for(i=0;i<=m;i++) c[i][0]=0;
for(j=0;j<=n;j++) c[0][j]=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{
if(a[i-1]==b[j-1])
c[i][j]=c[i-1][j-1]+1;
else if(c[i-1][j]>c[i][j-1])
c[i][j]=c[i-1][j];
else
c[i][j]=c[i][j-1];
}
return c[m][n];
}
5.LCS-最大公共子串长度
语法:result=build_lcs(char s[], char *a, int blen, int clen);
参数:
*a:生成公共子串的字符串a,b中的a
s[]:接受返回结果的字符串数组
blen:生成公共子串的字符串a,b中的b的长度
clen:最大公共子串的长度,通过lcs_len函数求得
返回值:最大公共子串的长度
注意:
需要 string.h
需要lcs_len函数求clen并且生成c[M][N]
可通过result=build_lcs返回指针或者通过build_lcs(s,a,blen,clen),用s接受结果
源程序:
char *build_lcs(char s[], char *a, int blen, int clen)
{
int k=clen,alen=strlen(a),i,j;
s[k]='\0';
i=alen,j=blen;
while(k>0)
{
if(c[i][j]==c[i-1][j])
i--;
else if(c[i][j]==c[i][j-1])
j--;
else
{
s[--k]=a[i-1];
i--;j--;
}
}
return s;
}
6.数字转换为字符
语法:cstr(int k,char o[]);
参数:
k:转换的数字
o[]:存储转换结果的字符串
返回值:null
注意:
需要 math.h
源程序:
void cstr(int k,char o[])
{
int len,i,t;
len=log10(k)+1;
for (i=len;i>0;i--)
{
t=k%10;
k-=t;k/=10;
o[i-1]='0'+t;
}
o[len]='\0';
}
三、计算几何
1.叉乘法求任意多边形面积
语法:result=polygonarea(Point *polygon,int N);
参数:
*polygon:多变形顶点数组
N:多边形顶点数目
返回值:多边形面积
注意:
支持任意多边形,凹、凸皆可
多边形顶点输入时按顺时针顺序排列
源程序:
typedef struct {
double x,y;
} Point;
double polygonarea(Point *polygon,int N)
{
int i,j;
double area = 0;
for (i=0;i<N;i++) {
j = (i + 1) % N;
area += polygon[i].x * polygon[j].y;
area -= polygon[i].y * polygon[j].x;
}
area /= 2;
return(area < 0 ? -area : area);
}
2.求三角形面积
语法:result=area3(float x1,float y1,float x2,float y2,float x3,float y3);
参数:
x1~3:三角形3个顶点x坐标
y1~3:三角形3个顶点y坐标
返回值:三角形面积
注意:
需要 math.h
源程序:
float area3(float x1,float y1,float x2,float y2,float x3,float y3)
{
float a,b,c,p,s;
a=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
b=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));
c=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));
p=(a+b+c)/2;
s=sqrt(p*(p-a)*(p-b)*(p-c));
return s;
}
3.两矢量间角度
语法:result=angle(double x1, double y1, double x2, double y2);
参数:
x/y1~2:两矢量的坐标
返回值:两的角度矢量
注意:
返回角度为弧度制,并且以逆时针方向为正方向
需要 math.h
源程序:
#define PI 3.1415926
double angle(double x1, double y1, double x2, double y2)
{
double dtheta,theta1,theta2;
theta1 = atan2(y1,x1);
theta2 = atan2(y2,x2);
dtheta = theta2 - theta1;
while (dtheta > PI)
dtheta -= PI*2;
while (dtheta < -PI)
dtheta += PI*2;
return(dtheta);
}
4.两点距离(2D、3D)
语法:result=distance_2d(float x1,float x2,float y1,float y2);
参数:
x/y/z1~2:各点的x、y、z坐标
返回值:两点之间的距离
注意:
需要 math.h
源程序:
float distance_2d(float x1,float x2,float y1,float y2)
{
return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
float distance_3d(float x1,float x2,float y1,float y2,float z1,float z2)
{
return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)));
}
5.射向法判断点是否在多边形内部
语法:result=insidepolygon(Point *polygon,int N,Point p);
参数:
*polygon:多边形顶点数组
N:多边形顶点个数
p:被判断点
返回值:0:点在多边形内部;1:点在多边形外部
注意:
若p点在多边形顶点或者边上,返回值不确定,需另行判断
需要 math.h
源程序:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
typedef struct {
double x,y;
} Point;
int insidepolygon(Point *polygon,int N,Point p)
{
int counter = 0;
int i;
double xinters;
Point p1,p2;
p1 = polygon[0];
for (i=1;i<=N;i++) {
p2 = polygon[i % N];
if (p.y > MIN(p1.y,p2.y)) {
if (p.y <= MAX(p1.y,p2.y)) {
if (p.x <= MAX(p1.x,p2.x)) {
if (p1.y != p2.y) {
xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
if (p1.x == p2.x || p.x <= xinters)
counter++;
}
}
}
}
p1 = p2;
}
if (counter % 2 == 0)
return(OUTSIDE);
else
return(INSIDE);
}
6.判断点是否在线段上
语法:result=Pointonline(Point p1,Point p2,Point p);
参数:
p1、p2:线段的两个端点
p:被判断点
返回值:0:点在不在线段上;1:点在线段上
注意:
若p线段端点上返回1
需要 math.h
源程序:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
typedef struct {
double x,y;
} Point;
int FC(double x1,double x2)
{
if (x1-x2<0.000002&&x1-x2>-0.000002) return 1; else return 0;
}
int Pointonline(Point p1,Point p2,Point p)
{
double x1,y1,x2,y2;
x1=p.x-p1.x;
x2=p2.x-p1.x;
y1=p.y-p1.y;
y2=p2.y-p1.y;
if (FC(x1*y2-x2*y1,0)==0) return 0;
if ((MIN(p1.x,p2.x)<=p.x&&p.x<=MAX(p1.x,p2.x))&&
(MIN(p1.y,p2.y)<=p.y&&p.y<=MAX(p1.y,p2.y)))
return 1; else return 0;
}
7.判断两线段是否相交
语法:result=lineintersect(Point p1,Point p2,Point p3,Point p4);
参数:
p1~4:两条线段的四个端点
返回值:0:两线段不相交;1:两线段相交;2两线段首尾相接
注意:
p1!=p2;p3!=p4;
源程序:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
typedef struct {
double x,y;
} Point;
int lineintersect(Point p1,Point p2,Point p3,Point p4)
{
Point tp1,tp2,tp3;
if
((p1.x==p3.x&&p1.y==p3.y)||(p1.x==p4.x&&p1.y==p4.y)||(p2.x==p3.x&&p2.y==p3.y)||(p2.x==p4.x&&p2.y==p4.y))
return 2;
//快速排斥试验
if
((MIN(p1.x,p2.x)<=p3.x&&p3.x<=MAX(p1.x,p2.x)&&MIN(p1.y,p2.y)<=p3.y&&p3.y<=MAX(p1.y,p2.y))||
(MIN(p1.x,p2.x)<=p4.x&&p4.x<=MAX(p1.x,p2.x)&&MIN(p1.y,p2.y)<=p4.y&&p4.y<=MAX(p1.y,p2.y)))
;else return 0;
//跨立试验
tp1.x=p1.x-p3.x;
tp1.y=p1.y-p3.y;
tp2.x=p4.x-p3.x;
tp2.y=p4.y-p3.y;
tp3.x=p2.x-p3.x;
tp3.y=p2.y-p3.y;
if ((tp1.x*tp2.y-tp1.y*tp2.x)*(tp2.x*tp3.y-tp2.y*tp3.x)>=0) return 1;
else return 0;
}
8.判断线段与直线是否相交
语法:result=lineintersect(Point p1,Point p2,Point p3,Point p4);
参数:
p1、p2:线段的两个端点
p3、p4:直线上的两个点
返回值:0:线段直线不相交;1:线段和直线相交
注意:
如线段在直线上,返回 1
源程序:
typedef struct {
double x,y;
} Point;
int lineintersect(Point p1,Point p2,Point p3,Point p4)
{
Point tp1,tp2,tp3;
tp1.x=p1.x-p3.x;
tp1.y=p1.y-p3.y;
tp2.x=p4.x-p3.x;
tp2.y=p4.y-p3.y;
tp3.x=p2.x-p3.x;
tp3.y=p2.y-p3.y;
if ((tp1.x*tp2.y-tp1.y*tp2.x)*(tp2.x*tp3.y-tp2.y*tp3.x)>=0) return 1;
else return 0;
}
9.点到线段最短距离
语法:result=mindistance(Point p1,Point p2,Point q);
参数:
p1、p2:线段的两个端点
q:判断点
返回值:点q到线段p1p2的距离
注意:
需要 math.h
源程序:
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
typedef struct {
double x,y;
} Point;
double mindistance(Point p1,Point p2,Point q)
{
int flag=1;
double k;
Point s;
if (p1.x==p2.x) {s.x=p1.x;s.y=q.y;flag=0;}
if (p1.y==p2.y) {s.x=q.x;s.y=p1.y;flag=0;}
if (flag)
{
k=(p2.y-p1.y)/(p2.x-p1.x);
s.x=(k*k*p1.x+k*(q.y-p1.y)+q.x)/(k*k+1);
s.y=k*(s.x-p1.x)+p1.y;
}
if (MIN(p1.x,p2.x)<=s.x&&s.x<=MAX(p1.x,p2.x))
return sqrt((q.x-s.x)*(q.x-s.x)+(q.y-s.y)*(q.y-s.y));
else
return
MIN(sqrt((q.x-p1.x)*(q.x-p1.x)+(q.y-p1.y)*(q.y-p1.y)),sqrt((q.x-p2.x)*(q.x-p2.x)+(q.y-p2.y)*(q.y-p2.y)));
}
10.求两直线的交点
语法:result=mindistance(Point p1,Point p2,Point q);
参数:
p1~p4:直线上不相同的两点
*p:通过指针返回结果
返回值:1:两直线相交;2:两直线平行
注意:
如需要判断两线段交点,检验k和对应k1(注释中)的值是否在0~1之间,用在0~1之间的那个求交点
源程序:
typedef struct {
double x,y;
} Point;
int linecorss(Point p1,Point p2,Point p3,Point p4,Point *p)
{
double k;
if ((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y)==0) return 0;
if ((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x)==0&&
(p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x)==0) return 0;
k=((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y));
//k1=((p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x))/((p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y));
(*p).x=p1.x+k*(p2.x-p1.x);
(*p).y=p1.y+k*(p2.y-p1.y);
return 1;
}
11.判断一个封闭图形是凹集还是凸集
语法:result=convex(Point *p,int n);
参数:
*p:封闭曲线顶点数组
n:封闭曲线顶点个数
返回值:1:凸集;-1:凹集;0:曲线不符合要求无法计算
注意:
默认曲线为简单曲线:无交叉、无圈
源程序:
typedef struct {
double x,y;
} Point;
int convex(Point *p,int n)
{
int i,j,k;
int flag = 0;
double z;
if (n < 3)
return(0);
for (i=0;i<n;i++) {
j = (i + 1) % n;
k = (i + 2) % n;
z = (p[j].x - p[i].x) * (p[k].y - p[j].y);
z -= (p[j].y - p[i].y) * (p[k].x - p[j].x);
if (z < 0)
flag |= 1;
else if (z > 0)
flag |= 2;
if (flag == 3)
return -1; //CONCAVE
}
if (flag != 0)
return 1; //CONVEX
else
return 0;
}
12.Graham扫描法寻找凸包
语法:Graham_scan(Point PointSet[],Point ch[],int n,int &len);
参数:
PointSet[]:输入的点集
ch[]:输出的凸包上的点集,按照逆时针方向排列
n:PointSet中的点的数目
len:输出的凸包上的点的个数
返回值:null
源程序:
struct Point{
float x,y;
};
float multiply(Point p1,Point p2,Point p0)
{
return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}
float distance(Point p1,Point p2)
{
return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
}
void Graham_scan(Point PointSet[],Point ch[],int n,int &len)
{
int i,j,k=0,top=2;
Point tmp;
for(i=1;i<n;i++)
if
((PointSet[i].y<PointSet[k].y)||((PointSet[i].y==PointSet[k].y)&&(PointSet[i].x<PointSet[k].x)))
k=i;
tmp=PointSet[0];
PointSet[0]=PointSet[k];
PointSet[k]=tmp;
for (i=1;i<n-1;i++)
{
k=i;
for (j=i+1;j<n;j++)
if ( (multiply(PointSet[j],PointSet[k],PointSet[0])>0) ||
((multiply(PointSet[j],PointSet[k],PointSet[0])==0)
&&(distance(PointSet[0],PointSet[j])<distance(PointSet[0],PointSet[k])))
)
k=j;
tmp=PointSet[i];
PointSet[i]=PointSet[k];
PointSet[k]=tmp;
}
ch[0]=PointSet[0];
ch[1]=PointSet[1];
ch[2]=PointSet[2];
for (i=3;i<n;i++)
{
while (multiply(PointSet[i],ch[top],ch[top-1])>=0) top--;
ch[++top]=PointSet[i];
}
len=top+1;
}
13.求两条线段的交点
语法:Result=IntersectPoint (Point p1,Point p2,Point p3,Point p4,Point &p);
参数:
P1~P4:两条线断4个端点
P:线段交点
返回值:如果两条线段平行无交点,返回 0,否则返回 1
源程序:
struct Point{
float x,y;
};
int IntersectPoint (Point p1,Point p2,Point p3,Point p4,Point &p)
{
float a,b,c,d,e,f;
a=p2.y-p1.y;
b=p1.x-p2.x;
c=p1.y*(p2.x-p1.x)+p1.x*(p2.y-p1.y);
d=p4.y-p3.y;
e=p3.x-p4.x;
f=p3.y*(p4.x-p3.x)+p1.x*(p4.y-p3.y);
if (a*e==b*d)
return 0;
else
{
p.x=(e*c-b*f)/(b*d-a*e);
p.y=(d*c-a*f)/(a*e-b*d);
return 1;
}
}
四、数论
1.x的二进制长度
语法:result=BitLength(int x);
参数:
x:测长的x
返回值:x的二进制长度
源程序:
int BitLength(int x)
{
int d = 0;
while (x > 0) {
x >>= 1;
d++;
}
return d;
}
2.返回x的二进制表示中从低到高的第i位
语法:result=BitAt(int x, int i);
参数:
x:十进制 x
i:要求二进制的第i位
返回值:返回x的二进制表示中从低到高的第i位
注意:
最低位为第一位
源程序:
int BitAt(int x, int i)
{
return ( x & (1 << (i-1)) );
}
3.模取幂运算
语法:result=Modular_Expoent(int a,int b,int n);
参数:
a、b、n:a^b mod n 的对应参数
返回值:a^b mod n 的值
注意:
需要BitLength和BitAt
源程序:
int Modular_Expoent(int a,int b,int n)
{
int i, y=1;
for (i = BitLength(b); i > 0; i--)
{
y = (y*y)%n;
if (BitAt(b,i) > 0)
y = (y*a)%n;
}
return y;
}
4.求解模线性方程
语法:result=modular_equation(int a,int b,int n);
参数:
a、b、n:ax=b (mod n) 的对应参数
返回值:方程的解
源程序:
int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by
{
int t,d;
if (b==0) {x=1;y=0;return a;}
d=ext_euclid(b,a %b,x,y);
t=x;
x=y;
y=t-a/b*y;
return d;
}
void modular_equation(int a,int b,int n)
{
int e,i,d;
int x,y;
d=ext_euclid(a,n,x,y);
if (b%d>0)
printf("No answer!\n");
else
{
e=(x*(b/d))%n;
for (i=0;i<d;i++)
printf("The %dth answer is : %ld\n",i+1,(e+i*(n/d))%n);
}
}
5.求解模线性方程组(中国余数定理)
语法:result=Modular_Expoent(int a,int b,int n);
参数:
B[]、W[]:a=B[] (mod W[]) 的对应参数
返回值:a 的值
注意:
其中W[],B[]已知,W[i]>0且W[i]与W[j]互质, 求a
源程序:
int ext_euclid(int a,int b,int &x,int &y) //求gcd(a,b)=ax+by
{
int t,d;
if (b==0) {x=1;y=0;return a;}
d=ext_euclid(b,a %b,x,y);
t=x;
x=y;
y=t-a/b*y;
return d;
}
int China(int B[],int W[],int k)
{
int i;
int d,x,y,a=0,m,n=1;
for (i=0;i<k;i++)
n*=W[i];
for (i=0;i<k;i++)
{
m=n/W[i];
d=ext_euclid(W[i],m,x,y);
a=(a+y*m*B[i])%n;
}
if (a>0) return a;
else return(a+n);
}
6.筛法素数产生器
语法:result=prime(int a[],int n);
参数:
a[]:用于返回素数的数组
n:产生n以内的素数,按升序放入a[]中
返回值:n以内素数的个数
注意:
其中W[],B[]已知,W[i]>0且W[i]与W[j]互质, 求a
源程序:
int prime(int a[],int n)
{
int i,j,k,x,num,*b;
n++;
n/=2;
b=new int[(n+1)*2];
a[0]=2;a[1]=3;num=2;
for(i=1;i<=2*n;i++)
b[i]=0;
for(i=3;i<=n;i+=3)
for(j=0;j<2;j++)
{
x=2*(i+j)-1;
while(b[x]==0)
{
a[num++]=x;
for(k=x;k<=2*n;k+=x)
b[k]=1;
}
}
return num;
}
7.判断一个数是否素数
语法:result=comp(int n);
参数:
n:判断n是否素数
返回值:素数返回1,否则返回0
源程序:
//传统方法
int comp(int n){
if(n<2)return 0;
if(n%2==0)return 0;
for(int i=3;i<=sqrt(n);i+=2) if(n%i==0) return 0;
return 1;
}
//大数素数判定,(1/4)^K出错概率
int powermod(int a,int b,int n)
{//get (a^b)%n
i64 d=1, t=a;
while(b>0){
if(t==1)return d;
if(b%2==1)d=(t*d)%n;
b/=2; t=(t*t)%n;
}
return d;
}
int isprime(int n,int k){
int a;
while(k--){
a=rand();
a%=n-3; a+=2;
if(powermod(k+2,n-1,n)!=1)return 0;
}
return 1;
}
8.求距阵最大和
语法:result=maxsum2(int n);
参数:
a:距阵
n,m:距阵行列数
返回值:一维,二维距阵最大和
源程序:
int a[101][101];
int maxsum(int a[],int n)//一维最大串
{
int sum=-10000000,b=0;
int i;
for(i=0;i<n;i++)
{
if (b>0)
b+=a[i];
else
b=a[i];
if(b>sum)
sum=b;
}
return sum;
}
int maxsum2(int m,int n)//二维最大串
{
int sum = -10000000;
int i,j,k,max;
int* b = new int[n+1];
for (i=0;i<m;i++)
{
for(k=0;k<n;k++)
b[k]=a[i][k];
max = maxsum(b,n);//第i列的一维最大串
if(max>sum)
sum=max;
for(j=i+1;j<m;j++)
{
for (k=0;k<=n;k++)b[k]+=a[j][k];
max = maxsum(b,n);//类似maxsum,通过每列相加求二维最大串
if(max>sum)sum=max;
}
}
delete []b;
return sum;
}
8.求一个数每一位相加之和
语法:result=digadd(int n)
参数:
n:待求数字
返回值:各数字之和
源程序:
int digadd(int n)
{
int i=0,k=0;
while(i=n%10,n/=10) k+=i;
return k+i;
}
10.质因数分解
语法:result=int reduce(int prime[],int pn,int n,int rest[])
参数:
Prime[]:素数表,至少需要达到sqrt(n)
pn:素数表的元素个数
N:待分解的数
Rest:分解结果,按照升序排列
返回值:分解因子个数
源程序:
int reduce(int prime[],int pn,int n,int rest[])
{
int i,k=0;
for(i=0;i<pn;i++)
{
if (n==1) break;
if (prime[i]*prime[i]>n) {rest[k++]=n;break;}
while(n%prime[i]==0)
{
n/=prime[i];
rest[k++]=prime[i];
}
}
return k;
}
11.高斯消元法解线性方程组
语法:gauss(int n,double ** a)
参数:
N:变量个数
Rest:变量系数行列式
源程序:
void gauss(int n,double **a)
{
int i, j, k;
double client, temp = 0.0;
for(k = 0; k < n - 1; k++)
for(i = k + 1; i < n; i++)
{
client = a[i][k]/a[k][k];
for(j = k + 1; j < n; j++)
a[i][j] = a[i][j] - client * a[k][j];
a[i][n] = a[j - 1][n] - client * a[k][n];
}
a[n - 1][n] = a[n - 1][n]/a[n - 1][n - 1];
for(i = n - 2; i >= 0; i--)
{
for (j = i + 1; j < n; j++)
temp += a[i][j] * a[j][n];
a[i][n] = (a[i][n] - temp) / a[i][i];
}
}
//打印
//for(i = 0; i < n; i++)
// printf("X%d = %lf\n", i + 1, a[i][n]);
五、图论
1.Prim算法求最小生成树
语法:prim(Graph G,int vcount,int father[]);
参数:
G:图,用邻接矩阵表示
vcount:表示图的顶点个数
father[]:用来记录每个节点的父节点
返回值:null
注意:
常数max_vertexes为图最大节点数
常数infinity为无穷大
源程序:
#define infinity 1000000
#define max_vertexes 5
typedef int Graph[max_vertexes][max_vertexes];
void prim(Graph G,int vcount,int father[])
{
int i,j,k;
int lowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes];
for (i=0;i<vcount;i++)
{
lowcost[i]=G[0][i];
closeset[i]=0;
used[i]=0;
father[i]=-1;
}
used[0]=1;
for (i=1;i<vcount;i++)
{
j=0;
while (used[j]) j++;
for (k=0;k<vcount;k++)
if ((!used[k])&&(lowcost[k]<lowcost[j])) j=k;
father[j]=closeset[j];
used[j]=1;
for (k=0;k<vcount;k++)
if (!used[k]&&(G[j][k]<lowcost[k]))
{ lowcost[k]=G[j][k];
closeset[k]=j; }
}
}
2.Dijkstra算法求单源最短路径
语法:result=Dijkstra(Graph G,int n,int s,int t, int path[]);
参数:
G:图,用邻接矩阵表示
n:图的顶点个数
s:开始节点
t:目标节点
path[]:用于返回由开始节点到目标节点的路径
返回值:最短路径长度
注意:
输入的图的权必须非负
顶点标号从0开始
用如下方法打印路径:
i=t;
while (i!=s)
{
printf("%d<--",i+1);
i=path[i];
}
printf("%d\n",s+1);
源程序:
int Dijkstra(Graph G,int n,int s,int t, int path[])
{
int i,j,w,minc,d[max_vertexes],mark[max_vertexes];
for (i=0;i<n;i++) mark[i]=0;
for (i=0;i<n;i++)
{ d[i]=G[s][i];
path[i]=s; }
mark[s]=1;path[s]=0;d[s]=0;
for (i=1;i<n;i++)
{
minc=infinity;
w=0;
for (j=0;j<n;j++)
if ((mark[j]==0)&&(minc>=d[j])) {minc=d[j];w=j;}
mark[w]=1;
for (j=0;j<n;j++)
if ((mark[j]==0)&&(G[w][j]!=infinity)&&(d[j]>d[w]+G[w][j]))
{ d[j]=d[w]+G[w][j];
path[j]=w; }
}
return d[t];
}
3.Bellman-ford算法求单源最短路径
语法:result=Bellman_ford(Graph G,int n,int s,int t,int path[],int success);
参数:
G:图,用邻接矩阵表示
n:图的顶点个数
s:开始节点
t:目标节点
path[]:用于返回由开始节点到目标节点的路径
success:函数是否执行成功
返回值:最短路径长度
注意:
输入的图的权可以为负,如果存在一个从源点可达的权为负的回路则success=0
顶点标号从0开始
用如下方法打印路径:
i=t;
while (i!=s)
{
printf("%d<--",i+1);
i=path[i];
}
printf("%d\n",s+1);
源程序:
int Bellman_ford(Graph G,int n,int s,int t,int path[],int success)
{
int i,j,k,d[max_vertexes];
for (i=0;i<n;i++) {d[i]=infinity;path[i]=0;}
d[s]=0;
for (k=1;k<n;k++)
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (d[j]>d[i]+G[i][j]) {d[j]=d[i]+G[i][j];path[j]=i;}
success=0;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (d[j]>d[i]+G[i][j]) return 0;
success=1;
return d[t];
}
4.Floyd-Warshall算法求每对节点间最短路径
语法:Floyd_Washall(Graph G,int n,Graph D,Graph P);
参数:
G:图,用邻接矩阵表示
n:图的顶点个数
D:D[i,j]表示从i到j的最短距离
P:P[i,j]表示从i到j的最短路径上j 的父节点
返回值:null
源程序:
void Floyd_Washall(Graph G,int n,Graph D,Graph P)
{
int i,j,k;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
{ D[i][j]=G[i][j];
P[i][j]=i; }
for (i=0;i<n;i++) { D[i][i]=0;P[i][i]=0; }
for (k=0;k<n;k++)
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (D[i][j]>D[i][k]+D[k][j])
{ D[i][j]=D[i][k]+D[k][j];
P[i][j]=P[k][j]; }
}
5.解欧拉图
语法:int Eular(int graph[8][8], int v, int *path)
参数:
graph:图,用邻接矩阵表示
v:图的顶点个数
path:D[i,j]表示从i到j的最短距离
注意:
此函数会删除图中的边
返回值:若找到欧拉回路则返回路径长度,否则返回-1
源程序:
int Eular(int graph[8][8], int v, int *path)
{
int start,a,b,count=0, deg,i;
int s[1000], sp=0;//栈,大小可根据需要改变
start=0;
while(true)
{
a=start;
s[sp++]=a;
for(b=-1,i=0;i<v;i++) if (graph[i][a]&& a!=i) {b=i;break;}
for(;b!=start&&b!=-1;)
{
s[sp++]=b;
graph[a][b]=graph[b][a]=0;
a=b;
for(b=-1,i=0;i<v;i++) if (graph[i][a]&& a!=i) {b=i;break;}
}
if (b==-1) return(-1);//若找不到Eular回路返回-1
s[sp++]=b;
graph[a][b]=graph[b][a]=0;
while(sp>0)
{
b=s[--sp];
for(i=0,deg=0;i<v;i++) if (graph[i][b]==1) {deg++; break;}
if (deg>0) break;
path[count++]=b;
}
if (sp==0) return(count);
start=b;
}
}
六、排序/查找
1.快速排序
语法:quicksort(int l,int r,int b[]);
参数:
l:排序上界,开始时l=0
r:排序下界,开始时r=数组元素个数
b[]:被排序的元素
返回值:null
注意:
输出升序序列
源程序:
void quicksort(int l,int r,int b[])
{
int i,j,x;
if(l>=r) return;
i=l;
j=r;
x=b[i];
while(i!=j)
{
while(b[j]>x&&j>i) j--;
if(i<j)
{
b[i]=b[j];
i++;
}
while(b[i]<x&&j>i)i++;
if(i<j)
{
b[j]=b[i];
j--;
}
}
b[i]=x;
quicksort(l,j-1,b);
quicksort(i+1,r,b);
}
2.希尔排序
语法:shellsort(int a[],int n);
参数:
n:数组元素个数
a[]:待排序数组
返回值:null
注意:
输出升序序列
源程序:
void shellsort(int a[],int n)
{
int i,j,g;
int temp,k;
g=n/2;
while(g!=0)
{
for(i=g+1;i<=n;i++)
{
temp=a[i];
j=i-g;
while(j>0)
{
k=j+g;
if(a[j]<=a[k])
j=0;
else
{
temp=a[j];a[j]=a[k];a[k]=temp;
}
j=j-g;
}
}
g=g/2;
}
}
3.选择法排序
语法:sort(int t[],int n);
参数:
t[]:待排序数组
n:数组t[]元素的个数
返回值:null
注意:
输出升序序列
小规模排序用
源程序:
void sort(int t[],int n)
{
int i,j,k,temp;
for (i=0;i<n;i++)
{
k=i;
for (j=i;j<n;j++) if (t[j]<t[k]) k=j;
temp=t[i];t[i]=t[k];t[k]=temp;
}
}
4.二分查找
语法:result=search_bin(int *t,int k);
参数:
t[]:待查找数组
k:查找关键字
返回值:如果k在t[]中存在,输出i:t[i]=k,否则输出-1
注意:
要求查找数组是有序升序序列
源程序:
int search_bin(int *t,int k)
{
int low=1,high=10,mid;
while (low<=high)
{
mid=(low+high)/2;
if (k==t[mid]) return mid;
else if (k<t[mid]) high=mid-1;
else low=mid+1;
}
return -1;
}
七、数据结构
1.顺序队列
源程序:
#define maxsize 100
typedef struct
{
int data[maxsize];
int front;
int rear;
} sqqueue;
int sqinit(sqqueue *p) //队列初始化
{
p->front=0;
p->rear=0;
return 1;
}
int enqueue(sqqueue *q, int e) //入队
{
if((q->rear+1)%maxsize==q->front)
return 0;
else
q->data[q->rear]=e;
q->rear=(q->rear+1)%maxsize;
return 1;
}
int dequeue(sqqueue *q) //出队
{
int e;
if (q->front==q->rear)
return 0;
e=q->data[q->front];
q->front=(q->front+1)%maxsize;
return e;
}
int empty(sqqueue *q) //判空
{
int v;
if (q->front==q->rear)
v=1;
else
v=0;
return v;
}
int gethead(sqqueue *q) //取得头元素
{
int e;
if (q->front==q->rear)
e=-1;
else
e=q->data[q->front];
return e;
}
void display(sqqueue *q) //显示所有元素
{
int s;
s=q->front;
printf("the sequeue is display:\n");
if (q->front==q->rear)
printf("the sequeue is empty!");
else
{
while(s<q->rear)
{
printf("->%d", q->data[s]);
s=(s+1)%maxsize;
}
printf("\n");
}
}
main(sqqueue *head) //函数使用样例
{
int n,i,m,x,y,select,xq;
printf("create a empty sequeue\n");
sqinit(head);
printf("please input the sequeue length:\n");
scanf("%d",&n);
for (i=0;i<n;i++)
{
printf("please input a sequeue value:\n");
scanf("%d",&m);
enqueue(head,m);
}
printf("head->rear:%d\n",head->rear);
printf("head->front:%d\n",head->front);
display(head);
printf("select 1 **** enqueue() \n");
printf("select 2 **** dequeue() \n");
printf("select 3 **** empty () \n");
printf("select 4 **** gethead() \n");
printf("select 5 **** display() \n");
printf("please select (1--5):");
scanf("%d",&select);
switch(select)
{
case 1:
{
printf("please input a value :\n ");
scanf("%d",&x);
enqueue(head,x);
display(head);
break;
}
case 2:
{
dequeue(head);
display(head);
break;
}
case 3:
{
if(empty(head))
printf("the sequeue is empty");
else
printf("the sequeue is full");
}
case 4:
{
y=gethead(head);
printf("output head value:%d\n",y);
break;
}
case 5:
{
display(head);
break;
}
}
}
}
2.顺序栈
源程序:
#define m 100
typedef struct
{
int stack[m];
int top;
} stackstru;
init(stackstru *s) /*装入栈*/
{
s->top=0;
return 1;
}
int push(stackstru *s,int x) /*入栈操作*/
{
if (s->top==m)
printf("the stack is overflow!\n");
else
{
s->top=s->top+1;
s->stack[s->top]=x;
}
}
void display(stackstru *s) /*显示栈所有数据*/
{
if(s->top==0)
printf("the stack is empty!\n");
else
{
while(s->top!=0)
{
printf("%d->",s->stack[s->top]);
s->top=s->top-1;
}
}
}
int pop(stackstru *s) /*出栈操作并返回被删除的那个记录*/
{
int y;
if(s->top==0)
printf("the stack is empty!\n");
else
{
y=s->stack[s->top];
s->top=s->top-1;
return y;
}
}
int gettop(stackstru *s) /*得到栈顶数*/
{
int e;
if(s->top==0)
return 0;
else
e=s->stack[s->top];
return e;
}
main(stackstru *p) //函数使用演示
{
int n,i,k,h,x1,x2,select;
printf("create a empty stack!\n");
init(p);
printf("input a stack length:\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("input a stack value:\n");
scanf("%d",&k);
push(p,k);
}
printf("select 1:display()\n");
printf("select 2:push()\n");
printf("select 3:pop()\n");
printf("select 4:gettop()\n");
printf("input a your select(1-4):\n");
scanf("%d",&select);
switch(select)
{
case 1:
{
display(p);
break;
}
case 2:
{
printf("input a push a value:\n");
scanf("%d",&h);
push(p,h);
display(p);
break;
}
case 3:
{
x1=pop(p);
printf("x1->%d\n",x1);
display(p);
break;
}
case 4:
{
x2=gettop(p);
printf("x2->%d",x2);
break;
}
}
}
3.链表
源程序:
# define null 0
typedef char ElemType; /* 字符型数据*/
typedef struct LNode
{
ElemType data;
struct LNode *next;
};
setnull(struct LNode **p);
int length (struct LNode **p);
ElemType get(struct LNode **p,int i);
void insert(struct LNode **p,ElemType x,int i);
int delete(struct LNode **p,int i);
void display(struct LNode **p);
main()
{
struct LNode *head,*q; /*定义静态变量*/
int select,x1,x2,x3,x4;
int i,n;
int m,g;
char e,y;
head=setnull(&head); /*建议链表并设置为空表*/
printf("请输入数据长度: ");
scanf("%d",&n);
for(i=1;i<n;i++);
{
printf("将数据插入到单链表中: ");
scanf("%d",&y);
insert(&head,y,i);} /*插入数据到链表*/
display(&head); /*显示链表所有数据*/
printf("select 1 求长度 length()\n");
printf("select 2 取结点 get()\n");
printf("select 3 求值查找 locate()\n");
printf("select 4 删除结点 delete()\n");
printf("input your select: ");
scanf("%d",&select);
switch(select)
{
case 1:
{
x1=length(&head);
printf("输出单链表的长度%d ",x1);
display(&head);
}break;
case 2:
{
printf("请输入要取得结点: ");
scanf("%d",&m);
x2=get(&head,m);
printf(x2);
display(&head);
}break;
case 3:
{
printf("请输入要查找的数据: ");
scanf("%d",&e);
x3=locate(&head,e);
printf(x3);
display(&head);
}break;
case 4:
{
printf("请输入要删除的结点: ");
scanf("%d",&g);
x4=delete(&head,g);
printf(x4);
display(&head);
}break;
}
}
}
setnull(struct LNode **p)
{
*p=null;
}
int length (struct LNode **p)
{
int n=0;
struct LNode *q=*p;
while (q!=null)
{
n++;
q=q->next;
}
return(n);
}
ElemType get(struct LNode **p,int i)
{
int j=1;
struct LNode *q=*p;
while (j<i&&q!=null)
{
q=q->next;
j++;
}
if(q!=null)
return(q->data);
else
printf("位置参数不正确!\n");
}
int locate(struct LNode **p,ElemType x)
{
int n=0;
struct LNode *q=*p;
while (q!=null&&q->data!=x)
{
q=q->next;
n++;
}
if(q==null)
return(-1);
else
return(n+1);
}
void insert(struct LNode **p,ElemType x,int i)
{
int j=1;
struct LNode *s,*q;
s=(struct LNode *)malloc(sizeof(struct LNode));
s->data=x;
q=*p;
if(i==1)
{
s->next=q;
p=s;
}
else
{
while(j<i-1&&q->next!=null)
{
q=q->next;
j++;
}
if(j==i-1)
{
s->next=q->next;
q->next=s;
}
else
printf("位置参数不正确!\n");
}
}
int delete(struct LNode **p,int i)
{
int j=1;
struct LNode *q=*p,*t;
if(i==1)
{
t=q;
*p=q->next;
}
else
{
while(j<i-1&&q->next!=null)
{
q=q->next;
j++;
}
if(q->next!=null&&j==i-1)
{
t=q->next;
q->next=t->next;
}
else
printf("位置参数不正确!\n");
}
if(t=null)
free(t);
}
void display(struct LNode **p)
{
struct LNode *q;
q=*p;
printf("单链表显示: ");
if(q==null)
printf("链表为空!");
else if (q->next==null)
printf("%c\n",q->data);
else
{
while(q->next!=null)
{
printf("%c->",q->data);
q=q->next;
}
printf("%c",q->data);
}
printf("\n");
}
4.链栈
源程序:
# define null 0
typedef struct stacknode
{
int data;
struct stacknode *next;
} stacklink;
typedef struct
{
stacklink *top;
int stacksize;
}stackk;
initlink(stackk *s)
{
s->top=(stacklink *)malloc(sizeof(stacklink));
s->top->data=0;
s->top->next=null;
}
int poplink(stackk *s)
{
stackk *p;int v;
if(s->top->next==null) printf("the stackis empty\n");
else
{
v=s->top->next->data;
p=s->top->next;
s->top=s->top->next;
}
free(p);
return v;
}
}
int pushlink(stackk *s,int x)
{
stackk *p;
p=(stacklink *)malloc(sizeof(stacklink));
p->data=x;
p->next=s->top->next;
s->top->next=p;
}
int gettop(stackk *s)
{
int e;
if(s==null) printf("the stack is empty!\n");
e=s->top->next->data;
return e;
}
display(stackk *s)
{
stackk *p;
p=s->top->next;
printf("display the stacklink:\n");
if (s->top=null) printf("the stacklink is empty!\n");
else
{
while(p)
{
printf("->%d",p->data);
p=p->next;
}
}
}
main(stacklink *p)
{
int n,k,i,select,h,x1,x2;
printf("create a empty stacklink!\n");
initlink(p);
printf("input a stacklink length:\n");
scanf("%d",&n);
for (i=1;i<=n;i++)
{printf("input a stacklink value:\n");
scanf("%d",&k);
pushlink(p,k);
}
printf("select 1:display()\n");
printf("select 2:pushlink()\n");
printf("select 3:poplink()\n");
printf("select 4:gettop()\n");
printf("input a your select(1-4):\n");
scanf("%d",&select);
switch(select)
{case 1:
{display(p);break;}
case 2:
{printf("input a push a value :\n");
scanf("%d",&h);
pushlink(p,h);
display(p);
break;}
case 3:
{x1=poplink(p);printf("x1->%d\n",x1);
display(p);
break;}
case 4:
{x2=gettop(p);printf("x2->%d",x2);
break;}
}
}
5.二叉树
源程序:
typedef struct bitnode
{
char data;
struct bitnode *lchild, *rchild;
}bitnode, *bitree;
void createbitree(t,n)
bitnode ** t;
int *n;
{
char x;
bitnode *q;
*n=*n+1;
printf("\n Input %d DATA:",*n);
x=getchar();
if(x!='\n') getchar();
if (x=='\n')
return;
q=(bitnode*)malloc(sizeof(bitnode));
q->data=x;
q->lchild=NULL;
q->rchild=NULL;
*t=q;
printf(" This Address is: %o, Data is: %c,\n Left Pointer is: %o,
Right Pointer is: %o",q,q->data,q->lchild,q->rchild);
createbitree(&q->lchild,n);
createbitree(&q->rchild,n);
return;
}
void visit(e)
bitnode *e;
{
printf(" Address: %o, Data: %c, Left Pointer: %o, Right Pointer:
%o\n",e,e->data,e->lchild,e->rchild);
}
void preordertraverse(t)
bitnode *t;
{
if(t)
{
visit(t);
preordertraverse(t->lchild);
preordertraverse(t->rchild);
return ;
}
else
return ;
}
void countleaf(t,c)
bitnode *t;
int *c;
{
if(t!=NULL)
{
if (t->lchild==NULL && t->rchild==NULL)
{*c=*c+1;
}
countleaf(t->lchild,c);
countleaf(t->rchild,c);
}
return;
}
int treehigh(t)
bitnode *t;
{
int lh,rh,h;
if(t==NULL)
h=0;
else
{
lh=treehigh(t->lchild);
rh=treehigh(t->rchild);
h=(lh>rh ? lh:rh)+1;
}
return h;
}
main()
{
bitnode *t; int count=0;
int n=0;
printf("\n Please input TREE Data:\n");
createbitree(&t,&n);
printf("\n This is TREE struct: \n");
preordertraverse(t);
countleaf(t,&count);
printf("\n This TREE has %d leaves ",count);
printf(" , High of The TREE is: %d\n",treehigh(t));
}
八、高精度运算专题
1.专题函数说明
说明:
本栏为本专题所有程序的公用部分,调用本专题任何一个程序必须加上本栏的代码
input/print为高精度数输入输出,调用格式为input(hp HightPoint,"123456")/print(hp
HighPoint)
本栏为纯C++代码
源程序:
#include <iostream>
using namespace std;
#define maxsize 100
struct hp
{
int len;
int s[maxsize+1];
};
void input(hp &a,string str)
{
int i;
while(str[0]=='0' && str.size()!=1)
str.erase(0,1);
a.len=(int)str.size();
for(i=1;i<=a.len;++i)
a.s[i]=str[a.len-i]-48;
for (i=a.len+1;i<=maxsize;++i)
a.s[i]=0;
}
void print(const hp &y)
{
int i;
for(i=y.len;i>=1;i--)
cout<<y.s[i];
cout<<endl;
}
2.高精度数比较
语法:int result=compare(const hp &a,const hp &b);
参数:
a,b:进行比较的高精度数字
返回值:比较结果,a>b返回正数,a=b返回0,a<b返回负数
源程序:
int compare(const hp &a,const hp &b)
{
int len;
if(a.len>b.len)
len=a.len;
else
len=b.len;
while(len>0 && a.s[len]==b.s[len]) len--;
if(len==0)
return 0;
else
return a.s[len]-b.s[len];
}
3.高精度数加法
语法:plus(const hp &a,const hp &b,hp &c);
参数:
a,b:进行加法的高精度数字
返回值:返回相加结果到c中
源程序:
void plus(const hp &a,const hp &b,hp &c)
{
int i,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
if(a.len>b.len) len=a.len;
else len=b.len;
for(i=1;i<=len;i++)
{
c.s[i]+=a.s[i]+b.s[i];
if(c.s[i]>=10)
{
c.s[i]-=10;
c.s[i+1]++;
}
}
if(c.s[len+1]>0) len++;
c.len=len;
}
4.高精度数减法
语法:subtract(const hp &a,const hp &b,hp &c);
参数:
a,b:进行减法的高精度数字,a是被减数,b是减数,不支持负数
返回值:返回结果到c中
源程序:
void subtract(const hp &a,const hp &b,hp &c)
{
int i,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
if(a.len>b.len) len=a.len;
else len=b.len;
for(i=1;i<=len;i++)
{
c.s[i]+=a.s[i]-b.s[i];
if(c.s[i]<0)
{
c.s[i]+=10;
c.s[i+1]--;
}
}
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
5.高精度乘10
语法:multiply10(hp &a);
参数:
a:进行乘法的高精度数字
返回值:返回结果到 a 中
源程序:
void multiply10(hp &a)
{
int i;
for(i=a.len;i>=1;i--)
a.s[i+1]=a.s[i];
a.s[1]=0;
a.len++;
while(a.len>1&&a.s[a.len]==0) a.len--;
}
6.高精度乘单精度
语法:multiply(const hp &a,int b,hp &c);
参数:
a:进行乘法的高精度数字
b:进行乘法的单精度数字
返回值:返回结果到 c 中
源程序:
void multiply(const hp &a,int b,hp &c)
{
int i,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
len=a.len;
for(i=1;i<=len;i++)
{
c.s[i]+=a.s[i]*b;
c.s[i+1]+=c.s[i]/10;
c.s[i]%=10;
}
len++;
while(c.s[len]>=10)
{
c.s[len+1]+=c.s[len]/10;
c.s[len]%=10;
len++;
}
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
7.高精度乘高精度
语法:multiplyh(const hp &a,const hp &b,hp &c);
参数:
a,b:进行乘法的高精度数字
返回值:返回结果到 c 中
源程序:
void multiplyh(const hp &a,const hp &b,hp &c)
{
int i,j,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
for(i=1;i<=a.len;i++)
for(j=1;j<=b.len;j++)
{
c.s[i+j-1]+=a.s[i]*b.s[j];
c.s[i+j]+=c.s[i+j-1]/10;
c.s[i+j-1]%=10;
}
len=a.len+b.len+1;
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
8.高精度除单精度
语法:divide(const hp &a,int b,hp &c,int &d);
参数:
a:进行除法的高精度数字
返回值:返回商到 c 中,余数到 d 中
源程序:
void divide(const hp &a,int b,hp &c,int &d)
{
int i,len;
for(i=1;i<=maxsize;i++) c.s[i]=0;
len=a.len;
d=0;
for(i=len;i>=1;i--)
{
d=d*10+a.s[i];
c.s[i]=d/b;
d%=b;
}
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
9.高精度除高精度
语法:divideh(const hp &a,const hp &b,hp &c,hp &d);
参数:
a,b:进行除法的高精度数字
返回值:返回商到 c 中,余数到 d 中
注意:
需要compare、multiply10、subtract
源程序:
void divideh(const hp &a,const hp &b,hp &c,hp &d)
{
hp e;
int i,len;
for(i=1;i<=maxsize;i++)
{
c.s[i]=0;
d.s[i]=0;
}
len=a.len;
d.len=1;
for(i=len;i>=1;i--)
{
multiply10(d);
d.s[1]=a.s[i];
while(compare(d,b)>=0)
{
subtract(d,b,e);
d=e;
c.s[i]++;
}
}
while(len>1&&c.s[len]==0) len--;
c.len=len;
}
C++
#include<fstream.h>
ifstream filein("file.in");
ofstream fileout("file.out");
int main(){
int a,b;
filein>>a>>b;
fileout<<(a+b);
return 0;
}
C:
#include<stdio.h>
int main(){
freopen("file.in","r",stdin);
freopen("file.out","w",stdout);
int a,b;
scanf("%d%d",&a,&b);
printf("%d",a+b);
fclose(stdin); fclose(stdout);
return 0;
}
输入一开始就会说有N个Input Block,下面接着是N个Input Block。
如1526
Code:
cin >> n;
for( i=0 ; i<n ; i++ )
{
....
}
输入不说明有多少个Input Block,但以某个特殊输入为结束标志。
如1115
Code:
while( cin >> n && n != 0 )
{
....
}
输入不说明有多少个Input Block,以EOF为结束标志。
如1001
Code:
while( cin >> a >> b )
{
....
}
输入是一整行的字符串的
如1392
如果你用char buf[ 255 ]; 来保存的:
Code:
cin.getline( buf, 255 );
如果你用string buf;来保存的:
Code:
getline( cin , buf );
输出部分:
一个Input Block对应一个Output Block,Output Block之间没有空行。
如1001
Code:
{
...
cout << ans << endl;
}
一个Input Block对应一个Output Block,Output Block之间有空行。
如1152
Code:
int nCases = 0;
...
{
if ( nCases++ ) cout << endl;
...
cout << ans << endl;
}
一个Input Block对应一个Output Block,每个Output Block之后都有空行。
如1457
Code:
{
...
cout << ans << endl << endl; }
几何公式:
1.长方体
长方体的表面积=2×(a×b+b×c+c×a)
长方体的体积=a×b×c(这里a、b、c分别表示长方体的长、宽、高)。
2.正方体
正方体的表面积=6×a2
正方体的体积=a3(这里a为正方体的棱长)。
3.圆柱体
圆柱体的侧面积=2πRh
圆柱体的全面积=2πRh+2πR2=2πR(h+R)
圆柱体的体积=πR2h(这里R表示圆柱体底面圆的半径,h表示圆柱的高)。
4.圆锥体
圆锥体的侧面积=πRl
圆锥体的全面积=πRl+πR2
母线长与高)。
积=6×a2
正方体的体积=a3(这里a为正方体的棱长)。
3.圆柱体
圆柱体的侧面积=2πRh
圆柱体的全面积=2πRh+2πR2=2πR(h+R)
圆柱体的体积=πR2h(这里R表示圆柱体底面圆的半径,h表示圆柱的高)。
4.圆锥体
圆锥体的侧面积=πRl
圆锥体的全面积=πRl+πR2
母线长与高)。