當前位置:首頁 » 操作系統 » 上述演算法是A

上述演算法是A

發布時間: 2022-04-28 18:17:48

⑴ 簡述演算法的各種表示形式

一、什麼是演算法

演算法是一系列解決問題的清晰指令,也就是說,能夠對一定規范的輸入,在有限時間內獲得所要求的輸出。演算法常常含有重復的步驟和一些比較或邏輯判斷。如果一個演算法有缺陷,或不適合於某個問題,執行這個演算法將不會解決這個問題。不同的演算法可能用不同的時間、空間或效率來完成同樣的任務。一個演算法的優劣可以用空間復雜度與時間復雜度來衡量。

演算法的時間復雜度是指演算法需要消耗的時間資源。一般來說,計算機演算法是問題規模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>

# define MAXN 1000

void pnext(int a[ ],int k)

{ int *b,m=a[0],i,j,r,carry;

b=(int * ) malloc(sizeof(int)* (m+1));

for ( i=1;i<=m;i++) b[i]=a[i];

for ( j=1;j<=k;j++)

{ for ( carry=0,i=1;i<=m;i++)

{ r=(i<a[0]?a[i]+b[i]:a[i])+carry;

a[i]=r%10;

carry=r/10;

}

if (carry) a[++m]=carry;

}

free(b);

a[0]=m;

}

void write(int *a,int k)

{ int i;

printf(「%4d!=」,k);

for (i=a[0];i>0;i--)

printf(「%d」,a[i]);

printf(「\n\n」);

}

void main()

{ int a[MAXN],n,k;

printf(「Enter the number n: 「);

scanf(「%d」,&n);

a[0]=1;

a[1]=1;

write(a,1);

for (k=2;k<=n;k++)

{ pnext(a,k);

write(a,k);

getchar();

}

}

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[i],後一個數字比前一個大;

(2) a[i]-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[i]=1;

do {

if (a[i]-i<=m-r+1

{ if (i==r-1)

{ for (j=0;j<r;j++)

printf(「%4d」,a[j]);

printf(「\n」);

}

a[i]++;

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。

若每隻箱子所裝物品用鏈表來表示,鏈表首結點指針存於一個結構中,結構記錄尚剩餘的空間量和該箱子所裝物品鏈表的首指針。另將全部箱子的信息也構成鏈表。以下是按以上演算法編寫的程序。

【程序】

# include <stdio.h>

# include <stdlib.h>

typedef struct ele

{ int vno;

struct ele *link;

} ELE;

typedef struct hnode

{ int remainder;

ELE *head;

Struct hnode *next;

} HNODE;

void main()

{ int n, i, box_count, box_volume, *a;

HNODE *box_h, *box_t, *j;

ELE *p, *q;

Printf(「輸入箱子容積\n」);

Scanf(「%d」,&box_volume);

Printf(「輸入物品種數\n」);

Scanf(「%d」,&n);

A=(int *)malloc(sizeof(int)*n);

Printf(「請按體積從大到小順序輸入各物品的體積:」);

For (i=0;i<n;i++) scanf(「%d」,a+i);

Box_h=box_t=NULL;

Box_count=0;

For (i=0;i<n;i++)

{ p=(ELE *)malloc(sizeof(ELE));

p->vno=i;

for (j=box_h;j!=NULL;j=j->next)

if (j->remainder>=a[i]) break;

if (j==NULL)

{ j=(HNODE *)malloc(sizeof(HNODE));

j->remainder=box_volume-a[i];

j->head=NULL;

if (box_h==NULL) box_h=box_t=j;

else box_t=boix_t->next=j;

j->next=NULL;

box_count++;

}

else j->remainder-=a[i];

for (q=j->next;q!=NULL&&q->link!=NULL;q=q->link);

if (q==NULL)

{ p->link=j->head;

j->head=p;

}

else

{ p->link=NULL;

q->link=p;

}

}

printf(「共使用了%d只箱子」,box_count);

printf(「各箱子裝物品情況如下:」);

for (j=box_h,i=1;j!=NULL;j=j->next,i++)

{ printf(「第%2d只箱子,還剩餘容積%4d,所裝物品有;\n」,I,j->remainder);

for (p=j->head;p!=NULL;p=p->link)

printf(「%4d」,p->vno+1);

printf(「\n」);

}

}

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[i][0]=0;

for (i=0;i<=n;i++) c[0][i]=0;

for (i=1;i<=m;i++)

for (j=1;j<=m;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];

}

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]=』\0』;

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;

}

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[i]=初始近似根;

