C++常用经典算法及其实现Word下载.docx

上传人:b****4 文档编号:16175702 上传时间:2022-11-21 格式:DOCX 页数:21 大小:24.01KB
下载 相关 举报
C++常用经典算法及其实现Word下载.docx_第1页
第1页 / 共21页
C++常用经典算法及其实现Word下载.docx_第2页
第2页 / 共21页
C++常用经典算法及其实现Word下载.docx_第3页
第3页 / 共21页
C++常用经典算法及其实现Word下载.docx_第4页
第4页 / 共21页
C++常用经典算法及其实现Word下载.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

C++常用经典算法及其实现Word下载.docx

《C++常用经典算法及其实现Word下载.docx》由会员分享,可在线阅读,更多相关《C++常用经典算法及其实现Word下载.docx(21页珍藏版)》请在冰豆网上搜索。

C++常用经典算法及其实现Word下载.docx

for(intj=1;

j<

=n-i;

j++)//相邻的两两比较

if(a[j]<

a[j+1]){inttemp=a[j];

a[j]=a[j+1];

a[j+1]=temp;

或者

for(intj=n-i;

j>

=1;

j--)//相邻的两两比较

paopao(),适用于n比较小的排序

三、桶排序

voidbucketsort(void)//a的取值范围已知。

如a<

=cmax。

{memset(tong,0,sizeof(tong));

//桶初始化

for(inti=1;

=n;

i++)//读入n个数

{inta

cin>

a;

tong[a]++;

}//相应的桶号计数器加1

for(inti=1;

=cmax;

i++)

{if(tong[i]>

0)//当桶中装的树大于0,说明i出现过tong[i]次,否则没出现过i

while(tong[i]!

=0)

{tong[i]--;

cout<

<

’‘;

桶排序适用于那些待排序的关键字的值在已知范围的排序。

四、合(归)并排序

voidmerge(intl,intm,intr)//合并[l,m]和[m+1,r]两个已经有序的区间

{intb[101];

//借助一个新的数组B,使两个有序的子区间合并成一个有序的区间,b数组的大小要注意

inth,t,k;

k=0;

//用于新数组B的指针

h=l;

t=m+1;

//让h指向第一个区间的第一个元素,t指向第二个区间的第一个元素。

while((h<

=m)&

&

(t<

=r))//在指针h和t没有到区间尾时,把两个区间的元素抄在新数组中

{k++;

//新数组指针加1

if(a[h]<

a[t]){b[k]=a[h];

h++;

//抄第一个区间元素到新数组

else{b[k]=a[t];

t++;

//抄第二个区间元素到新数组

}

=m){k++;

b[k]=a[h];

//如果第一个区间没有抄结束,把剩下的抄在新数组中

while(t<

=r){k++;

b[k]=a[t];

//如果第二个区间没有抄结束,把剩下的抄在新数组中

for(into=1;

o<

=k;

o++)//把新数组中的元素,再抄回原来的区间,这两个连续的区间变为有序的区间。

a[l+o-1]=b[o];

voidmergesort(intx,inty)//对区间[x,y]进行二路归并排序

{

intmid;

if(x>

=y)return;

mid=(x+y)/2;

//求[x,y]区间,中间的那个点mid,mid把x,y区间一分为二

mergesort(x,mid);

//对前一段进行二路归并

mergesort(mid+1,y);

//对后一段进行二路归并

merge(x,mid,y);

//把已经有序的前后两段进行合并

归并排序应用了分治思想,把一个大问题,变成两个小问题。

二分是分治的思想。

五、二分查找

intfind(intx,inty,intm)//在[x,y]区间查找关键字等于m的元素下标

{inthead,tail,mid;

head=x;

tail=y;

mid=((x+y)/2);

//取中间元素下标

if(a[mid]==m)returnmid;

//如果中间元素值为m返回中间元素下标mid

if(head>

tail)return0;

//如果x>

y,查找失败,返回0

if(m>

a[mid]) 

//如果m比中间元素大,在后半区间查找,返回后半区间查找结果

returnfind(mid+1,tail);

else//如果m比中间元素小,在前半区间查找,返回后前区间查找结果

returnfind(head,mid-1);

六、高精度加法

#include<

iostream>

cstring>

usingnamespacestd;

intmain()

stringstr1,str2;

inta[250],b[250],len;

//数组的大小决定了计算的高精度最大位数

inti;

memset(a,0,sizeof(a));

memset(b,0,sizeof(b));

cin>

str1>

str2;

//输入两个字符串

a[0]=str1.length();

//取得第一个字符串的长度

for(i=1;

=a[0];

//把第一个字符串转换为整数,存放在数组a中

a[i]=str1[a[0]-i]-'

0'

;

b[0]=str2.length();

//取得第二个字符串长度

=b[0];

//把第二个字符串中的每一位转换为整数,存放在数组B中

b[i]=str2[b[0]-i]-'

len=(a[0]>

b[0]?

a[0]:

b[0]);

//取两个字符串最大的长度

=len;

//做按位加法,同时处理进位

{

a[i]+=b[i];

a[i+1]+=a[i]/10;

a[i]%=10;

len++;

//下面是去掉最高位的0,然后输出。

while((a[len]==0)&

(len>

1))len--;

for(i=len;

i>

i--)

cout<

a[i];

return0;

注意:

两个数相加,结果的位数,应该比两个数中大的那个数多一位。

七、高精度减法

intcompare(strings1,strings2);

if((compare(str1,str2))==0) 

//大于等于,做按位减,并处理借位。

{a[i]-=b[i];

if(a[i]<

0){a[i+1]--;

a[i]+=10;

a[0]++;

while((a[a[0]]==0)&

(a[0]>

1))a[0]--;

for(i=a[0];

endl;

else

'

-'

//小于就输出负号

//做按位减,大的减小的

{b[i]-=a[i];

if(b[i]<

0){b[i+1]--;

b[i]+=10;

b[0]++;

while((b[b[0]]==0)&

(b[0]>

1))b[0]--;

for(i=b[0];

b[i];

intcompare(strings1,strings2) 

//比较字符串(两个数)数字的大小,大于等于返回0,小于返回1。

if(s1.length()>

s2.length())return0;

//先比较长度,哪个字符串长,对应的那个数就大

if(s1.length()<

s2.length())return1;

for(inti=0;

=s1.length();

//长度相同时,就一位一位比较。

if(s1[i]>

s2[i])return0;

if(s1[i]<

s2[i])return1;

//如果长度相同,每一位也一样,就返回0,说明相等

做减法时,首先要判断两个字符串的大小,决定是否输出负号,然后就是按位减法,注意处理借位。

八、高精度乘法

inta[250],b[250],c[500],len;

//250位以内的两个数相乘

inti,j;

memset(c,0,sizeof(c));

//做按位乘法同时处理进位,注意循环内语句的写法。

for(j=1;

j++)

c[i+j-1]+=a[i]*b[j];

c[i+j]+=c[i+j-1]/10;

c[i+j-1]%=10;

len=a[0]+b[0]+1;

//去掉最高位的0,然后输出

while((c[len]==0)&

//为什么此处要len>

1?

?

c[i];

两个数相乘,结果的位数应该是这两个数的位数和减1。

优化:

万进制

voidnum1(ints[],stringst1);

inta[2501],b[2501],c[5002];

//此处可以进行2500位万进制乘法,即10000位十进制乘法。

Intmain()

intlen;

num1(a,str1);

//把str1从最低位开始,每4位存放在数组a中

num1(b,str2);

//把str2从最低位开始,每4位存放在数组b中

i++)//作按位乘法并处理进位,此处是万进制进位

c[i+j]+=c[i+j-1]/10000;

c[i+j-1]%=10000;

len=a[0]+b[0];

//a[0]和b[0]存放的是每个数按4位处理的位数

while((c[len]==0)&

//去掉高位的0,并输出最高位

c[len];

for(inti=len-1;

i--)//把剩下来的每一位还原成4位输出

if(c[i]<

1000)cout<

’0’;

100)cout<

10)cout<

voidnum1(ints[],stringst1)//此函数的作用就是把字符串st1,按4位一组存放在数组s中

intk=1,count=1;

s[0]=st1.length();

//存放st1的长度,省去一长度变量

for(inti=s[0]-1;

=0;

i--)//从最低位开始,处理每一位

{if(count%4==0){s[k]+=(st1[i]-‘0’)*1000;

if(i!

=0)k++;

if(count%4==1)s[k]=(st1[i]-‘0’);

if(count%4==2)s[k]+=(st1[i]-‘0’)*10;

if(count%4==3)s[k]+=(st1[i]-‘0’)*100;

count++;

s[0]=k;

//存放数组的位数,就是按4位处理后的万进制数的位数。

Return;

九、高精度除法(没讲)

十、筛选法建立素数表

voidmaketable(intx)//建立X以内的素数表prim,prim[i]为0,表示i为素数,为1表示不是质数

memset(prim,0,sizeof(prim));

//初始化质数表

prim[0]=1;

prim[1]=1;

prim[2]=0;

//用筛选法求X以内的质数表

for(inti=2;

=x;

if(prim[i]==0)

{intj=2*i;

while(j<

=x)

{prim[j]=1;

j=j+i;

对于那些算法中,经常要判断素数的问题,建立一个素数表,可以达到一劳永逸的目的。

十一、深度优先搜索

voiddfs(intx) 

\\以图的深度优先遍历为例。

x<

‘‘;

\\访问x顶点

visited[x]=1;

\\作已访问的标记

for(intk=1;

k<

k++)\\对与顶点x相邻而又没访问过的结点k进行深度优先搜索。

if((a[x][k]==1)&

(visited[k]==0))

dfs(k);

十二、广度优先搜索

void 

bfs(void)//按广度优先非递归遍历图G,n个顶点,编号为1..n。

注:

图不一定是连通的

{//使用辅助队列Q和访问标记数组visited。

for(v=1;

v<

v++) 

visited[v]=0;

//标记数组初始化

v<

v++)

if(visited[v]==0){ 

//v尚未访问

inth=1,r=1;

//置空的辅助队列q

visited[v]=1;

//顶点v,作访问标记

//访问顶点v

q[r]=v;

//v入队列

=r)//当队列非空时循环

inttmp=q[h];

//队头元素出队,并赋值给tmp

if((visited[j]==0)&

(a[tmp][j]==1))

{//j为tmp的尚未访问的邻接顶点

visited[j]=1;

对j作访问标记

访问j

r++;

//队尾指针加1

q[r]=j;

//j入队

//end-if

}//end-while

十三、二叉树的前序、中序和后序遍历

voidpreorder(intx)//二叉树的先序遍历

if(x==0)return;

x;

//先访问根

preorder(a[x].ld);

//再先序遍历根的左子树

preorder(a[x].rd);

//最后先序遍历根的右子树

voidinorder(intx)//二叉树的中序遍历

//先中序遍历根的左子树

//再访问根

//最后中序遍历根的右子树

voidreorder(intx)//二叉树的后序遍历

//先后序遍历根的左子树

//再后序遍历根的右子树

//最后访问根

十四、树转换为二叉树算法

十五、二叉排序树

十六、哈夫曼树

voidhaff(void)//构建哈夫曼树

for(inti=n+1;

=2*n-1;

i++)//依次生成n-1个结点

{intl=fmin(i-1);

//查找权值最小的结点的编号l

a[i].lchild=l;

//把l作为结点i的左孩子

a[l].father=i;

//把l的父结点修改为i

intr=fmin(i-1);

//查找次小权值的编号r

a[i].rchild=r;

//把l作为结点i的右孩子

a[r].father=i;

//把r的父结点修改为i

a[i].da=a[l].da+a[r].da;

//合并l,j结点,生成新结点i

intfmin(intk)//在1到K中寻找最小的权值的编号

intmins=0;

for(ints=1;

s<

s++)

if((a[mins].da>

a[s].da)&

(a[s].father==0))//a[s].father=0,说明这个结点还不是别个结点

mins=s;

//的孩子,不等于0说明这个结点已经用过。

returnmins;

voidinorder(intx)//递归生成哈夫曼编码

if(a[x].father==0){a[x].code=”“;

}//根结点

if(a[a[x].father].lchild==x) 

a[x].code=a[a[x].father].code+'

if(a[a[x].father].rchild==x) 

1'

if(a[x].lchild!

=0)inorder(a[x].lchild);

//递归生成左子树

if((a[x].lchild==0)&

(a[x].rchild==0))//输出叶子结点

a[x].da<

:

a[x].code<

if(a[x].rchild!

=0)inorder(a[x].rchild);

//递归生成右子树

十七、并查集

intgetfather(intx)//非递归求X结点的根结点的编号

{while(x!

=father[x])

x=father[x];

returnx;

intgetfather(intx)//递归求X结点的根结点的编号

{if(x==father[x])returnx;

el

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 兵器核科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1