演算法 演算法的藝術(三)

2021-09-06 10:41:52 字數 4884 閱讀 5191

列印魔方陣

乙個奇數階(設為n階)的方陣,將1、2、3……n2填入方陣中,使每行、每列資料之和都相等,這樣的方陣便是魔方陣。

例項解析:

填寫魔方陣有乙個固定的方法:

(1)1總是位於第一行的中間。

(3)若右上方超出**的右邊界,則數字填入到第一列,行數不變。圖16-1中的3和8都是這種情況。

若右上方超出上邊界,則數字填入最後一行,列數不變。圖16-1中2和9都是這種情況。

下面是程式**:

#define n 19

int main()

, i, j, k, n;

/*陣列元素全部初始化為0,表示沒有資料填入*/

scanf("%d",&n); //輸入方陣階數(奇數)

i = 0; //1的行數應該是0

j = n/2; //計算1應該在的列數

a[i][j] = 1; //將1填入表中

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

a[i][j] = k; //將k填入

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

getch();

return 0;

}

猜數遊戲

隨機生成乙個0~100之間的數,由使用者猜,允許猜5次,每次猜大了或猜小了,都要給出提示。最後,無論猜對或猜錯,都給出正確答案。

例項解析:

隨機數的生成可利用例項11所介紹的知識。使用者猜數可用迴圈,最多5次,若某次猜中則break。

#include #include #include int main()

if(i <= 5) //因break而退出

printf(「\n恭喜您,猜對了! 答案正是%d\n」, n);

else //迴圈自然退出

printf(「\n抱歉,沒猜對! 正確答案是%d\n」, n);

getch();

return 0;

}

二維陣列的排序輸出

有10名學生,每個學生考試三門功課:數學、英語、計算機,鍵盤輸入學號和成績(學號和分數都是整數),按總分高低排序輸出。

例項解析:

本題目需要完成輸入、排序和輸出。由於每個學生有5項資料:學號、三門成績、總分,儲存10個人的資料需要乙個二維陣列:

int  a[11][5];    //第0行閒置不用

設計思路:

陣列的第0列用來存學號,第1~3列存單科成績,第4列存總分。

所有資料從鍵盤輸入,用迴圈實現,迴圈的同時計算每個人的總分。

排序用選擇法,與一維陣列不同的是,這裡的排序如果需要交換資料,那麼交換的是兩行的資料,而不是僅交換總分。

下面是程式**:

# define number  10

int main()

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

}printf(" 學號 數學 英語 計算機 總分 名次\n");

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

for(j = 0; j <= 5; j++)

getch();

return 0;

}

尋找假幣

80枚硬幣中有一枚假幣,假幣比真幣稍輕,請用天平稱4次,將假幣找出。

天平兩邊都可以放硬幣

例項解析:

要用天平稱4次找出假幣,必須這樣稱:

(1) 將硬幣分成三組:27、27、26,將前兩組硬幣分放在天平兩側稱量,可以確定假幣在某一組,假幣範圍縮小到27(26)個硬幣中。

(2) 將假幣所在組再分三組9、9、9(或9、9、8),前兩組放天平上稱量,又可以確定假幣在哪一小組,假幣範圍縮小為9(8)個硬幣之中。

(3) 繼續分組3、3、3(或3、3、2),可確定假幣在3(2)個中。

(4) 繼續分組1、1、1(或1、1、0),便能找出假幣。

上面描述的是用天平找出假幣的方法,但計算機不是天平,要用計算機程式設計解這個題,就需要用程式來模擬天平稱量的過程,故必須先建立數學模型。

天平稱重,其實是比較兩邊硬幣的總重量是否相等。為了能計算總重量,我們定義乙個陣列,每個元素儲存乙個硬幣的重量,並使真幣的重量為1,假幣重量為0(只要比真幣輕即可),然後按照上面的方法分組4次,稱量4次。每次稱完,都用k記錄下假幣所在小組中第一枚硬幣的序號,以便下次分組從k開始。

下面為程式**:

#include "time.h"

#include "stdlib.h"

int main()

if(s1 > s2) //假幣在第2組

k += m;

if(s1 == s2) //假幣在第3組

k += 2*m;

m /= 3; //繼續分組,下次迴圈每組m/3個硬幣

}printf("假幣的序號是:%d\n", k);

getch();

