当前位置:首页 » 操作系统 » 算法程序里的

算法程序里的

发布时间: 2024-07-30 01:37:40

❶ 程序员都应该精通的六种算法,你会了吗

对于一名优秀的程序员来说,面对一个项目的需求的时候,一定会在脑海里浮现出最适合解决这个问题的方法是什么,选对了算法,就会起到事半功倍的效果,反之,则可能会使程序运行效率低下,还容易出bug。因此,熟悉掌握常用的算法,是对于一个优秀程序员最基本的要求。


那么,常用的算法都有哪些呢?一般来讲,在我们日常工作中涉及到的算法,通常分为以下几个类型:分治、贪心、迭代、枚举、回溯、动态规划。下面我们来一一介绍这几种算法。


一、分治算法


分治算法,顾名思义,是将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。


分治算法一般分为三个部分:分解问题、解决问题、合并解。

分治算法适用于那些问题的规模缩小到一定程度就可以解决、并且各子问题之间相互独立,求出来的解可以合并为该问题的解的情况。


典型例子比如求解一个无序数组中的最大值,即可以采用分治算法,示例如下:


def pidAndConquer(arr,leftIndex,rightIndex):

if(rightIndex==leftIndex+1 || rightIndex==leftIndex){

return Math.max(arr[leftIndex],arr[rightIndex]);

}

int mid=(leftIndex+rightIndex)/2;

int leftMax=pidAndConquer(arr,leftIndex,mid);

int rightMax=pidAndConquer(arr,mid,rightIndex);

return Math.max(leftMax,rightMax);


二、贪心算法


贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。


贪心算法的基本思路是把问题分成若干个子问题,然后对每个子问题求解,得到子问题的局部最优解,最后再把子问题的最优解合并成原问题的一个解。这里要注意一点就是贪心算法得到的不一定是全局最优解。这一缺陷导致了贪心算法的适用范围较少,更大的用途在于平衡算法效率和最终结果应用,类似于:反正就走这么多步,肯定给你一个值,至于是不是最优的,那我就管不了了。就好像去菜市场买几样菜,可以经过反复比价之后再买,或者是看到有卖的不管三七二十一先买了,总之最终结果是菜能买回来,但搞不好多花了几块钱。


典型例子比如部分背包问题:有n个物体,第i个物体的重量为Wi,价值为Vi,在总重量不超过C的情况下让总价值尽量高。每一个物体可以只取走一部分,价值和重量按比例计算。

贪心策略就是,每次都先拿性价比高的,判断不超过C。


三、迭代算法


迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程。迭代算法是用计算机解决问题的一种基本方法,它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。最终得到问题的结果。


迭代算法适用于那些每步输入参数变量一定,前值可以作为下一步输入参数的问题。


典型例子比如说,用迭代算法计算斐波那契数列。


四、枚举算法


枚举算法是我们在日常中使用到的最多的一个算法,它的核心思想就是:枚举所有的可能。枚举法的本质就是从所有候选答案中去搜索正确地解。

枚举算法适用于候选答案数量一定的情况。


典型例子包括鸡钱问题,有公鸡5,母鸡3,三小鸡1,求m钱n鸡的所有可能解。可以采用一个三重循环将所有情况枚举出来。代码如下:



五、回溯算法


回溯算法是一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。


典型例子是8皇后算法。在8 8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问一共有多少种摆法。


回溯法是求解皇后问题最经典的方法。算法的思想在于如果一个皇后选定了位置,那么下一个皇后的位置便被限制住了,下一个皇后需要一直找直到找到安全位置,如果没有找到,那么便要回溯到上一个皇后,那么上一个皇后的位置就要改变,这样一直递归直到所有的情况都被举出。


六、动态规划算法


动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。


动态规划算法适用于当某阶段状态给定以后,在这阶段以后的过程的发展不受这段以前各段状态的影响,即无后效性的问题。


典型例子比如说背包问题,给定背包容量及物品重量和价值,要求背包装的物品价值最大。


❷ 算法与程序有什么异同

用一句说话答你的话, 那就是 : 算法只是程序中可以处理的其中一件事.
算法, 基本上就是以数学的形式去对一个 "模式" 的模术, 例如最简单的毕氏定理 a^2 + b^2 = c^2 . 当然还有更多更复杂的算法, 例如 OpenCV 对面容辨识的各种算法, 从距离, 比例, 颜色深浅来定位那里是双眼, 嘴巴, 人面... 但总言之, 算法离不开 f(x) = ..... 这个框架. 你可以从算法中求 x 等于甚么, 又或者从已知的 x 去找出算法中其他的未知数.. 算法, 就是数学

