❶ 什麼是演算法
演算法(Algorithm)是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制。也就是說,能夠對一定規范的輸入,在有限時間內獲得所要求的輸出。如果一個演算法有缺陷,或不適合於某個問題,執行這個演算法將不會解決這個問題。不同的演算法可能用不同的時間、空間或效率來完成同樣的任務。一個演算法的優劣可以用空間復雜度與時間復雜度來衡量。一個演算法應該具有以下五個重要的特徵:演算法可以使用自然語言、偽代碼、流程圖等多種不同的方法來描述。1、有窮性(Finiteness)演算法的有窮性是指演算法必須能在執行有限個步驟之後終止2、確切性(Difiniteness)演算法的每一步驟必須有確切的定義;3、輸入項(Input)一個演算法有0個或多個輸入,以刻畫運算對象的初始情況,所謂0個輸入是指演算法本身定出了初始條件;4、輸出項(Output)一個演算法有一個或多個輸出,以反映對輸入數據加工後的結果。沒有輸出的演算法是毫無意義的;5、可行性(Effectiveness)演算法中執行的任何計算步都是可以被分解為基本的可執行的操作步,即每個計算步都可以在有限時間內完成。(也稱之為有效性)計算機科學家尼克勞斯-沃思曾著過一本著名的書《數據結構十演算法= 程序》,可見演算法在計算機科學界與計算機應用界的地位。編輯本段演算法的復雜度同一問題可用不同演算法解決,而一個演算法的質量優劣將影響到演算法乃至程序的效率。演算法分析的目的在於選擇合適演算法和改進演算法。一個演算法的評價主要從時間復雜度和空間復雜度來考慮。時間復雜度演算法的時間復雜度是指執行演算法所需要的時間。一般來說,計算機演算法是問題規模n 的函數f(n),演算法的時間復雜度也因此記做T(n)=Ο(f(n))因此,問題的規模n 越大,演算法執行的時間的增長率與f(n) 的增長率正相關,稱作漸進時間復雜度(Asymptotic Time Complexity)。空間復雜度演算法的空間復雜度是指演算法需要消耗的內存空間。其計算和表示方法與時間復雜度類似,一般都用復雜度的漸近性來表示。同時間復雜度相比,空間復雜度的分析要簡單得多。詳見網路詞條"演算法復雜度"編輯本段演算法設計與分析的基本方法1.遞推法遞推法是利用問題本身所具有的一種遞推關系求問題解的一種方法。它把問題分成若干步,找出相鄰幾步的關系,從而達到目的,此方法稱為遞推法。2.遞歸遞歸指的是一個過程:函數不斷引用自身,直到引用的對象已知3.窮舉搜索法窮舉搜索法是對可能是解的眾多候選解按某種順序進行逐一枚舉和檢驗,並從眾找出那些符合要求的候選解作為問題的解。4.貪婪法貪婪法是一種不追求最優解,只希望得到較為滿意解的方法。貪婪法一般可以快速得到滿意的解,因為它省去了為找最優解要窮盡所有可能而必須耗費的大量時間。貪婪法常以當前情況為基礎作最優選擇,而不考慮各種可能的整體情況,所以貪婪法不要回溯。5.分治法分治法是把一個復雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題……直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合並。6.動態規劃法動態規劃是一種在數學和計算機科學中使用的,用於求解包含重疊子問題的最優化問題的方法。其基本思想是,將原問題分解為相似的子問題,在求解的過程中通過子問題的解求出原問題的解。動態規劃的思想是多種演算法的基礎,被廣泛應用於計算機科學和工程領域。7.迭代法迭代法是數值分析中通過從一個初始估計出發尋找一系列近似解來解決問題(一般是解方程或者方程組)的過程,為實現這一過程所使用的方法統稱為迭代法。編輯本段演算法分類演算法可大致分為基本演算法、數據結構的演算法、數論與代數演算法、計算幾何的演算法、圖論的演算法、動態規劃以及數值分析、加密演算法、排序演算法、檢索演算法、隨機化演算法、並行演算法。演算法可以宏泛的分為三類:有限的,確定性演算法 這類演算法在有限的一段時間內終止。他們可能要花很長時間來執行指定的任務,但仍將在一定的時間內終止。這類演算法得出的結果常取決於輸入值。有限的,非確定演算法 這類演算法在有限的時間內終止。然而,對於一個(或一些)給定的數值,演算法的結果並不是唯一的或確定的。無限的演算法 是那些由於沒有定義終止定義條件,或定義的條件無法由輸入的數據滿足而不終止運行的演算法。通常,無限演算法的產生是由於未能確定的定義終止條件。編輯本段舉例經典的演算法有很多,如:"歐幾里德演算法,割圓術,秦九韶演算法"。編輯本段演算法經典專著目前市面上有許多論述演算法的書籍,其中最著名的便是《計算機程序設計藝術》(The Art Of Computer Programming) 以及《演算法導論》(Introction To Algorithms)。編輯本段演算法的歷史「演算法」即演演算法的大陸中文名稱出自《周髀算經》;而英文名稱Algorithm 來自於9世紀波斯數學家al-Khwarizmi,因為al-Khwarizmi在數學上提出了演算法這個概念。「演算法」原為"algorism",意思是阿拉伯數字的運演算法則,在18世紀演變為"algorithm"。歐幾里得演算法被人們認為是史上第一個演算法。 第一次編寫程序是Ada Byron於1842年為巴貝奇分析機編寫求解解伯努利方程的程序,因此Ada Byron被大多數人認為是世界上第一位程序員。因為查爾斯·巴貝奇(Charles Babbage)未能完成他的巴貝奇分析機,這個演算法未能在巴貝奇分析機上執行。 因為"well-defined procere"缺少數學上精確的定義,19世紀和20世紀早期的數學家、邏輯學家在定義演算法上出現了困難。20世紀的英國數學家圖靈提出了著名的圖靈論題,並提出一種假想的計算機的抽象模型,這個模型被稱為圖靈機。圖靈機的出現解決了演算法定義的難題,圖靈的思想對演算法的發展起到了重要作用的。求素數的埃拉托塞尼篩法和求方根的開方的方法公式(演算法不等於公式,公式卻是提供一種演算法)
❷ 演算法設計的過程一般是什麼樣子
您好,樓主
演算法設計就是把問題的解決步驟通過計算機編程語言來實現。
大概步驟如下:
1.分析問題:輸入什麼/輸出什麼/條件什麼/能用什麼方法
2.用流程圖畫出解決方案:決定程序的結構(有三大結構:順序結構、判斷結構、循環結構)
3.演算法設計:常見的演算法設計方法有:窮舉法/迭代法/遞推法/遞歸法/回溯法/貪婪法/分治法。
4.程序設計:這個就需要變成語言來實現的。
❸ 高二數學 演算法的概念 在線等!!!!!!!!!!!!!
演算法 參考出處:http://blog.csdn.net/ctu_85/archive/2008/05/11/2432736.aspx
一、什麼是演算法
演算法是一系列解決問題的清晰指令,也就是說,能夠對一定規范的輸入,在有限時間內獲得所要求的輸出。演算法常常含有重復的步驟和一些比較或邏輯判斷。如果一個演算法有缺陷,或不適合於某個問題,執行這個演算法將不會解決這個問題。不同的演算法可能用不同的時間、空間或效率來完成同樣的任務。一個演算法的優劣可以用空間復雜度與時間復雜度來衡量。
演算法的時間復雜度是指演算法需要消耗的時間資源。一般來說,計算機演算法是問題規模n 的函數f(n),演算法執行的時間的增長率與f(n) 的增長率正相關,稱作漸進時間復雜度(Asymptotic Time Complexity)。時間復雜度用「O(數量級)」來表示,稱為「階」。常見的時間復雜度有: O(1)常數階;O(log2n)對數階;O(n)線性階;O(n2)平方階。
演算法的空間復雜度是指演算法需要消耗的空間資源。其計算和表示方法與時間復雜度類似,一般都用復雜度的漸近性來表示。同時間復雜度相比,空間復雜度的分析要簡單得多。
[font class="Apple-style-span" style="font-weight: bold;" id="bks_etfhxykd"]演算法 Algorithm [/font]
演算法是在有限步驟內求解某一問題所使用的一組定義明確的規則。通俗點說,就是計算機解題的過程。在這個過程中,無論是形成解題思路還是編寫程序,都是在實施某種演算法。前者是推理實現的演算法,後者是操作實現的演算法。
一個演算法應該具有以下五個重要的特徵:
1、有窮性: 一個演算法必須保證執行有限步之後結束;
2、確切性: 演算法的每一步驟必須有確切的定義;
3、輸入:一個演算法有0個或多個輸入,以刻畫運算對象的初始情況,所謂0個輸入是指演算法本身定除了初始條件;
4、輸出:一個演算法有一個或多個輸出,以反映對輸入數據加工後的結果。沒有輸出的演算法是毫無意義的;
5、可行性: 演算法原則上能夠精確地運行,而且人們用筆和紙做有限次運算後即可完成。
演算法的設計要求
1)正確性(Correctness)
有4個層次:
A.程序不含語法錯誤;
B.程序對幾組輸入數據能夠得出滿足規格要求的結果;
C.程序對精心選擇的、典型的、苛刻的、帶有刁難性的幾組輸入數據能夠得出滿足規格要求的結果;
D.程序對一切合法的輸入數據都能產生滿足規格要求的結果。
2)可讀性(Readability)
演算法的第一目的是為了閱讀和交流;
可讀性有助於對演算法的理解;
可讀性有助於對演算法的調試和修改。
3)高效率與低存儲量
處理速度快;存儲容量小
時間和空間是矛盾的、實際問題的求解往往是求得時間和空間的統一、折中。
演算法的描述 演算法的描述方式(常用的)
演算法描述 自然語言
流程圖 特定的表示演算法的圖形符號
偽語言 包括程序設計語言的三大基本結構及自然語言的一種語言
類語言 類似高級語言的語言,例如,類PASCAL、類C語言。
演算法的評價 演算法評價的標准:時間復雜度和空間復雜度。
1)時間復雜度 指在計算機上運行該演算法所花費的時間。用「O(數量級)」來表示,稱為「階」。
常見的時間復雜度有: O(1)常數階;O(logn)對數階;O(n)線性階;O(n^2)平方階
2)空間復雜度 指演算法在計算機上運行所佔用的存儲空間。度量同時間復雜度。
時間復雜度舉例
(a) X:=X+1 ; O(1)
(b) FOR I:=1 TO n DO
X:= X+1; O(n)
(c) FOR I:= 1 TO n DO
FOR J:= 1 TO n DO
X:= X+1; O(n^2)
「演算法」一詞最早來自公元 9世紀 波斯數學家比阿勒·霍瓦里松的一本影響深遠的著作《代數對話錄》。20世紀的 英國 數學家 圖靈 提出了著名的圖靈論點,並抽象出了一台機器,這台機器被我們稱之為 圖靈機 。圖靈的思想對演算法的發展起到了重要的作用。
演算法是 計算機 處理信息的本質,因為 計算機程序 本質上是一個演算法,告訴計算機確切的步驟來執行一個指定的任務,如計算職工的薪水或列印學生的成績單。 一般地,當演算法在處理信息時,數據會從輸入設備讀取,寫入輸出設備,可能保存起來以供以後使用。
這是演算法的一個簡單的例子。
我們有一串隨機數列。我們的目的是找到這個數列中最大的數。如果將數列中的每一個數字看成是一顆豆子的大小 可以將下面的演算法形象地稱為「撿豆子」:
首先將第一顆豆子(數列中的第一個數字)放入口袋中。
從第二顆豆子開始檢查,直到最後一顆豆子。如果正在檢查的豆子比口袋中的還大,則將它撿起放入口袋中,同時丟掉原先的豆子。 最後口袋中的豆子就是所有的豆子中最大的一顆。
下面是一個形式演算法,用近似於 編程語言 的 偽代碼 表示
給定:一個數列「list",以及數列的長度"length(list)" largest = list[1] for counter = 2 to length(list): if list[counter] > largest: largest = list[counter] print largest
符號說明:
= 用於表示賦值。即:右邊的值被賦予給左邊的變數。
List[counter] 用於表示數列中的第 counter 項。例如:如果 counter 的值是5,那麼 List[counter] 表示數列中的第5項。
<= 用於表示「小於或等於」。
二、演算法設計的方法
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.什麼是演算法
從字面上來說,演算法也就是用於計算的方法。是用來解決某些問題的方法。通過這個方法,可以達到想要的計算結果。它就像我們小時候學些的一些數學公式和解題步驟。
演算法,一般有5個特徵:
有窮性:
演算法的執行步驟、時間、都是有限的。不會無休止的一直執行下去。
確切性:
演算法的每一步都必須有明確的定義和描述。
輸入:
一個演算法應該有相應的輸入條件,就像我們小時候做的應用題,已知什麼什麼。來求某個結果,已知部分便是輸入條件。
輸出:
演算法必須有明確的結果輸出。沒有結果,那這個演算法是沒有任何意義的。
可行性:
演算法的步驟必須是可行的,無法執行的則沒有意義,也解決不了任何問題
2.演算法的分類
按照演算法的應用來分:演算法可以分為基本演算法、幾何演算法、加密/解密演算法、查找演算法、圖標數據分析演算法等。
按照演算法的思路來分:演算法可以分為遞推演算法、遞歸演算法、窮舉演算法、分治演算法等。
下面,我們就來講我們的重點之一:也就是演算法思想:
3.常用演算法思想
窮舉演算法思想;
遞推演算法思想;
遞歸演算法思想;
分治演算法思想;
概率演算法思想;
❺ hadoop中mapper用時間間隔做為key怎麼寫
從Map到Rece
MapRece其實是分治演算法的一種實現,其處理過程亦和用管道命令來處理十分相似,一些簡單的文本字元的處理甚至也可以使用Unix的管道命令來替代,從處理流程的角度來看大概如下:
cat input | grep | sort | uniq -c | cat > output # Input -> Map -> Shuffle & Sort -> Rece -> Output
簡單的流程圖如下:
對於Shuffle,簡單地說就是將Map的輸出通過一定的演算法劃分到合適的Recer中進行處理。Sort當然就是對中間的結果進行按key排序,因為Recer的輸入是嚴格要求按key排序的。
Input->Map->Shuffle&Sort->Rece->Output只是從宏觀的角度對MapRece的簡單描述,實際在MapRece的框架中,即從編程的角度來看,其處理流程是Input->Map->Sort->Combine->Partition->Rece->Output。用之前的對溫度進行統計的例子來講述這些過程。
Input Phase
輸入的數據需要以一定的格式傳遞給Mapper的,格式有多種,如TextInputFormat、DBInputFormat、SequenceFileInput等等,可以使用JobConf.setInputFormat來設置,這個過程還應該包括對輸入的數據進行任務粒度劃分(split)然後再傳遞給Mapper。在溫度的例子中,由於處理的都是文本數據,輸入的格式使用默認的TextInputFormat即可。
Map Phase
對輸入的key、value對進行處理,輸出的是key、value的集合,即map (k1, v1) -> list(k2, v2),使用JobConf.setMapperClass設置自己的Mapper。在例子中,將(行號、溫度的文本數據)作為key/value輸入,經過處理後,從溫度的文件數據中提取出日期中的年份和該日的溫度數據,形成新的key/value對,最後以list(年, 溫度)的結果輸出,如[(1950, 10), (1960, 40), (1960, 5)]。
Sort Phase
對Mapper輸出的數據進行排序,可以通過JobConf.setOutputKeyComparatorClass來設置自己的排序規則。在例子中,經過排序之後,輸出的list集合是按年份進行排序的list(年, 溫度),如[(1950, 10), (1950, 5), (1960, 40)]。
Combine Phase
這個階段是將中間結果中有相同的key的<key, value>對合並成一對,Combine的過程與Rece很相似,使用的甚至是Rece的介面。通過Combine能夠減少<key, value>的集合數量,從而減少網路流量。Combine只是一個可選的優化過程,並且無論Combine執行多少次(>=0),都會使Recer產生相同的輸出,使用JobConf.setCombinerClass來設置自定義的Combine Class。在例子中,假如map1產生出的結果為[(1950, 0), (1950, 20), (1950, 10)],在map2產生出的結果為[(1950, 15), (1950, 25)],這兩組數據作為Recer的輸入並經過Recer處理後的年最高溫度結果為(1950, 25),然而當在Mapper之後加了Combine(Combine先過濾出最高溫度),則map1的輸出是[(1950, 20)]和map2的輸出是[(1950, 25)],雖然其他的三組數據被拋棄了,但是對於Recer的輸出而言,處理後的年最高溫度依然是(1950, 25)。
Partition Phase
把Mapper任務輸出的中間結果按key的范圍劃分成R份(R是預先定義的Rece任務的個數),默認的劃分演算法是」(key.hashCode() & Integer.MAX_VALUE) % numPartitions」,這樣保證了某一范圍的key一定是由某個Recer來處理,簡化了Recer的處理流程,使用JobConf.setPartitionClass來設置自定義的Partition Class。在例子中,默認就自然是對年份進行取模了。
Rece Phase
Recer獲取Mapper輸出的中間結果,作為輸入對某一key范圍區間進行處理,使用JobConf.setRecerClass來設置。在例子中,與Combine Phase中的處理是一樣的,把各個Mapper傳遞過來的數據計算年最高溫度。
Output Phase
Recer的輸出格式和Mapper的輸入格式是相對應的,當然Recer的輸出還可以作為另一個Mapper的輸入繼續進行處理。
❻ 學習編程的基礎知識,如何做
編程的基礎知識包括:
小學、初中、高中基礎課程,大學計算機科學專業所有基礎課、專業基礎課和專業課(雜課不用學)。
如果一般摟一下基礎,找些快速入門的書比劃比劃,也能編。但是要想作為職業,繞不開上面那些知識,每門課涉及到的知識在實際工作中只要遇到,都是邁不過去的坎。
❼ ns結構流程圖是什麼
NS圖是用於取代傳統流程圖的一種描述方式。 以 SP方法為基礎,NS圖僅含有下圖 的5種基本成分,它們分別表示SP方法的幾種標准控制結構。
NS圖的優點:
首先,它強制設計人員按SP方法進行思考並描述他的設計方案,因為除了表示幾種標准結構的符號之處,它不再提供其他描述手段,這就有效地保證了設計的質量,從而也保證了程序的質量;第二,NS圖形象直觀,具有良好的可見度。例如循環的范圍、條件語句的范圍都是一目瞭然的,所以容易理解設計意圖,為編程、復查、選擇測試用例、維護都帶來了方便;第三,NS圖簡單、易學易用,可用於軟體教育和其他方面。
NS圖的缺點:
手工修改比較麻煩,這是有些人不用它的主要原因。
❽ pascal基礎知識
一、演算法的基礎知識
1.用計算機解決問題的步驟:
① 分析問題
② 演算法設計
③ 描述演算法
④ 編程實現
從上面的求解問題過程可以看出,關鍵在於前三步的解決:第一步就是解決模型的數據結構,第二步是解決問題的演算法,第三步是形式化地描寫演算法。
2.演算法的定義:
演算法是一組有窮的規則,它們規定了解決某一特定類型問題的一系列運算。演算法可以理解為:程序(數據處理)+ 數據結構(數據組織)。
3.演算法的性質:
① 有限性
② 確定性
③ 輸入輸出(可以沒有輸入,但一定有輸出)
④ 可行性
常見的演算法有:窮舉法、迭代法、遞推法、遞歸法、回溯法、深度及廣度搜索法、動態規劃、構造法等等。
2.N-S圖:
1973年,美國學者I.Nassi和B.Shneiderman提出了一種用圖形表示演算法的方法,稱為N-S流程圖。N-S圖包括順序、選擇和循環三種基本結構。
3.程序設計語言:
計算機中的語言分為低級語言和高級語言,而低級語言又分為機器語言和匯編語言。
機器語言是一種CPU的指令系統,它是CPU可以識別的一系列有0和1這種二進制代碼組成的指令。它依賴於機器,不同類型的計算機有不同的機器語言,機器語言的程序有許多機器指令組成,每條指令由操作碼和地址碼組成,數據和指令都放在不同的地址單元中。
匯編語言它是一種符號語言,為了克服機器語言固有的缺陷,20世紀50年代中期出現,將難以記憶和辨別的機器語言操作碼用有意義的英文單詞作為「助記符」來代替0、1進行編程。
高級語言,不再面向機器,而是接近人類的自然語言。常見的還有C/C++,Pascal,Basic,java等。
數據類型、常量、變數及說明方法
數據類型確定了該類型數據項的表示、取值范圍以及所能參與的運算。在pascal語言中,無論常量還是變數都必須屬於一個確定的數據類型。
Pascal 提供了豐富的數據類型,可以分為三大類:
① 簡單類型:分為標准類型(整型、實型、字元型和布爾型)和自定義類型(枚舉型和子界型)
② 構造類型:分為數組類型、集合類型、記錄類型和文件類型
③ 指針類型
這些數據類型中除了指針類型是動態數據類型外,其他的都是靜態數據類型。另外,我們把整型、字元型、布爾型、枚舉型和子界型稱為順序類型。
另:數據結構
-棧 隊列
– 並查集
– 堆
– 字母樹 線段樹 平衡樹 動態樹
– 塊狀鏈表
– 後綴數組
– ……
棧
– 先進後出
* 隊列
– 先進先出
* 常見的應用有哪些?
– 表達式求值
– 搜索
* 深搜
* 廣搜
– 優化
* 集合用代表元表示
– representative?Getfather(x)
* 初始的時候,所有元素各自成為一個集合
– for i?1 to N
* father[i]?i
* 判斷是否在同一集合
– 代表元是否相同
* return Getfather(x)=Getfather(y)
* 合並兩個集合
– 將其中一集合的代表元指向另一集合代表元
* father[Getfather(x)]?y
並查集
* 如何尋找代表元?
– Getfather(x)
* if father[x]=x
– return x
* return Getfather(father[x])
* 如何優化?
– 路徑壓縮
* Getfather(x)
– if father[x]=x
>>return x
– father[x]?Getfather(father[x])
– return father[x]
* 用途
– 用於尋找最值
* 大根堆、小根堆
* 小根堆性質
– 是一棵完全二叉樹
* i的父親是誰?
– idiv 2
* i的左右兒子是誰?
– 2i和2i+1
– 樹上的每棵子樹,兒子的值不小於根
堆排序
– 建堆
– 取出根
– 刪除根
– 反復取、刪的過程
時間效率
– O(Nlog N)
塊狀數組
* 增加一下題目內容
– 詢問區間最大值
– 詢問區間和
– 詢問區間內的和最大連續串
– 可以修改一個數
– 可以將一串連續的數變為一個值
– 可以將一串連續的數旋轉一下
* 塊狀數組?塊狀鏈表
– 可以將一串連續的數翻轉一下
可能有些難
❾ 怎樣寫流程圖才能使raptor隨機產生一個1到100的整數
import java.util.Random;
/**
*定義一個具有10個整形元素的數組,隨機生成1——100之間的整數初始化數組元
*素:(List實現)
*(1)使用冒泡演算法對數組元素進行排序,輸出結果。
*(2)除了使用冒泡排序演算法之外,請再給出至少3中不同的排序演算法。
*/
public class paixu{
public static void main(String[]args){
int[]arr=new int[10];
Random r=new Random();
for(int i=0;i<10;++i){
arr<i>=r.nextInt(100)+1;
System.out.print(arr<i>+"");
}
System.out.println("");
int temp;
int len=arr.length;
for(int i=len-1;i>=1;i--){
for(int j=0;j<i;j++){
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for(int i=0;i<10;i++){
System.out.print(arr<i>+"");
}
}
}
鏈表法
package com.abc;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
*定義一個具有10個整形元素的數組,隨機生成1——100之間的整數初始化數組元
*素:(List實現)
*(1)使用冒泡演算法對數組元素進行排序,輸出結果。
*(2)除了使用冒泡排序演算法之外,請再給出至少3中不同的排序演算法。
*/
public class paixu{
public static void main(String[]args){
List<Integer>arr=new ArrayList<Integer>();
Random r=new Random();
for(int i=0;i<10;++i){
arr.add(r.nextInt(100)+1);
}
for(int i=0;i<10;i++){
System.out.print(arr.get(i)+"");
}
System.out.println("");
int temp;
int temp1;
int len=arr.size();
for(int i=len-1;i>=1;i--){
for(int j=0;j<i;j++){
if((int)(arr.get(j))>(int)(arr.get(j+1)))
{
temp=arr.get(j);
temp1=arr.get(j+1);
arr.set(j,temp1);
arr.set(j+1,temp);
}
}
}
for(int i=0;i<10;i++){
System.out.print(arr.get(i)+"-->");
}
}}
(9)分治演算法流程圖擴展閱讀:
特徵
使用DllImport屬性調用Windows API
通過在「文件」菜單上單擊「新建」,然後單擊「項目」,打開一個新的「Windows應用程序」項目。出現「新建項目」對話框。
從Visual Basic項目模板的列表中選擇「Windows應用程序」。將顯示新項目。
將一個名為Button2的按鈕添加到啟動窗體上。
雙擊Button2打開窗體的代碼視圖。
要簡化對DllImport的訪問,請向啟動窗口類的代碼頂部添加一條Imports語句:
Visual Basic復制代碼
Imports System.Runtime.InteropServices
在End Class語句之前為窗體聲明一個空函數,並將函數命名為MoveFile。
將Public和Shared修飾符應用到函數聲明中,並基於Windows API函數使用的參數來設置MoveFile的參數:
Visual Basic復制代碼
Public Shared Function MoveFile(_
ByVal src As String,_
ByVal dst As String)_
As Boolean
'Leave the body of the function empty.
End Function
函數可以有任意一個有效的過程名;DllImport屬性指定DLL中的名稱。它還為參數和返回值處理互操作封送處理,因此可以選擇與API使用的數據類型相似的Visual Studio數據類型。
將DllImport屬性應用到空函數中。
第一個參數是包含要調用的函數的DLL的名稱和位置。不必為位於Windows系統目錄下的文件指定路徑。
第二個參數是一個命名參數,指定Windows API中的函數名稱。在本示例中,DllImport屬性強制將MoveFile調用轉發給KERNEL32.DLL中的MoveFileW。MoveFileW方法將文件從路徑src復制到路徑dst。
❿ 什麼叫演算法演算法有哪幾種表示方法
演算法(Algorithm)是指解題方案的准確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制。計算機科學家往往將「演算法」一詞的含義限定為此類「符號演算法」。「演算法」概念的初步定義:一個演算法是解決一個問題的進程。而並不需要每次都發明一個解決方案。
已知的演算法有很多,例如「分治法」、「枚舉測試法」、「貪心演算法」、「隨機演算法」等。
(10)分治演算法流程圖擴展閱讀
演算法中的「分治法」
「分治法」是把一個復雜的問題拆分成兩個較為簡單的子問題,進而兩個子問題又可以分別拆分成另外兩個更簡單的子問題,以此類推。問題不斷被層層拆解。然後,子問題的解被逐層整合,構成了原問題的解。
高德納曾用過一個郵局分發信件的例子對「分治法」進行了解釋:信件根據不同城市區域被分進不同的袋子里;每個郵遞員負責投遞一個區域的信件,對應每棟樓,將自己負責的信件分裝進更小的袋子;每個大樓管理員再將小袋子里的信件分發給對應的公寓。