久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

立即注冊 登錄
返回首頁

uid:150126的個人空間

日志

C語言經(jīng)典算法大全

已有 2287 次閱讀2016-12-21 14:43

C語言經(jīng)典算法大全

Ø  老掉牙

河內(nèi)塔

費式數(shù)列

巴斯卡三角形

三色棋

老鼠走迷官(一)

老鼠走迷官(二)

騎士走棋盤

八個皇后

八枚銀幣

生命游戲

字串核對

雙色、三色河內(nèi)塔

背包問題(Knapsack Problem

Ø  數(shù)、運算

蒙地卡羅法求 PI                                                                       

Eratosthenes篩選求質(zhì)數(shù)

超長整數(shù)運算(大數(shù)運算)

PI

最大公因數(shù)、最小公倍數(shù)、因式分解

完美數(shù)

阿姆斯壯數(shù)

最大訪客數(shù)

中序式轉(zhuǎn)后序式(前序式)

后序式的運算

Ø  關(guān)于賭博

洗撲克牌(亂數(shù)排列)

Craps賭博游戲

約瑟夫問題(Josephus Problem

Ø  集合問題

排列組合

格雷碼(Gray Code

產(chǎn)生可能的集合

m元素集合的n個元素子集

數(shù)字拆解

Ø  排序

得分排行

選擇、插入、氣泡排序

Shell 排序法 - 改良的插入排序

Shaker 排序法 - 改良的氣泡排序

Heap 排序法 - 改良的選擇排序

快速排序法(一)

快速排序法(二)

快速排序法(三)

合并排序法

基數(shù)排序法

Ø  搜尋

循序搜尋法(使用衛(wèi)兵)

二分搜尋法(搜尋原則的代表)

插補搜尋法

費氏搜尋法

Ø  矩陣

稀疏矩陣

多維矩陣轉(zhuǎn)一維矩陣

上三角、下三角、對稱矩陣

奇數(shù)魔方陣

4N 魔方陣

2(2N+1) 魔方陣

 

 

 

 

 

 

 

 

 

 

 

1.河內(nèi)之塔

說明河內(nèi)之塔(Towers of Hanoi)是法國人M.Claus(Lucas)1883年從泰國帶至法國的,河內(nèi)為越戰(zhàn)時北越的首都,即現(xiàn)在的胡志明市;1883年法國數(shù)學(xué)家 Edouard Lucas曾提及這個故事,據(jù)說創(chuàng)世紀時Benares有一座波羅教塔,是由三支鉆石棒(Pag)所支撐,開始時神在第一根棒上放置64個由上至下依由小至大排列的金盤(Disc),并命令僧侶將所有的金盤從第一根石棒移至第三根石棒,且搬運過程中遵守大盤子在小盤子之下的原則,若每日僅搬一個盤子,則當盤子全數(shù)搬運完畢之時,此塔將毀損,而也就是世界末日來臨之時。

解法如果柱子標為ABC,要由A搬至C,在只有一個盤子時,就將它直接搬至C,當有兩個盤子,就將B當作輔助柱。如果盤數(shù)超過2個,將第三個以下的盤子遮起來,就很簡單了,每次處理兩個盤子,也就是:A->BA ->CB->C這三個步驟,而被遮住的部份,其實就是進入程式的遞回處理。事實上,若有n個盤子,則移動完畢所需之次數(shù)為2^n - 1,所以當盤數(shù)為64時,則所需次數(shù)為:264- 1 = 184467440737095516155.05390248594782e+16年,也就是約5000世紀,如果對這數(shù)字沒什幺概念,就假設(shè)每秒鐘搬一個盤子好了,也要約5850億年左右。

#include <stdio.h>

void hanoi(int n, char A, char B, char C) {

    if(n == 1) {

        printf("Move sheet %d from %c to %c\n", n, A, C);

    }

    else {

        hanoi(n-1, A, C, B);

        printf("Move sheet %d from %c to %c\n", n, A, C);

        hanoi(n-1, B, A, C);

    }

}

 

int main() {

    int n;

    printf("請輸入盤數(shù)");

    scanf("%d", &n);

    hanoi(n, 'A', 'B', 'C');

    return 0;

}

 

 


2.Algorithm Gossip: 費式數(shù)列

說明

Fibonacci1200年代的歐洲數(shù)學(xué)家,在他的著作中曾經(jīng)提到:「若有一只免子每個月生一只小免子,一個月后小免子也開始生產(chǎn)。起初只有一只免子,一個月后就有兩只免子,二個月后有三只免子,三個月后有五只免子(小免子投入生產(chǎn))......

如果不太理解這個例子的話,舉個圖就知道了,注意新生的小免子需一個月成長期才會投入生產(chǎn),類似的道理也可以用于植物的生長,這就是Fibonacci數(shù)列,一般習(xí)慣稱之為費氏數(shù)列,例如以下: 11 23581321345589......

解法

依說明,我們可以將費氏數(shù)列定義為以下:

fn = fn-1 + fn-2    if n > 1

fn = n       if n = 0, 1

#include <stdio.h>

#include <stdlib.h>

 

#define N 20

 

int main(void) {

int Fib[N] = {0};

int i;

 

Fib[0] = 0;

Fib[1] = 1;

 

for(i = 2; i < N; i++)

Fib[i] = Fib[i-1] + Fib[i-2];

 

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

printf("%d ", Fib[i]);

printf("\n");

return 0;

}

 

 

 

 

3. 巴斯卡三角形

#include <stdio.h>

#define N 12

long combi(int n, int r){

    int i;

    long p = 1;

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

        p = p * (n-i+1) / i;

    return p;

}

void paint() {

    int n, r, t;

    for(n = 0; n <= N; n++) {

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

            int i;/* 排版設(shè)定開始 */

            if(r == 0) { 

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

                    printf("   ");

            }else {

                printf("   ");

            } /* 排版設(shè)定結(jié)束 */

            printf("%3d", combi(n, r));

        }

        printf("\n");

    }

}


4.Algorithm Gossip: 三色棋

說明

三色旗的問題最早由E.W.Dijkstra所提出他所使用的用語為Dutch Nation Flag(Dijkstra為荷蘭人)而多數(shù)的作者則使用Three-Color Flag來稱之。

 

假設(shè)有一條繩子,上面有紅、白、藍三種顏色的旗子,起初繩子上的旗子顏色并沒有順序,您希望將之分類,并排列為藍、白、紅的順序,要如何移動次數(shù)才會最少,注意您只能在繩子上進行這個動作,而且一次只能調(diào)換兩個旗子。

解法

在一條繩子上移動,在程式中也就意味只能使用一個陣列,而不使用其它的陣列來作輔助,問題的解法很簡單,您可以自己想像一下在移動旗子,從繩子開頭進行,遇到藍色往前移,遇到白色留在中間,遇到紅色往后移,如下所示:

只是要讓移動次數(shù)最少的話,就要有些技巧:

如果圖中W所在的位置為白色,則W+1,表示未處理的部份移至至白色群組。

如果W部份為藍色,則BW的元素對調(diào),而BW必須各+1,表示兩個群組都多了一個元素。

如果W所在的位置是紅色,則將WR交換,但R要減1,表示未處理的部份減1

 

注意BWR并不是三色旗的個數(shù),它們只是一個移動的指標;什幺時候移動結(jié)束呢?一開始時未處理的R指標會是等于旗子的總數(shù),當R的索引數(shù)減至少于W的索引數(shù)時,表示接下來的旗子就都是紅色了,此時就可以結(jié)束移動,如下所示:

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

#define BLUE 'b'

#define WHITE 'w'

#define RED 'r'

 

#define SWAP(x, y) { char temp; \

                     temp = color[x]; \

                     color[x] = color[y]; \

                     color[y] = temp; }

 

int main() {

    char color[] = {'r', 'w', 'b', 'w', 'w',

                    'b', 'r', 'b', 'w', 'r', '\0'};

 

    int wFlag = 0;

    int bFlag = 0;

    int rFlag = strlen(color) - 1;

    int i;

 

    for(i = 0; i < strlen(color); i++)

        printf("%c ", color[i]);

    printf("\n");

 

    while(wFlag <= rFlag) {

        if(color[wFlag] == WHITE)

            wFlag++;

        else if(color[wFlag] == BLUE) {

            SWAP(bFlag, wFlag);

            bFlag++; wFlag++;

        }

        else {

            while(wFlag < rFlag && color[rFlag] == RED)

              rFlag--;

            SWAP(rFlag, wFlag);

            rFlag--;

        }

    }

 

    for(i = 0; i < strlen(color); i++)

        printf("%c ", color[i]);

    printf("\n");

 

    return 0;

}

 

 

 

 


5.Algorithm Gossip: 老鼠走迷官

說明老鼠走迷宮是遞回求解的基本題型,我們在二維陣列中使用2表示迷宮墻壁,使用1來表示老鼠的行走路徑,試以程式求出由入口至出口的路徑。

解法老鼠的走法有上、左、下、右四個方向,在每前進一格之后就選一個方向前進,無法前進時退回選擇下一個可前進方向,如此在陣列中依序測試四個方向,直到走到出口為止,這是遞回的基本題,請直接看程式應(yīng)就可以理解。

#include <stdio.h>

#include <stdlib.h>

 

int visit(int, int);

 

int maze[7][7] = {{2, 2, 2, 2, 2, 2, 2},

                  {2, 0, 0, 0, 0, 0, 2},

                  {2, 0, 2, 0, 2, 0, 2},

                  {2, 0, 0, 2, 0, 2, 2},

                  {2, 2, 0, 2, 0, 2, 2},

                  {2, 0, 0, 0, 0, 0, 2},

                  {2, 2, 2, 2, 2, 2, 2}};

 

int startI = 1, startJ = 1;  // 入口

int endI = 5, endJ = 5;  // 出口

int success = 0;

 

int main(void) {

    int i, j;

 

    printf("顯示迷宮\n");

    for(i = 0; i < 7; i++) {

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

            if(maze[i][j] == 2)

                printf("█");

            else

                printf("  ");

        printf("\n");

    }

 

    if(visit(startI, startJ) == 0)

        printf("\n沒有找到出口\n");

    else {

        printf("\n顯示路徑\n");

        for(i = 0; i < 7; i++) {

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

                if(maze[i][j] == 2)

                    printf("█");

                else if(maze[i][j] == 1)

                    printf("◇");

                else

                    printf("  ");

            }

            printf("\n");

        }

    }

 

    return 0;

}

 