程序, 基本有: 输入 -> 处理 -> 输出 -> 存取档案这几个部份, 当中便有豪多样的可能性, 光是输入, 就已可分由用者输入, 从档案输入, 甚至... 从算法中输入!! 又来到处理, 算法所不能做到的的一件事, 就是程序可以做出逻辑的分支, if ... elseif... else... 整个流程可以随意跳跃...

最后一句就是, 算法是死的, 程序是活的.

❸ 算法在程序里有啥意义

算法可以优化程序的性能,比如普通的程序员写一个遍历可能就是for循环再叠加放for循环,而如果说是使用算法的话就可以从队列以及二叉树等其他一些角度来考虑。合适的算法能够大大的缩减程序的运行时间也节省服务器的性能。
希望可以帮到您,感谢您的采纳。

❹ 算法与程序的区别与联系

算法和程序的区别是:

(1) 两者定义不同。算法是对特定问题求解步骤的描述,它是有限序列指令。而程序是实现预期目的而进行操作的一系列语句和指令。

说通俗一些算法是解决一个问题的思路,程序,是解决这些问题所具体好写的代码。算法没有语言界限。他只是一个思路。为实现相同的一个算法,用不同语言编写的程序会不一样。

(2)两者的书写规定不同。程序必须用规定的程序设计语言来写,而算法很随意。算法是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。算法常常含有重复的步骤和一些逻辑判断。

简单算法举例 例:求 1*2*3*4*5

步骤 1 :先求 1*2 ,得到结果 2 。

步骤 2 :将步骤 1 得到的乘积 2 再乘以 3 ,得到结果 6 。

步骤 3 :将步骤 2 得到的乘积 6 再乘以 4 ,得到结果 24 。

步骤 4 :将步骤 3 得到的乘积 24 再乘以 5 ,得到最后结果 120 。

算法与程序的联系 :

算法和程序都是指令的有限序列 ,但是程序是算法,而算法不一定是 程序。程序 = 数据结构 + 算法。算法的主要目的在于为人们提供阅读了解所执行的工作流程与步骤。数据结构与算法要通过程序的实现,才能由计算机系统来执行。可以这样理解,数据结构和算法形成了可执行的程序。

(4)算法程序里的扩展阅读

算法的要素:

一、数据对象的运算和操作:计算机可以执行的基本操作是以指令的形式描述的。一个计算机系统能执行的所有指令的集合,成为该计算机系统的指令系统。一个计算机的基本运算和操作有如下四类:

1、算术运算:加减乘除等运算。

2、逻辑运算:或、且、非等运算。

3、关系运算:大于、小于、等于、不等于等运算。

4、数据传输:输入、输出、赋值等运算。

二、算法的控制结构:一个算法的功能结构不仅取决于所选用的操作,而且还与各操作之间的执行顺序有关。

❺ C语言中什么叫算法,算法在程序设计中的重要作用

一、什么是算法
算法是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。算法常常含有重复的步骤和一些比较或逻辑判断。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
算法的时间复杂度是指算法需要消耗的时间资源。一般来说,计算机算法是问题规模n 的函数f(n),算法执行的时间的增长率与f(n) 的增长率正相关,称作渐进时间复杂度(Asymptotic Time Complexity)。时间复杂度用“O(数量级)”来表示,称为“阶”。常见的时间复杂度有: O(1)常数阶;O(log2n)对数阶;O(n)线性阶;O(n2)平方阶。
算法的空间复杂度是指算法需要消耗的空间资源。其计算和表示方法与时间复杂度类似,一般都用复杂度的渐近性来表示。同时间复杂度相比,空间复杂度的分析要简单得多。