do {

for (i=0;i<n;i++)

y[i] = x[i];

for (i=0;i<n;i++)

x[i] = gi(X);

for (delta=0.0,i=0;i<n;i++)

if (fabs(y[i]-x[i])>delta) delta=fabs(y[i]-x[i]); } while (delta>Epsilon);

for (i=0;i<n;i++)

printf(「變數x[%d]的近似根是 %f」,I,x[i]);

printf(「\n」);

} 具體使用迭代法求根時應注意以下兩種可能發生的情況:

(1)如果方程無解,演算法求出的近似根序列就不會收斂,迭代過程會變成死循環,因此在使用迭代演算法前應先考察方程是否有解,並在程序中對迭代的次數給予限制;

(2)方程雖然有解,但迭代公式選擇不當,或迭代的初始近似根選擇不合理,也會導致迭代失敗。

8.窮舉搜索法

窮舉搜索法是對可能是解的眾多候選解按某種順序進行逐一枚舉和檢驗,並從眾找出那些符合要求的候選解作為問題的解。

【問題】 將A、B、C、D、E、F這六個變數排成如圖所示的三角形,這六個變數分別取[1,6]上的整數,且均不相同。求使三角形三條邊上的變數之和相等的全部解。如圖就是一個解。

程序引入變數a、b、c、d、e、f,並讓它們分別順序取1至6的整數,在它們互不相同的條件下,測試由它們排成的如圖所示的三角形三條邊上的變數之和是否相等,如相等即為一種滿足要求的排列,把它們輸出。當這些變數取盡所有的組合後,程序就可得到全部可能的解。程序如下:

# include <stdio.h>

void main()

{ int a,b,c,d,e,f;

for (a=1;a<=6;a++) {

for (b=1;b<=6;b++) {

if (b==a) continue;

for (c=1;c<=6;c++) {

if (c==a)||(c==b) continue;

for (d=1;d<=6;d++) {

if (d==a)||(d==b)||(d==c) continue;

for (e=1;e<=6;e++) {

if (e==a)||(e==b)||(e==c)||(e==d) continue;

f = 21-(a+b+c+d+e);

if ((a+b+c==c+d+e))&&(a+b+c==e+f+a)) {

printf(「%6d,a);

printf(「%4d%4d」,b,f);

printf(「%2d%4d%4d」,c,d,e);

scanf(「%*c」);

}

}

}

}

}

}}

按窮舉法編寫的程序通常不能適應變化的情況。如問題改成有9個變數排成三角形,每條邊有4個變數的情況,程序的循環重數就要相應改變。

⑵ 下面關於演算法的描述正確的是a

由演算法的概念可知:
演算法不是一個問題的解題過程,演算法可以理解為有基本運算及規定的運算順序所構成的完整的解題步驟.
或者看成按照要求設計好的有限的確切的計算序列,並且這樣的步驟和序列可以解決一類問題,故A,B錯;
求解某一類問題的演算法不是唯一的,故C正確;
演算法的概念可知:演算法是有限步,結果明確性,D是不正確的.
故選C.

⑶ 計算長方體體積的演算法如下:

A解析演算法
所謂解析法(analysis algorithm)是指用解析的方法找出表示問題的前提條件與結果之間關系的數學表達式,並通過表達式的計算來實現問題求解。

⑷ VB問題 會考題目

給出了 計算公式,不屬於遞歸演算法。答案A

⑸ 數據結構的習題(C語言版)

第一個問題,分析下要求,可以知道要做的事情是合並兩個數組到一個數組里去,數組C的長度是AB之和。表C的第一個字元不是A的第一個字元就是B的第一個字元。因此接下來要做的事情就是做一個長度為AB之和的循環,每一次找出A或B中的最小元素,存到C裡面去,循環結束,C就自動有了。

第二個問題,有時間和空間的要求,不太容易,只有更好,沒有最好。不過提供一個思路。可以首先掃描整個數列,將奇數偶數的位置和個數標注出來,存在一個數列中。例如數列奇 奇 偶 奇 奇,可以得到奇數個數為4,位置為[0,1,3,4],偶數為1,位置為[2],因此要生成的數列中前4個必定為奇數,而題目中沒有對大小的要求,因此只用將偶數與最後面的奇數對換位置即可。對換的次數即為偶數的個數。

大概思路如此,不過有很多方法可以高效的存儲和計算,具體實現,希望你能親自琢磨下,還可以鞏固一下C技巧。
祝好,有問題可以探討。

⑹ 閱讀下列演算法,指出演算法A的功能和時間復雜度,其中h、g分別為單循環鏈表中兩個節點指針。