int visit(int i, int j) {

    maze[i][j] = 1;

 

    if(i == endI && j == endJ)

        success = 1;

 

    if(success != 1 && maze[i][j+1] == 0) visit(i, j+1);

    if(success != 1 && maze[i+1][j] == 0) visit(i+1, j);

    if(success != 1 && maze[i][j-1] == 0) visit(i, j-1);

    if(success != 1 && maze[i-1][j] == 0) visit(i-1, j);

 

    if(success != 1)

        maze[i][j] = 0;

   

    return success;

 

 

 

 


6.Algorithm Gossip: 老鼠走迷官

說明由于迷宮的設(shè)計,老鼠走迷宮的入口至出口路徑可能不只一條,如何求出所有的路徑呢?

解法求所有路徑看起來復(fù)雜但其實更簡單,只要在老鼠走至出口時顯示經(jīng)過的路徑,然后退回上一格重新選擇下一個位置繼續(xù)遞回就可以了,比求出單一路徑還簡單,我們的程式只要作一點修改就可以了。

#include <stdio.h>

#include <stdlib.h>

 

void visit(int, int);

 

int maze[9][9] = {{2, 2, 2, 2, 2, 2, 2, 2, 2},

                  {2, 0, 0, 0, 0, 0, 0, 0, 2},

                  {2, 0, 2, 2, 0, 2, 2, 0, 2},

                  {2, 0, 2, 0, 0, 2, 0, 0, 2},

                  {2, 0, 2, 0, 2, 0, 2, 0, 2},

                  {2, 0, 0, 0, 0, 0, 2, 0, 2},

                  {2, 2, 0, 2, 2, 0, 2, 2, 2},

                  {2, 0, 0, 0, 0, 0, 0, 0, 2},

                  {2, 2, 2, 2, 2, 2, 2, 2, 2}};

 

int startI = 1, startJ = 1;  // 入口

int endI = 7, endJ = 7;  // 出口

 

int main(void) {

    int i, j;

 

    printf("顯示迷宮\n");

    for(i = 0; i < 7; i++) {

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

            if(maze[i][j] == 2)

                printf("█");

            else

                printf("  ");

        printf("\n");

    }

 

    visit(startI, startJ);

 

    return 0;

}

 

void visit(int i, int j) {

    int m, n;

 

    maze[i][j] = 1;

 

    if(i == endI && j == endJ) {

        printf("\n顯示路徑\n");

        for(m = 0; m < 9; m++) {

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

                if(maze[m][n] == 2)

                    printf("█");

                else if(maze[m][n] == 1)

                    printf("◇");

                else

                    printf("  ");

            printf("\n");

        }

    }

 

    if(maze[i][j+1] == 0) visit(i, j+1);

    if(maze[i+1][j] == 0) visit(i+1, j);

    if(maze[i][j-1] == 0) visit(i, j-1);

    if(maze[i-1][j] == 0) visit(i-1, j);

 

    maze[i][j] = 0;

 

 

 

 

 

 

 

 


7.Algorithm Gossip: 騎士走棋盤

說明騎士旅游Knight tour在十八世紀初倍受數(shù)學(xué)家與拼圖迷的注意它什么時候被提出已不可考騎士的走法為西洋棋的走法騎士可以由任一個位置出發(fā)它要如何走完[所有的位置

解法騎士的走法,基本上可以使用遞回來解決,但是純綷的遞回在維度大時相當沒有效率,一個聰明的解法由J.C. Warnsdorff1823年提出,簡單的說,先將最難的位置走完,接下來的路就寬廣了,騎士所要走的下一步,「為下一步再選擇時,所能走的步數(shù)最少的一步。」,使用這個方法,在不使用遞回的情況下,可以有較高的機率找出走法(找不到走法的機會也是有的)。

#include <stdio.h>

 

int board[8][8] = {0};

 

int main(void) {

    int startx, starty;

    int i, j;

    printf("輸入起始點");

    scanf("%d %d", &startx, &starty);

 

    if(travel(startx, starty)) {

        printf("游歷完成\n");

    }

    else {

        printf("游歷失敗\n");

    }

 

    for(i = 0; i < 8; i++) {

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

            printf("%2d ", board[i][j]);

        }

        putchar('\n');

    }

    return 0;

}

 

int travel(int x, int y) {

    // 對應(yīng)騎士可走的八個方向

    int ktmove1[8] = {-2, -1, 1, 2, 2, 1, -1, -2};

    int ktmove2[8] = {1, 2, 2, 1, -1, -2, -2, -1};

 

    // 測試下一步的出路

    int nexti[8] = {0};

    int nextj[8] = {0};

    // 記錄出路的個數(shù)

    int exists[8] = {0};

    int i, j, k, m, l;

    int tmpi, tmpj;

    int count, min, tmp;

 

    i = x;

    j = y;

    board[i][j] = 1;

 

    for(m = 2; m <= 64; m++) {

        for(l = 0; l < 8; l++)

            exists[l] = 0;

 

        l = 0;

 

        // 試探八個方向

        for(k = 0; k < 8; k++) {

            tmpi = i + ktmove1[k];

            tmpj = j + ktmove2[k];

 

            // 如果是邊界了不可走

            if(tmpi < 0 || tmpj < 0 || tmpi > 7 || tmpj > 7)

                continue;

 

            // 如果這個方向可走記錄下來

            if(board[tmpi][tmpj] == 0) {

                nexti[l] = tmpi;

                nextj[l] = tmpj;

                // 可走的方向加一個

                l++;

            }

        }

 

        count = l;

        // 如果可走的方向為0返回

        if(count == 0) {

            return 0;

        }

        else if(count == 1) {

            // 只有一個可走的方向

            // 所以直接是最少出路的方向

            min = 0;

        }

        else {

            // 找出下一個位置的出路數(shù)

            for(l = 0; l < count; l++) {

                for(k = 0; k < 8; k++) {

                    tmpi = nexti[l] + ktmove1[k];

                    tmpj = nextj[l] + ktmove2[k];

                    if(tmpi < 0 || tmpj < 0 ||

                       tmpi > 7 || tmpj > 7) {

                        continue;

                    }

                    if(board[tmpi][tmpj] == 0)

                        exists[l]++;

                }

            }

            tmp = exists[0];

            min = 0;

            // 從可走的方向中尋找最少出路的方向

            for(l = 1; l < count; l++) {

                if(exists[l] < tmp) {

                    tmp = exists[l];

                    min = l;

                }

            }

        }

 

        // 走最少出路的方向

        i = nexti[min];

        j = nextj[min];

        board[i][j] = m;

    }

 

    return 1;

}

 


8.Algorithm Gossip: 八皇后

說明西洋棋中的皇后可以直線前進,吃掉遇到的所有棋子,如果棋盤上有八個皇后,則這八個皇后如何相安無事的放置在棋盤上,1970年與1971年, E.W.DijkstraN.Wirth曾經(jīng)用這個問題來講解程式設(shè)計之技巧。

解法關(guān)于棋盤的問題,都可以用遞回求解,然而如何減少遞回的次數(shù)?在八個皇后的問題中,不必要所有的格子都檢查過,例如若某列檢查過,該該列的其它格子就不用再檢查了,這個方法稱為分支修剪。

 

#include <stdio.h>

#include <stdlib.h>

#define N 8

 

int column[N+1]; // 同欄是否有皇后1表示有

int rup[2*N+1]; // 右上至左下是否有皇后

int lup[2*N+1]; // 左上至右下是否有皇后

int queen[N+1] = {0};

int num; // 解答編號

 

void backtrack(int); // 遞回求解

 

int main(void) {

    int i;

    num = 0;

 

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

        column[i] = 1;

 

    for(i = 1; i <= 2*N; i++)

        rup[i] = lup[i] = 1;

 

    backtrack(1);

 

    return 0;

}

 

void showAnswer() {

    int x, y;

    printf("\n解答 %d\n", ++num);

    for(y = 1; y <= N; y++) {

        for(x = 1; x <= N; x++) {

            if(queen[y] == x) {

                printf(" Q");

            }

            else {

                printf(" .");

            }

        }

        printf("\n");

    }

}

 

void backtrack(int i) {

    int j;

 

    if(i > N) {

        showAnswer();

    }

    else {

        for(j = 1; j <= N; j++) {

            if(column[j] == 1 &&

                 rup[i+j] == 1 && lup[i-j+N] == 1) {

                queen[i] = j;

                // 設(shè)定為占用

                column[j] = rup[i+j] = lup[i-j+N] = 0;

                backtrack(i+1);

                column[j] = rup[i+j] = lup[i-j+N] = 1;

            }

        }

    }

}

 

 

 

 

 


9.Algorithm Gossip: 八枚銀幣

說明現(xiàn)有八枚銀幣a b c d e f g h,已知其中一枚是假幣,其重量不同于真幣,但不知是較輕或較重,如何使用天平以最少的比較次數(shù),決定出哪枚是假幣,并得知假幣比真幣較輕或較重。

解法單就求假幣的問題是不難,但問題限制使用最少的比較次數(shù),所以我們不能以單純的回圈比較來求解,我們可以使用決策樹(decision tree),使用分析與樹狀圖來協(xié)助求解。一個簡單的狀況是這樣的,我們比較a+b+cd+e+f ,如果相等,則假幣必是gh,我們先比較gh哪個較重,如果g較重,再與a比較(a是真幣),如果g等于a,則g為真幣,則h為假幣,由于hg輕而 g是真幣,則h假幣的重量比真幣輕。

 

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

 

void compare(int[], int, int, int);

void eightcoins(int[]);

 

int main(void) {

    int coins[8] = {0};

    int i;

 

    srand(time(NULL));

 

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

        coins[i] = 10;

 

    printf("\n輸入假幣重量(10大或小)");

    scanf("%d", &i);

    coins[rand() % 8] = i;

 

    eightcoins(coins);

 

    printf("\n\n列出所有錢幣重量");

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

        printf("%d ", coins[i]);

 

    printf("\n");

 

    return 0;

}

 

void compare(int coins[], int i, int j, int k) {

    if(coins[i] > coins[k])

        printf("\n假幣 %d 較重", i+1);

    else

        printf("\n假幣 %d 較輕", j+1);

}

 

void eightcoins(int coins[]) {

    if(coins[0]+coins[1]+coins[2] ==

       coins[3]+coins[4]+coins[5]) {

        if(coins[6] > coins[7])

            compare(coins, 6, 7, 0);

        else

            compare(coins, 7, 6, 0);

    }

    else if(coins[0]+coins[1]+coins[2] >

            coins[3]+coins[4]+coins[5]) {

        if(coins[0]+coins[3] == coins[1]+coins[4])

            compare(coins, 2, 5, 0);

        else if(coins[0]+coins[3] > coins[1]+coins[4])

            compare(coins, 0, 4, 1);

        if(coins[0]+coins[3] < coins[1]+coins[4])

            compare(coins, 1, 3, 0);

    }

    else if(coins[0]+coins[1]+coins[2] <

            coins[3]+coins[4]+coins[5]) {

        if(coins[0]+coins[3] == coins[1]+coins[4])

            compare(coins, 5, 2, 0);

        else if(coins[0]+coins[3] > coins[1]+coins[4])

            compare(coins, 3, 1, 0);

        if(coins[0]+coins[3] < coins[1]+coins[4])

            compare(coins, 4, 0, 1);

    }

}

 

 

 


10.Algorithm Gossip: 生命游戲

說明生命游戲game of life1970年由英國數(shù)學(xué)家J. H. Conway所提出某一細胞的鄰居包括上、下、左、右、左上、左下、右上與右下相鄰之細胞游戲規(guī)則如下

孤單死亡:如果細胞的鄰居小于一個,則該細胞在下一次狀態(tài)將死亡。

擁擠死亡:如果細胞的鄰居在四個以上,則該細胞在下一次狀態(tài)將死亡。

穩(wěn)定:如果細胞的鄰居為二個或三個,則下一次狀態(tài)為穩(wěn)定存活。

復(fù)活:如果某位置原無細胞存活,而該位置的鄰居為三個,則該位置將復(fù)活一細胞。

解法生命游戲的規(guī)則可簡化為以下,并使用CASE比對即可使用程式實作:

鄰居個數(shù)為0145678時,則該細胞下次狀態(tài)為死亡。

鄰居個數(shù)為2時,則該細胞下次狀態(tài)為復(fù)活。

鄰居個數(shù)為3時,則該細胞下次狀態(tài)為穩(wěn)定。

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

 

#define MAXROW 10

#define MAXCOL 25

#define DEAD 0

#define ALIVE 1

int map[MAXROW][MAXCOL], newmap[MAXROW][MAXCOL];

 

void init();

int neighbors(int, int);

void outputMap();

void copyMap();

 

int main() {

   int row, col;

   char ans;

   init();

   while(1) {

      outputMap();

      for(row = 0; row < MAXROW; row++) {

         for(col = 0; col < MAXCOL; col++) {

            switch (neighbors(row, col)) {

               case 0:

               case 1:

               case 4:

               case 5:

               case 6:

               case 7:

               case 8:

                  newmap[row][col] = DEAD;

                  break;

               case 2:

                  newmap[row][col] = map[row][col];

                  break;

               case 3:

                  newmap[row][col] = ALIVE;

                  break;

            }

         }

      }

 

      copyMap();

      printf("\nContinue next Generation ? ");

      getchar();

      ans = toupper(getchar());

      if(ans != 'Y')         break;

   }

   return 0;

}

 

void init() {

   int row, col;

   

   for(row = 0; row < MAXROW; row++)

      for(col = 0; col < MAXCOL; col++)

         map[row][col] = DEAD;

 

   puts("Game of life Program");

   puts("Enter x, y where x, y is living cell");

   printf("0 <= x <= %d, 0 <= y <= %d\n",

                 MAXROW-1, MAXCOL-1);

   puts("Terminate with x, y = -1, -1");

 

   while(1) {

      scanf("%d %d", &row, &col);

      if(0 <= row && row < MAXROW &&

         0 <= col && col < MAXCOL)

         map[row][col] = ALIVE;

      else if(row == -1 || col == -1)

         break;

      else

         printf("(x, y) exceeds map ranage!");

   }

}

 

int neighbors(int row, int col) {

   int count = 0, c, r;

   for(r = row-1; r <= row+1; r++)

      for(c = col-1; c <= col+1; c++) {

         if(r < 0 || r >= MAXROW || c < 0 || c >= MAXCOL)

            continue;

         if(map[r][c] == ALIVE)

            count++;

      }

 

   if(map[row][col] == ALIVE)

      count--;

   return count;

}

 

void outputMap() {

   int row, col;

   printf("\n\n%20cGame of life cell status\n");

   for(row = 0; row < MAXROW; row++) {

      printf("\n%20c", ' ');

      for(col = 0; col < MAXCOL; col++)

         if(map[row][col] == ALIVE)        putchar('#');

         else         putchar('-');

   }

}

 

void copyMap() {

   int row, col;

   for(row = 0; row < MAXROW; row++)

      for(col = 0; col < MAXCOL; col++)

         map[row][col] = newmap[row][col];


11.Algorithm Gossip: 字串核對

說明今日的一些高階程式語言對于字串的處理支援越來越強大(例如JavaPerl等),不過字串搜尋本身仍是個值得探討的課題,在這邊以Boyer- Moore法來說明如何進行字串說明,這個方法快且原理簡潔易懂。

解法字串搜尋本身不難,使用暴力法也可以求解,但如何快速搜尋字串就不簡單了,傳統(tǒng)的字串搜尋是從關(guān)鍵字與字串的開頭開始比對,例如 Knuth-Morris-Pratt 演算法 字串搜尋,這個方法也不錯,不過要花時間在公式計算上;Boyer-Moore字串核對改由關(guān)鍵字的后面開始核對字串,并制作前進表,如果比對不符合則依前進表中的值前進至下一個核對處,假設(shè)是p好了,然后比對字串中p-n+1p的值是否與關(guān)鍵字相同。

如果關(guān)鍵字中有重復(fù)出現(xiàn)的字元,則前進值就會有兩個以上的值,此時則取前進值較小的值,如此就不會跳過可能的位置,例如texture這個關(guān)鍵字,t的前進值應(yīng)該取后面的3而不是取前面的7

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

void table(char*); // 建立前進表

int search(int, char*, char*); // 搜尋關(guān)鍵字

void substring(char*, char*, int, int); // 取出子字串

 

int skip[256];

 

int main(void) {

char str_input[80];

char str_key[80];

char tmp[80] = {'\0'};

int m, n, p;

printf("請輸入字串");

gets(str_input);

printf("請輸入搜尋關(guān)鍵字");

gets(str_key);

m = strlen(str_input); // 計算字串長度

n = strlen(str_key);

table(str_key);

p = search(n-1, str_input, str_key);

 

while(p != -1) {

substring(str_input, tmp, p, m);

printf("%s\n", tmp);

p = search(p+n+1, str_input, str_key);

}

 

printf("\n");

return 0;

}

 

void table(char *key) {

int k, n;

n = strlen(key);

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

skip[k] = n;

for(k = 0; k < n - 1; k++)

skip[key[k]] = n - k - 1;

}

 

int search(int p, char* input, char* key) {

int i, m, n;

char tmp[80] = {'\0'};

m = strlen(input);

n = strlen(key);

 

while(p < m) {

substring(input, tmp, p-n+1, p);

if(!strcmp(tmp, key)) // 比較兩字串是否相同

return p-n+1;

p += skip[input[p]];

}

return -1;

}

 

void substring(char *text, char* tmp, int s, int e) {

int i, j;

for(i = s, j = 0; i <= e; i++, j++)

        mp[j] = text[i];

tmp[j] = '\0';

}

 


12.Algorithm Gossip: 雙色、三色河內(nèi)塔

說明雙色河內(nèi)塔與三色河內(nèi)塔是由之前所介紹過的河內(nèi)塔規(guī)則衍生而來,雙色河內(nèi)塔的目的是將下圖左上的圓環(huán)位置經(jīng)移動成為右下的圓環(huán)位置:

而三色河內(nèi)塔則是將下圖左上的圓環(huán)經(jīng)移動成為右上的圓環(huán):

解法無論是雙色河內(nèi)塔或是三色河內(nèi)塔,其解法觀念與之前介紹過的河內(nèi)塔是類似的,同樣也是使用遞回來解,不過這次遞回解法的目的不同,我們先來看只有兩個盤的情況,這很簡單,只要將第一柱的黃色移動至第二柱,而接下來第一柱的藍色移動至第三柱。

再來是四個盤的情況,首先必須用遞回完成下圖左上至右下的移動:

接下來最底層的就不用管它們了,因為它們已經(jīng)就定位,只要再處理第一柱的上面兩個盤子就可以了。那么六個盤的情況呢?一樣!首先必須用遞回完成下圖左上至右下的移動:

接下來最底層的就不用管它們了,因為它們已經(jīng)就定位,只要再處理第一柱上面的四個盤子就可以了,這又與之前只有四盤的情況相同,接下來您就知道該如何進行解題了,無論是八個盤、十個盤以上等,都是用這個觀念來解題。

那么三色河內(nèi)塔呢?一樣,直接來看九個盤的情況,首先必須完成下圖的移動結(jié)果:

接下來最底兩層的就不用管它們了,因為它們已經(jīng)就定位,只要再處理第一柱上面的三個盤子就可以了。

雙色河內(nèi)塔 C 實作

#include <stdio.h>

 

void hanoi(int disks, char source, char temp, char target) {

    if (disks == 1) {

        printf("move disk from %c to %c\n", source, target);

        printf("move disk from %c to %c\n", source, target);

    } else {

        hanoi(disks-1, source, target, temp);

        hanoi(1, source, temp, target);

        hanoi(disks-1, temp, source, target);

    }

}

 

void hanoi2colors(int disks) {

    char source = 'A';

    char temp = 'B';

    char target = 'C';

    int i;

    for(i = disks / 2; i > 1; i--) {

        hanoi(i-1, source, temp, target);

        printf("move disk from %c to %c\n", source, temp);

        printf("move disk from %c to %c\n", source, temp);

        hanoi(i-1, target, temp, source);

        printf("move disk from %c to %c\n", temp, target);

    }

    printf("move disk from %c to %c\n", source, temp);

    printf("move disk from %c to %c\n", source, target);

}

 

int main() {

    int n;

    printf("請輸入盤數(shù)");

    scanf("%d", &n);

 

    hanoi2colors(n);

 

    return 0;

}

 

三色河內(nèi)塔 C 實作

#include <stdio.h>

 

void hanoi(int disks, char source, char temp, char target) {

    if (disks == 1) {

        printf("move disk from %c to %c\n", source, target);

        printf("move disk from %c to %c\n", source, target);

        printf("move disk from %c to %c\n", source, target);

    } else {

        hanoi(disks-1, source, target, temp);

        hanoi(1, source, temp, target);

        hanoi(disks-1, temp, source, target);

    }

}

 

void hanoi3colors(int disks) {

    char source = 'A';

    char temp = 'B';

    char target = 'C';

    int i;

    if(disks == 3) {

        printf("move disk from %c to %c\n", source, temp);

        printf("move disk from %c to %c\n", source, temp);

        printf("move disk from %c to %c\n", source, target);

        printf("move disk from %c to %c\n", temp, target);

        printf("move disk from %c to %c\n", temp, source);

        printf("move disk from %c to %c\n", target, temp);;

    }

    else {

        hanoi(disks/3-1, source, temp, target);

        printf("move disk from %c to %c\n", source, temp);

        printf("move disk from %c to %c\n", source, temp);

        printf("move disk from %c to %c\n", source, temp);

 

        hanoi(disks/3-1, target, temp, source);

        printf("move disk from %c to %c\n", temp, target);

        printf("move disk from %c to %c\n", temp, target);

        printf("move disk from %c to %c\n", temp, target);

 

        hanoi(disks/3-1, source, target, temp);

        printf("move disk from %c to %c\n", target, source);

        printf("move disk from %c to %c\n", target, source);

 

        hanoi(disks/3-1, temp, source, target);

        printf("move disk from %c to %c\n", source, temp);

       

        for (i = disks / 3 - 1; i > 0; i--) {

            if (i>1) {

                hanoi(i-1, target, source, temp);

            }

            printf("move disk from %c to %c\n",target, source);

            printf("move disk from %c to %c\n",target, source);

            if (i>1) {

                hanoi(i-1, temp, source, target);

            }

            printf("move disk from %c to %c\n", source, temp);

        }

    }

}

 

int main() {

    int n;

    printf("請輸入盤數(shù)");

    scanf("%d", &n);

 

    hanoi3colors(n);

    return 0;


路過

雞蛋

鮮花

握手

雷人

評論 (0 個評論)

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

返回頂部
主站蜘蛛池模板: 一级在线毛片 | 特一级毛片 | 二区在线观看 | 久久日韩粉嫩一区二区三区 | 午夜精品久久久久久久久久久久久 | 91免费看片 | 国产伦精品一区二区三区高清 | www.日本三级 | 天天艹天天干天天 | 色啪网| 激情欧美日韩一区二区 | 五月网婷婷 | 精品久久香蕉国产线看观看亚洲 | 久久精品中文字幕 | 国产一区不卡 | 亚洲午夜精品久久久久久app | a级黄色网 | 日韩视频在线观看中文字幕 | 中文字幕免费 | 国产免费av在线 | 国产精品久久久久久久久久免费看 | 午夜久久久久 | 色吊丝2| 男女网站在线观看 | 日本视频免费观看 | 久久中文字幕一区 | 丝袜毛片 | 天天天天天操 | 欧美一区二区在线观看 | 国产在线视频网 | 精品久久久久久久久久久久久久 | 日韩高清电影 | 国产乱码精品一区二区三区五月婷 | 91在线免费视频 | 国产成人精品久久久 | 成人精品免费视频 | 欧美多人在线 | 在线播放一区 | av先锋资源 | 亚洲欧美一区二区三区在线 | 成人影视网址 |