二、算法设计的方法
1.递推法
递推法是利用问题本身所具有的一种递推关系求问题解的一种方法。设要求问题规模为N的解,当N=1时,解或为已知,或能非常方便地得到解。能采用递推法构造算法的问题有重要的递推性质,即当得到问题规模为i-1的解后,由问题的递推性质,能从已求得的规模为1,2,…,i-1的一系列解,构造出问题规模为I的解。这样,程序可从i=0或i=1出发,重复地,由已知至i-1规模的解,通过递推,获得规模为i的解,直至得到规模为N的解。
【问题】 阶乘计算
问题描述:编写程序,对给定的n(n≤100),计算并输出k的阶乘k!(k=1,2,…,n)的全部有效数字。
由于要求的整数可能大大超出一般整数的位数,程序用一维数组存储长整数,存储长整数数组的每个元素只存储长整数的一位数字。如有m位成整数N用数组a[ ]存储:
N=a[m]×10m-1+a[m-1]×10m-2+ … +a[2]×101+a[1]×100
并用a[0]存储长整数N的位数m,即a[0]=m。按上述约定,数组的每个元素存储k的阶乘k!的一位数字,并从低位到高位依次存于数组的第二个元素、第三个元素……。例如,5!=120,在数组中的存储形式为:
3 0 2 1 ……
首元素3表示长整数是一个3位数,接着是低位到高位依次是0、2、1,表示成整数120。
计算阶乘k!可采用对已求得的阶乘(k-1)!连续累加k-1次后求得。例如,已知4!=24,计算5!,可对原来的24累加4次24后得到120。细节见以下程序。
# include <stdio.h>
# include <malloc.h>
......
2.递归
递归是设计和描述算法的一种有力的工具,由于它在复杂算法的描述中被经常采用,为此在进一步介绍其他算法设计方法之前先讨论它。
能采用递归描述的算法通常有这样的特征:为求解规模为N的问题,设法将它分解成规模较小的问题,然后从这些小问题的解方便地构造出大问题的解,并且这些规模较小的问题也能采用同样的分解和综合方法,分解成规模更小的问题,并从这些更小问题的解构造出规模较大问题的解。特别地,当规模N=1时,能直接得解。
【问题】 编写计算斐波那契(Fibonacci)数列的第n项函数fib(n)。
斐波那契数列为:0、1、1、2、3、……,即:
fib(0)=0;
fib(1)=1;
fib(n)=fib(n-1)+fib(n-2) (当n>1时)。
写成递归函数有:
int fib(int n)
{ if (n==0) return 0;
if (n==1) return 1;
if (n>1) return fib(n-1)+fib(n-2);
}
递归算法的执行过程分递推和回归两个阶段。在递推阶段,把较复杂的问题(规模为n)的求解推到比原问题简单一些的问题(规模小于n)的求解。例如上例中,求解fib(n),把它推到求解fib(n-1)和fib(n-2)。也就是说,为计算fib(n),必须先计算fib(n-1)和fib(n-2),而计算fib(n-1)和fib(n-2),又必须先计算fib(n-3)和fib(n-4)。依次类推,直至计算fib(1)和fib(0),分别能立即得到结果1和0。在递推阶段,必须要有终止递归的情况。例如在函数fib中,当n为1和0的情况。
在回归阶段,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解,例如得到fib(1)和fib(0)后,返回得到fib(2)的结果,……,在得到了fib(n-1)和fib(n-2)的结果后,返回得到fib(n)的结果。
在编写递归函数时要注意,函数中的局部变量和参数知识局限于当前调用层,当递推进入“简单问题”层时,原来层次上的参数和局部变量便被隐蔽起来。在一系列“简单问题”层,它们各有自己的参数和局部变量。
由于递归引起一系列的函数调用,并且可能会有一系列的重复计算,递归算法的执行效率相对较低。当某个递归算法能较方便地转换成递推算法时,通常按递推算法编写程序。例如上例计算斐波那契数列的第n项的函数fib(n)应采用递推算法,即从斐波那契数列的前两项出发,逐次由前两项计算出下一项,直至计算出要求的第n项。
【问题】 组合问题
问题描述:找出从自然数1、2、……、n中任取r个数的所有组合。例如n=5,r=3的所有组合为: (1)5、4、3 (2)5、4、2 (3)5、4、1
(4)5、3、2 (5)5、3、1 (6)5、2、1
(7)4、3、2 (8)4、3、1 (9)4、2、1
(10)3、2、1
分析所列的10个组合,可以采用这样的递归思想来考虑求组合函数的算法。设函数为void comb(int m,int k)为找出从自然数1、2、……、m中任取k个数的所有组合。当组合的第一个数字选定时,其后的数字是从余下的m-1个数中取k-1数的组合。这就将求m个数中取k个数的组合问题转化成求m-1个数中取k-1个数的组合问题。设函数引入工作数组a[ ]存放求出的组合的数字,约定函数将确定的k个数字组合的第一个数字放在a[k]中,当一个组合求出后,才将a[ ]中的一个组合输出。第一个数可以是m、m-1、……、k,函数将确定组合的第一个数字放入数组后,有两种可能的选择,因还未去顶组合的其余元素,继续递归去确定;或因已确定了组合的全部元素,输出这个组合。细节见以下程序中的函数comb。
【程序】
# include <stdio.h>
# define MAXN 100
int a[MAXN];
void comb(int m,int k)
{ int i,j;
for (i=m;i>=k;i--)
{ a[k]=i;
if (k>1)
comb(i-1,k-1);
else
{ for (j=a[0];j>0;j--)
printf(“%4d”,a[j]);
printf(“\n”);
}
}
}