A的作用:將一個單循環鏈表變為兩個單循環鏈表。
如:a->b->c->d->e->f->g->a
A(c,f)得到:c->d->e->c; f->g->a->b->f;

⑺ A.《演算法與程序設計》模塊 VB基本數據類型屬於數值型的是。把這個答案告訴我

A.《演算法與程序設計》模塊
一、單項選擇題
1.C.③②④①
2.看不流程圖符號
3.D."123"

4.A.上述演算法是用自然語言描述的
5.C.Abs(-4.1)
二、多項選擇題(每小題2分,共4分)

1.A.Integer B.Single
2.下面關於演算法的認識,正確的是( )
A.演算法是解決問題的方法和步驟
B.演算法有一個或多個的輸出
C.演算法的每一個步驟必須要確切地定義

三、判斷題(每小題1分,共5分)

1. 錯
2.對
3.錯
4.對
5. 錯
四、操作題(每題12分,共36分)
1.
① 從鍵盤輸入圓的半徑R,輸出圓的周長L和面積S。

Dim R As Single

Dim L As Single

Dim S As Single

___R__=InputBox("輸入半徑R ")

L=2*3.14*R

S=3.14*R*R

Print "圓的周長L= ";L

Print "圓的面積S= ";S

② 計算旅客的行李費,收費標准為:20千克以下(包括20千克)不收費,超過20千克的部分每千克收20元。X表示行李重量,Y表示行李費。
Dim X As Single
Dim Y As Single
X=InputBox("輸入行李重量")
If ___X<=20_____ Then
Y=0
Else
Y=(x-20)*20
end if

⑻ 下列關於演算法的說法中,正確的是()A.演算法是某個問題的解決過程B.演算法可以無限不停地操作下去C.

由演算法的概念可知:
演算法是某個問題的解決方法,而不是某個問題的解決過程,故A不正確;
演算法是在有限個步驟內解決問題,不可以無限不停地操作下去,故B不正確;
演算法的每一步操作都是明確的,演算法執行後的結果是確定的,故C不正確;
解決某類問題的演算法可能有多個,演算法是不唯一的,故D正確.
故選D.

⑼ 下列演算法,指出演算法A的功能和時間復雜度,其中h、g分別為單循環鏈表中兩個節點指針。

估計你的代碼是這樣的吧:
void B(int *s, int *q)
{
int *p;
p = s;
while(p->next != q)
p = p->next;
p->next = s;
}

void A(int *h, int *g)
{
B(h, g);
B(g, h);
}
首先說下函數B的作用,函數B的作用是將單循環鏈表(也可以是單向鏈表,如果是單鏈表,那麼s節點一定要在q節點之前,題意中指的是單循環鏈表)中的q節點和s節點相連接(q->next = s),從而形成一個單循環鏈表。
函數A的作用是使單循環鏈表中的g的下一個節點為h而h的下一個節點為g(即g->next = h且h->next = g),也可以說是形成一個只有g和h節點的單循環鏈表。

如果g,h所在單循環鏈表節點數為n,則當q->next == s時,"B(h, g);"要執行最多次" p = p->next;"(n-2次),執行p->next = s;一次;B(g, h);只執行p->next = s;一次。所以時間復雜度肯定是線性階,即T(n) = O(n)。

⑽ 演算法:第一步.輸人a,b,c,d.第二步.m=a第三步,若b<m.則m=b.第四步.若c<m.則m=c.第五步.若d

逐步分析框圖中的各框語句的功能,
第三步條件結構是比較a,b的大小,
並將a,b中的較小值保存在變數m中,
第四步條件結構是比較a,c的大小,
並將a,c中的較小值保存在變數m中,
故變數m的值最終為a,b,c中的最小值.
由此程序的功能為求a,b,c三個數的最小數.
故選B

熱點內容
在資源管理器中文件與文件夾 發布:2024-10-04 19:32:17 瀏覽:970
微笑的編程 發布:2024-10-04 19:04:38 瀏覽:234
28歲學編程 發布:2024-10-04 18:56:24 瀏覽:187
c語言定義函數結構體 發布:2024-10-04 18:46:19 瀏覽:404
安卓抖音表情在哪裡下載 發布:2024-10-04 18:37:21 瀏覽:945
雙色球演算法必中 發布:2024-10-04 18:36:25 瀏覽:205
壓縮機濾網 發布:2024-10-04 18:27:13 瀏覽:893
解壓縮一幀圖像 發布:2024-10-04 18:17:00 瀏覽:309
存儲講解p 發布:2024-10-04 18:12:41 瀏覽:744
普聯監控管理系統的伺服器地址 發布:2024-10-04 17:46:38 瀏覽:602