return 0;

}

計算矩陣相乘

程式設計序計算矩陣相乘:  a3×4×b4×2= c3×2

例項解析:

每個矩陣可用乙個陣列表示,陣列c中每一項都是累加的結果,因此c陣列中的資料必須先全部初始化為0。

c陣列中的某一項c[i][j]的值由a的第i行和b的第j列相乘而得。即:c[i][j] = a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j] + a[i][3]*b[3][j],此式的計算可用迴圈實現:

for(k =0; k<=3; k++) 

c[i][j] += a[i][k] * b[k][j];

上面只是求得陣列c中的一項,利用迴圈可求出所有的資料。

程式**:

#define m 3

#define k 4

#define n 2

int main()

;   int b[k][n] = , c[m][n] = ;

int i, j, k;

clrscr();

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

printf(「\n」);

}getch();

return 0;

}

向排好序的陣列中插入資料

陣列中已按從小到大順序存有10個整數,鍵盤輸入乙個整數插入到陣列中,插入後的資料還是按順序排列的。

例項解析:

解法1:

要向排好序的資料中插入乙個資料x,必須首先確定x應該插入到陣列的何處,然後再行插入。

要確定x應插入到何處,需要將x依次與陣列中的每個元素進行比較,若x小於某元素,則該元素的位置便是x應該插入的位置。這個過程可用下面**實現。

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

if(x < a[i])

break;

迴圈結束後,i的值便是x插入後的序號,即a[i]應當儲存x。

但是,此時還不能將x存入a[i],因為這樣做就把a[i]原值覆蓋了。正確的做法是,先把a[i]後移,然後再存入x。但是,如果a[i]後移到a[i+1],就把a[i+1]覆蓋了,如何解決?

可以從陣列最後乙個資料開始向後移動,即先把最後乙個後移,再把倒數第二個資料後移……

可用下面**實現:

k = i;      //用k記錄下i的值,以便後面迴圈再用i作迴圈變數

for(i = 9; i >= k; i--)

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

完成這一步後,便可以把x插入到a[k]了:

a[k] = x;

下面是完整的程式**:

#include int main()

;   int x, i, k;

scanf(「%d」, &x);

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

if(x < a[i])

break;

k = i;

for(i = 9; i >= k; i--) /*自第k個資料之後的所有資料後移*/

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

a[k] = x; //將x插入

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

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

getch();

return 0;

}

解法2:

將陣列的元素從最後乙個開始依次與x比較,若陣列元素大於x,則後移,直到遇到乙個不大於x的元素或所有元素都比較完了為止。

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

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

當迴圈結束時,存在兩種情況:

(1)遇到乙個元素,使得a[i]不大於x,此時,x應插入到a[i+1]。

(2)所有元素都比較完了,使得x<0退出迴圈,x應插入到a[0],亦即a[i+1]。

兩種情況都可以用a[i+1] = x; 來完成插入。

解法二的主要**為:

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

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

a[i+1] = x;

本文出自 「成鵬致遠」 部落格,請務必保留此出處

演算法 演算法的藝術(三)

列印魔方陣 乙個奇數階 設為n階 的方陣,將1 2 3 n2填入方陣中,使每行 每列資料之和都相等,這樣的方陣便是魔方陣。例項解析 填寫魔方陣有乙個固定的方法 1 1總是位於第一行的中間。3 若右上方超出 的右邊界,則數字填入到第一列,行數不變。圖16 1中的3和8都是這種情況。若右上方超出上邊界,...

演算法 演算法的藝術

小續 最近很多人都在問我資料結構和演算法的相關問題,對於初學者,貌似聽到演算法,資料結構什麼的,都覺得是比較高深的東西,其實它們並沒有想象中的難,只是你還沒有乙個整體上的把握,還沒有習慣站在整體上去思考問題。演算法是靈魂,資料結構是包裝,語言只是工具,學什麼語言並不重要,重要的是思想。這也是如鵬的理...

演算法 演算法的藝術(五)

利用位運算求整數的原碼或補碼 利用位運算求任意整數的原碼或補碼。例項解析 整數在記憶體中本來就是用補碼存放的,若要求出補碼,只需求出記憶體中的每一位二進位制數即可。而原碼,若是負數,則需要將補碼減1然後取反 最高位不取反 程式 include stdio.h int main while k 1 k...