void main()
{ a[0]=3;
comb(5,3);
}
3.回溯法
回溯法也称为试探法,该方法首先暂时放弃关于问题规模大小的限制,并将问题的候选解按某种顺序逐一枚举和检验。当发现当前候选解不可能是解时,就选择下一个候选解;倘若当前候选解除了还不满足问题规模要求外,满足所有其他要求时,继续扩大当前候选解的规模,并继续试探。如果当前候选解满足包括问题规模在内的所有要求时,该候选解就是问题的一个解。在回溯法中,放弃当前候选解,寻找下一个候选解的过程称为回溯。扩大当前候选解的规模,以继续试探的过程称为向前试探。

【问题】 组合问题
问题描述:找出从自然数1,2,…,n中任取r个数的所有组合。
采用回溯法找问题的解,将找到的组合以从小到大顺序存于a[0],a[1],…,a[r-1]中,组合的元素满足以下性质:
(1) a[i+1]>a,后一个数字比前一个大;
(2) a-i<=n-r+1。
按回溯法的思想,找解过程可以叙述如下:
首先放弃组合数个数为r的条件,候选组合从只有一个数字1开始。因该候选解满足除问题规模之外的全部条件,扩大其规模,并使其满足上述条件(1),候选组合改为1,2。继续这一过程,得到候选组合1,2,3。该候选解满足包括问题规模在内的全部条件,因而是一个解。在该解的基础上,选下一个候选解,因a[2]上的3调整为4,以及以后调整为5都满足问题的全部要求,得到解1,2,4和1,2,5。由于对5不能再作调整,就要从a[2]回溯到a[1],这时,a[1]=2,可以调整为3,并向前试探,得到解1,3,4。重复上述向前试探和向后回溯,直至要从a[0]再回溯时,说明已经找完问题的全部解。按上述思想写成程序如下:
【程序】
# define MAXN 100
int a[MAXN];
void comb(int m,int r)
{ int i,j;
i=0;
a=1;
do {
if (a-i<=m-r+1
{ if (i==r-1)
{ for (j=0;j<r;j++)
printf(“%4d”,a[j]);
printf(“\n”);
}
a++;
continue;
}
else
{ if (i==0)
return;
a[--i]++;
}
} while (1)
}

main()
{ comb(5,3);
}

4.贪婪法
贪婪法是一种不追求最优解,只希望得到较为满意解的方法。贪婪法一般可以快速得到满意的解,因为它省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪婪法常以当前情况为基础作最优选择,而不考虑各种可能的整体情况,所以贪婪法不要回溯。
例如平时购物找钱时,为使找回的零钱的硬币数最少,不考虑找零钱的所有各种发表方案,而是从最大面值的币种开始,按递减的顺序考虑各币种,先尽量用大面值的币种,当不足大面值币种的金额时才去考虑下一种较小面值的币种。这就是在使用贪婪法。这种方法在这里总是最优,是因为银行对其发行的硬币种类和硬币面值的巧妙安排。如只有面值分别为1、5和11单位的硬币,而希望找回总额为15单位的硬币。按贪婪算法,应找1个11单位面值的硬币和4个1单位面值的硬币,共找回5个硬币。但最优的解应是3个5单位面值的硬币。
【问题】 装箱问题
问题描述:装箱问题可简述如下:设有编号为0、1、…、n-1的n种物品,体积分别为v0、v1、…、vn-1。将这n种物品装到容量都为V的若干箱子里。约定这n种物品的体积均不超过V,即对于0≤i<n,有0<vi≤V。不同的装箱方案所需要的箱子数目可能不同。装箱问题要求使装尽这n种物品的箱子数要少。
若考察将n种物品的集合分划成n个或小于n个物品的所有子集,最优解就可以找到。但所有可能划分的总数太大。对适当大的n,找出所有可能的划分要花费的时间是无法承受的。为此,对装箱问题采用非常简单的近似算法,即贪婪法。该算法依次将物品放到它第一个能放进去的箱子中,该算法虽不能保证找到最优解,但还是能找到非常好的解。不失一般性,设n件物品的体积是按从大到小排好序的,即有v0≥v1≥…≥vn-1。如不满足上述要求,只要先对这n件物品按它们的体积从大到小排序,然后按排序结果对物品重新编号即可。装箱算法简单描述如下:
{ 输入箱子的容积;
输入物品种数n;
按体积从大到小顺序,输入各物品的体积;
预置已用箱子链为空;
预置已用箱子计数器box_count为0;
for (i=0;i<n;i++)
{ 从已用的第一只箱子开始顺序寻找能放入物品i 的箱子j;
if (已用箱子都不能再放物品i)
{ 另用一个箱子,并将物品i放入该箱子;
box_count++;
}
else
将物品i放入箱子j;
}
}
上述算法能求出需要的箱子数box_count,并能求出各箱子所装物品。下面的例子说明该算法不一定能找到最优解,设有6种物品,它们的体积分别为:60、45、35、20、20和20单位体积,箱子的容积为100个单位体积。按上述算法计算,需三只箱子,各箱子所装物品分别为:第一只箱子装物品1、3;第二只箱子装物品2、4、5;第三只箱子装物品6。而最优解为两只箱子,分别装物品1、4、5和2、3、6。
若每只箱子所装物品用链表来表示,链表首结点指针存于一个结构中,结构记录尚剩余的空间量和该箱子所装物品链表的首指针。另将全部箱子的信息也构成链表。以下是按以上算法编写的程序。
}

5.分治法
任何一个可以用计算机求解的问题所需的计算时间都与其规模N有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算;n=2时,只要作一次比较即可排好序;n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。
分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
如果原问题可分割成k个子问题(1<k≤n),且这些子问题都可解,并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
分治法所能解决的问题一般具有以下几个特征:
(1)该问题的规模缩小到一定的程度就可以容易地解决;
(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
(3)利用该问题分解出的子问题的解可以合并为该问题的解;
(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
上述的第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;第二条特征是应用分治法的前提,它也是大多数问题可以满足的,此特征反映了递归思想的应用;第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑贪心法或动态规划法。第四条特征涉及到分治法的效率,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。
分治法在每一层递归上都有三个步骤:
(1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
(2)解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;
(3)合并:将各个子问题的解合并为原问题的解。
6.动态规划法
经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题。简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加。
为了节约重复求相同子问题的时间,引入一个数组,不管它们是否对最终解有用,把所有子问题的解存于该数组中,这就是动态规划法所采用的基本方法。以下先用实例说明动态规划方法的使用。
【问题】 求两字符序列的最长公共字符子序列
问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj。例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列。
考虑最长公共子序列问题如何分解成子问题,设A=“a0,a1,…,am-1”,B=“b0,b1,…,bm-1”,并Z=“z0,z1,…,zk-1”为它们的最长公共子序列。不难证明有以下性质:
(1) 如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,…,zk-2”是“a0,a1,…,am-2”和“b0,b1,…,bn-2”的一个最长公共子序列;
(2) 如果am-1!=bn-1,则若zk-1!=am-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列;
(3) 如果am-1!=bn-1,则若zk-1!=bn-1,蕴涵“z0,z1,…,zk-1”是“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列。
这样,在找A和B的公共子序列时,如有am-1=bn-1,则进一步解决一个子问题,找“a0,a1,…,am-2”和“b0,b1,…,bm-2”的一个最长公共子序列;如果am-1!=bn-1,则要解决两个子问题,找出“a0,a1,…,am-2”和“b0,b1,…,bn-1”的一个最长公共子序列和找出“a0,a1,…,am-1”和“b0,b1,…,bn-2”的一个最长公共子序列,再取两者中较长者作为A和B的最长公共子序列。
代码如下:
# include <stdio.h>
# include <string.h>
# define N 100
char a[N],b[N],str[N];

int lcs_len(char *a, char *b, int c[ ][ N])
{ int m=strlen(a), n=strlen(b), i,j;
for (i=0;i<=m;i++) c[0]=0;
for (i=0;i<=n;i++) c[0]=0;
for (i=1;i<=m;i++)
for (j=1;j<=m;j++)
if (a[i-1]==b[j-1])
c[j]=c[i-1][j-1]+1;
else if (c[i-1][j]>=c[j-1])
c[j]=c[i-1][j];
else
c[j]=c[j-1];
return c[m][n];
}

char *buile_lcs(char s[ ],char *a, char *b)
{ int k, i=strlen(a), j=strlen(b);
k=lcs_len(a,b,c);
s[k]=’’;
while (k>0)
if (c[j]==c[i-1][j]) i--;
else if (c[j]==c[j-1]) j--;
else { s[--k]=a[i-1];
i--; j--;
}
return s;
}

void main()
{ printf (“Enter two string(<%d)!\n”,N);
scanf(“%s%s”,a,b);
printf(“LCS=%s\n”,build_lcs(str,a,b));
}
7.迭代法
迭代法是用于求方程或方程组近似根的一种常用的算法设计方法。设方程为f(x)=0,用某种数学方法导出等价的形式x=g(x),然后按以下步骤执行:
(1) 选一个方程的近似根,赋给变量x0;
(2) 将x0的值保存于变量x1,然后计算g(x1),并将结果存于变量x0;
(3) 当x0与x1的差的绝对值还小于指定的精度要求时,重复步骤(2)的计算。
若方程有根,并且用上述方法计算出来的近似根序列收敛,则按上述方法求得的x0就认为是方程的根。上述算法用C程序的形式表示为:
程序如下:
【算法】迭代法求方程组的根
{ for (i=0;i<n;i++)
x=初始近似根;
do {
for (i=0;i<n;i++)
y = x;
for (i=0;i<n;i++)
x = gi(X);
for (delta=0.0,i=0;i<n;i++)
if (fabs(y-x)>delta) delta=fabs(y-x); } while (delta>Epsilon);
for (i=0;i<n;i++)
printf(“变量x[%d]的近似根是 %f”,I,x);
printf(“\n”);
} 具体使用迭代法求根时应注意以下两种可能发生的情况:
(1)如果方程无解,算法求出的近似根序列就不会收敛,迭代过程会变成死循环,因此在使用迭代算法前应先考察方程是否有解,并在程序中对迭代的次数给予限制;
(2)方程虽然有解,但迭代公式选择不当,或迭代的初始近似根选择不合理,也会导致迭代失败。
8.穷举搜索法
穷举搜索法是对可能是解的众多候选解按某种顺序进行逐一枚举和检验,并从众找出那些符合要求的候选解作为问题的解。
【问题】 将A、B、C、D、E、F这六个变量排成如图所示的三角形,这六个变量分别取[1,6]上的整数,且均不相同。求使三角形三条边上的变量之和相等的全部解。如图就是一个解。
程序引入变量a、b、c、d、e、f,并让它们分别顺序取1至6的整数,在它们互不相同的条件下,测试由它们排成的如图所示的三角形三条边上的变量之和是否相等,如相等即为一种满足要求的排列,把它们输出。当这些变量取尽所有的组合后,程序就可得到全部可能的解。程序如下:
按穷举法编写的程序通常不能适应变化的情况。如问题改成有9个变量排成三角形,每条边有4个变量的情况,程序的循环重数就要相应改变。

❻ 绋嫔簭閲岀殑钬滈殢链衡濓纴鏄链夌壒娈婄殑绠楁硶锛岃缮鏄鐪熺殑闅忔満锛

浣犲ソ锛屾疮涓绋嫔簭閮芥湁锲哄畾镄勭畻娉曪纴闅忔満纭瀹炲瓨鍦锛屼絾鏄瑕佺湅杩欎釜绋嫔簭钖锷ㄧ殑鏄浠涔堢畻娉曪纴瀹冩槸鍙浠ユ带鍒惰繖涓绋嫔簭鏄钖︾湡镄勯殢链虹殑锛屼篃灏辨槸璇存牴鎹绋嫔簭锻樼殑镒忔効𨱒ヨ夊缑镄勚傛弧镒忚烽噰绾宠阿璋

❼ 简单算法的概念,并举例说明它在程序中的作用。

1 什么叫算法
算法(Algorithm)是解题的步骤,可以把算法定义成解一确定类问题的任意一种特殊的方法。在计算机科学中,算法要用计算机算法语言描述,算法代表用计算机解一类问题的精确、有效的方法。算法+数据结构=程序,求解一个给定的可计算或可解的问题,不同的人可以编写出不同的程序,来解决同一个问题,这里存在两个问题:一是与计算方法密切相关的算法问题;二是程序设计的技术问题。算法和程序之间存在密切的关系。
算法是一组有穷的规则,它们规定了解决某一特定类型问题的一系列运算,是对解题方案的准确与完整的描述。制定一个算法,一般要经过设计、确认、分析、编码、测试、调试、计时等阶段。
对算法的学习包括五个方面的内容:① 设计算法。算法设计工作是不可能完全自动化的,应学习了解已经被实践证明是有用的一些基本的算法设计方法,这些基本的设计方法不仅适用于计算机科学,而且适用于电气工程、运筹学等领域;② 表示算法。描述算法的方法有多种形式,例如自然语言和算法语言,各自有适用的环境和特点;③确认算法。算法确认的目的是使人们确信这一算法能够正确无误地工作,即该算法具有可计算性。正确的算法用计算机算法语言描述,构成计算机程序,计算机程序在计算机上运行,得到算法运算的结果;④ 分析算法。算法分析是对一个算法需要多少计算时间和存储空间作定量的分析。分析算法可以预测这一算法适合在什么样的环境中有效地运行,对解决同一问题的不同算法的有效性作出比较;⑤ 验证算法。用计算机语言描述的算法是否可计算、有效合理,须对程序进行测试,测试程序的工作由调试和作时空分布图组成。

2、算法的特性

算法的特性包括:① 确定性。算法的每一种运算必须有确定的意义,该种运算应执行何种动作应无二义性,目的明确;② 能行性。要求算法中有待实现的运算都是基本的,每种运算至少在原理上能由人用纸和笔在有限的时间内完成;③ 输入。一个算法有0个或多个输入,在算法运算开始之前给出算法所需数据的初值,这些输入取自特定的对象集合;④ 输出。作为算法运算的结果,一个算法产生一个或多个输出,输出是同输入有某种特定关系的量;⑤ 有穷性。一个算法总是在执行了有穷步的运算后终止,即该算法是可达的。
满足前四个特性的一组规则不能称为算法,只能称为计算过程,操作系统是计算过程的一个例子,操作系统用来管理计算机资源,控制作业的运行,没有作业运行时,计算过程并不停止,而是处于等待状态。

3、算法的描述

算法的描述方法可以归纳为以下几种:
(1) 自然语言;
(2) 图形,如N�S图、流程图,图的描述与算法语言的描述对应;
(3) 算法语言,即计算机语言、程序设计语言、伪代码;
(4) 形式语言,用数学的方法,可以避免自然语言的二义性。
用各种算法描述方法所描述的同一算法,该算法的功用是一样的,允许在算法的描述和实现方法上有所不同。
人们的生产活动和日常生活离不开算法,都在自觉不自觉地使用算法,例如人们到商店购买物品,会首先确定购买哪些物品,准备好所需的钱,然后确定到哪些商场选购、怎样去商场、行走的路线,若物品的质量好如何处理,对物品不满意又怎样处理,购买物品后做什么等。以上购物的算法是用自然语言描述的,也可以用其他描述方法描述该算法。

热点内容
我的世界如何强制获得服务器管理员权限 发布:2024-11-25 19:39:13 浏览:603
批量上传图片控件 发布:2024-11-25 19:27:12 浏览:765
黑马java就业班 发布:2024-11-25 19:10:54 浏览:714
我的世界国外小游戏服务器 发布:2024-11-25 18:52:12 浏览:646
传奇是要什么配置的手机 发布:2024-11-25 18:43:34 浏览:949
荣耀v6如何设置程序安装密码 发布:2024-11-25 18:43:25 浏览:556
C语言读盘 发布:2024-11-25 18:41:55 浏览:573
我的世界服务器被破坏了怎么恢复 发布:2024-11-25 18:27:57 浏览:330
日常电瓶叉车配置有哪些 发布:2024-11-25 18:21:17 浏览:362
java的二分查找 发布:2024-11-25 18:21:11 浏览:24