C語言常用的算法歸納_第1頁
C語言常用的算法歸納_第2頁
C語言常用的算法歸納_第3頁
C語言常用的算法歸納_第4頁
C語言常用的算法歸納_第5頁
已閱讀5頁,還剩19頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

實用標準文案語言常用算法歸納應當掌握的一般算法一、基本算法:交換、累加、累乘二、非數值計算常用經典算法:窮舉、排序(冒泡,選擇)、查找(順序即線性)三、數值計算常用經典算法:級數計算(直接、簡接即遞推)、一元非線性方程求根(牛頓迭代法、二分法)、定積分計算(矩形法、梯形法)四、其他:迭代、進制轉換、矩陣轉置、字符處理(統計、數字串、字母大小寫轉換、加密等)、整數各數位上數字的獲取、輾轉相除法求最大公約數(最小公倍數)、求最值、判斷素數(各種變形)、數組元素的插入(刪除)、二維數組的其他典型問題(方陣的特點、楊輝三角形)詳細講解一、基本算法1.交換(兩量交換借助第三者)例1、任意讀入兩個整數,將二者的值交換后輸出。main(){int a,b,t;scanf("%d%d",&a,&b);printf("%d,%d\n",a,b);t=a; a=b; b=t;printf("%d,%d\n",a,b);}精彩文檔實用標準文案【解析】程序中加粗部分為算法的核心,如同交換兩個杯子里的飲料,必須借助第三個空杯子。假設輸入的值分別為 3、7,則第一行輸出為 3,7;第二行輸出為 7,3。其中t為中間變量,起到“空杯子”的作用。注意:三句賦值語句賦值號左右的各量之間的關系!【應用】例2、任意讀入三個整數,然后按從小到大的順序輸出。main(){int a,b,c,t;scanf("%d%d%d",&a,&b,&c);/*以下兩個if 語句使得a中存放的數最小*/if(a>b){ t=a; a=b; b=t; }if(a>c){ t=a; a=c; c=t; }/*以下if 語句使得b中存放的數次小*/if(b>c) { t=b; b=c; c=t; }printf("%d,%d,%d\n",a,b,c);}2.累加累加算法的要領是形如“s=s+A”的累加式,此式必須出現在循環中才能被反復執行,從而實現累加功能。“A”通常是有規律變化的表達式,s在進入循環前必須獲得合適的初值,通常為0。例1、求1+2+3+??+100的和。main(){int i,s;s=0; i=1;while(i<=100){s=s+i; /*累加式*/i=i+1; /*特殊的累加式*/}printf("1+2+3+...+100=%d\n",s);}【解析】程序中加粗部分為累加式的典型形式,賦值號左右都出現的變量稱為累加器,其中“i = i + 1”為特殊的累加式,每次累加的值為 1,這樣的累加器又稱為計數器。3.累乘精彩文檔實用標準文案累乘算法的要領是形如“s=s*A”的累乘式,此式必須出現在循環中才能被反復執行,從而實現累乘功能。“A”通常是有規律變化的表達式,s在進入循環前必須獲得合適的初值,通常為1。例1、求10![分析]10!=1×2×3×??×10main(){int i; long c;c=1; i=1;while(i<=10){c=c*i; /*累乘式*/i=i+1;}printf("1*2*3*...*10=%ld\n",c);}二、非數值計算常用經典算法1.窮舉也稱為“枚舉法”,即將可能出現的每一種情況一一測試,判斷是否滿足條件,一般采用循環來實現。例1、用窮舉法輸出所有的水仙花數(即這樣的三位正整數:其每位數位上的數字的立方和與該數相等,比如:1*1*1+5*5*5+3*3*3=153)。[法一]main(){int x,g,s,b;for(x=100;x<=999;x++){g=x%10; s=x/10%10; b=x/100;if(b*b*b+s*s*s+g*g*g==x)printf("%d\n",x);}}【解析】此方法是將100到999所有的三位正整數一一考察,即將每一個三位正整數的個位數、十位數、百位數一一求出(各數位上的數字的提取算法見下面的“數字處理”),算出三者的立方和,一旦與原數相等就輸出。共考慮了 900個三位正整數。[法二]main(){int g,s,b;for(b=1;b<=9;b++)for(s=0;s<=9;s++)for(g=0;g<=9;g++)精彩文檔實用標準文案if(b*b*b+s*s*s+g*g*g==b*100+s*10+g) printf("%d\n",b*100+s*10+g);}【解析】此方法是用 1到9做百位數字、0到9做十位和個位數字,將組成的三位正整數與每一組的三個數的立方和進行比較,一旦相等就輸出。共考慮了 900個組合(外循環單獨執行的次數為9,兩個內循環單獨執行的次數分別為10次,故if語句被執行的次數為9×10×10=900),即900個三位正整數。與法一判斷的次數一樣。2.排序(1)冒泡排序(起泡排序)假設要對含有n個數的序列進行升序排列,冒泡排序算法步驟是:①從存放序列的數組中的第一個元素開始到最后一個元素,依次對相鄰兩數進行比較,若前者大后者小,則交換兩數的位置;②第①趟結束后,最大數就存放到數組的最后一個元素里了,然后從第一個元素開始到倒數第二個元素,依次對相鄰兩數進行比較,若前者大后者小,則交換兩數的位置;③重復步驟①n-1趟,每趟比前一趟少比較一次,即可完成所求。例1、任意讀入10個整數,將其用冒泡法按升序排列后輸出。#define n 10main(){int a[n],i,j,t;for(i=0;i<n;i++)scanf("%d",&a[i]);for(j=1;j<=n-1;j++) /*n 個數處理n-1趟*/for(i=0;i<=n-1-j;i++) /*每趟比前一趟少比較一次 */if(a[i]>a[i+1]){t=a[i];a[i]=a[i+1];a[i+1]=t;}for(i=0;i<n;i++) printf("%d\n",a[i]);}(2)選擇法排序選擇法排序是相對好理解的排序算法。假設要對含有 n個數的序列進行升序排列,算法步驟是:①從數組存放的n個數中找出最小數的下標(算法見下面的“求最值”),然后將最小數與第1個數交換位置;②除第1個數以外,再從其余n-1個數中找出最小數(即n個數中的次小數)的下標,將此數與第2個數交換位置;③重復步驟①n-1趟,即可完成所求。例1、任意讀入10個整數,將其用選擇法按升序排列后輸出。#define n 10main()精彩文檔實用標準文案{int a[n],i,j,k,t;for(i=0;i<n;i++) scanf("%d",&a[i]);for(i=0;i<n-1;i++) /*處理n-1趟*/{k = i; /*總是假設此趟處理的第一個(即全部數的第 i個)數最小,k記錄其下標*/for(j=i+1;j<n;j++)if(a[j] < a[k]) k = j;if (k != i){t = a[i]; a[i] = a[k]; a[k] = t;}}for(i=0;i<n;i++)printf("%d\n",a[i]);}3)插入法排序要想很好地掌握此算法,先請了解“有序序列的插入算法”,就是將某數據插入到一個有序序列后,該序列仍然有序。插入算法參見下面的“數組元素的插入”。例1、將任意讀入的整數 x插入一升序數列后,數列仍按升序排列。#define n 10main(){ int a[n]={-1,3,6,9,13,22,27,32,49},x,j,k; /*注意留一個空間給待插數 */scanf("%d",&x);if(x>a[n-2]) a[n-1]=x ; /*比最后一個數還大就往最后一個元素中存放*/else /*查找待插位置*/{j=0;while( j<=n-2 && x>a[j])j++;for(k=n-2; k>=j; k- -) /*從最后一個數開始直到待插位置上的數依次后移一位*/a[k+1]=a[k];a[j]=x; /*插入待插數*/}for(j=0;j<=n-1;j++) printf("%d ",a[j]);}插入法排序的要領就是每讀入一個數立即插入到最終存放的數組中,每次插入都使得該數組有序。例2、任意讀入10個整數,將其用插入法按降序排列后輸出。(提示:將第2至第10個數一一有序插入到數組a中)精彩文檔實用標準文案#define n 10main(){int a[n],i,j,k,x;scanf("%d",&a[0]); /*讀入第一個數,直接存到 a[0]中*/for(j=1;j<n;j++) /*將第2至第10個數一一有序插入到數組 a中*/{scanf("%d",&x);if(x<a[j-1]) a[j]=x;/*比原數列最后一個數還小就往最后一個元素之后存放新讀的數 */else /*以下查找待插位置*/{i=0;while(x<a[i]&&i<=j-1) i++;/*以下for 循環從原最后一個數開始直到待插位置上的數依次后移一位*/for(k=j-1;k>=i;k--) a[k+1]=a[k];a[i]=x; /*插入待插數*/}}for(i=0;i<n;i++) printf("%d\n",a[i]);}(4)歸并排序即將兩個都升序(或降序)排列的數據序列合并成一個仍按原序排列的序列。例1、有一個含有6個數據的升序序列和一個含有4個數據的升序序列,將二者合并成一個含有10個數據的升序序列。#define m 6#define n 4main(){int a[m]={-3,6,19,26,68,100} ,b[n]={8,10,12,22};int i,j,k,c[m+n];i=j=k=0;while(i<m && j<n) /*將a、b數組中的較小數依次存放到 c數組中*/{if(a[i]<b[j]){c[k]=a[i]; i++;}else {c[k]=b[j]; j++;}k++;}while(i>=m && j<n) /* 若a中數據全部存放完畢,將 b中余下的數全部存放到c中*/{c[k]=b[j]; k++; j++;}while(j>=n && i<m) /* 若b中數據全部存放完畢,將 a中余下的數全部存放到c中*/精彩文檔實用標準文案{c[k]=a[i]; k++; i++;}for(i=0;i<m+n;i++) printf("%d ",c[i]);}3.查找(1)順序查找(即線性查找)順序查找的思路是:將待查找的量與數組中的每一個元素進行比較,若有一個元素與之相等則找到;若沒有一個元素與之相等則找不到。例1、任意讀入10個數存放到數組a中,然后讀入待查找數值,存放到x中,判斷a中有無與x等值的數。#define N 10main(){int a[N],i,x;for(i=0;i<N;i++) scanf("%d",&a[i]);/*以下讀入待查找數值*/scanf("%d",&x);for(i=0;i<N;i++)if(a[i]==x)break ; /*一旦找到就跳出循環*/if(i<N) printf("Found!\n");else printf("Not found!\n");}2)折半查找(即二分法)順序查找的效率較低,當數據很多時,用二分法查找可以提高效率。使用二分法查找的前提是數列必須有序。二分法查找的思路是:要查找的關鍵值同數組的中間一個元素比較,若相同則查找成功,結束;否則判別關鍵值落在數組的哪半部分,就在這半部分中按上述方法繼續比較,直到找到或數組中沒有這樣的元素值為止。例1、任意讀入一個整數 x,在升序數組a中查找是否有與x等值的元素。#define n 10main(){int a[n]={2,4,7,9,12,25,36,50,77,90};int x,high,low,mid;/*x 為關鍵值*/scanf("%d",&x);high=n-1; low=0; mid=(high+low)/2;while(a[mid]!=x&&low<high){if(x<a[mid]) high=mid-1; /*修改區間上界*/else low=mid+1; /*修改區間下界*/mid=(high+low)/2;精彩文檔實用標準文案}if(x==a[mid]) printf("Found %d,%d\n",x,mid);else printf("Not found\n");}三、數值計算常用經典算法1.級數計算級數計算的關鍵是“描述出通項”,而通項的描述法有兩種:一為直接法、二為間接法又稱遞推法。直接法的要領是:利用項次直接寫出通項式;遞推法的要領是:利用前一個(或多個)通項寫出后一個通項。可以用直接法描述通項的級數計算例子有:1)1+2+3+4+5+??2)1+1/2+1/3+1/4+1/5+??等等。可以用間接法描述通項的級數計算例子有:1)1+1/2+2/3+3/5+5/8+8/13+??2)1+1/2!+1/3!+1/4!+1/5!+??等等。1)直接法求通項例1、求1+1/2+1/3+1/4+1/5+??+1/100的和。main(){float s; int i;s=0.0;for(i=1;i<=100;i++) s=s+1.0/i ;printf("1+1/2+1/3+...+1/100=%f\n",s);}【解析】程序中加粗部分就是利用項次 i的倒數直接描述出每一項,并進行累加。注意:因為i是整數,故分子必須寫成 1.0的形式!(2)間接法求通項(即遞推法)例2、計算下列式子前 20項的和:1+1/2+2/3+3/5+5/8+8/13+ ??。[分析]此題后項的分子是前項的分母,后項的分母是前項分子分母之和。main(){float s,fz,fm,t,fz1; int i;s=1; /*先將第一項的值賦給累加器 s*/fz=1;fm=2;t=fz/fm; /*將待加的第二項存入 t中*/for(i=2;i<=20;i++)精彩文檔實用標準文案{s=s+t;/*以下求下一項的分子分母 */fz1=fz; /*將前項分子值保存到 fz1中*/fz=fm; /*后項分子等于前項分母*/fm=fz1+fm; /*后項分母等于前項分子、分母之和 */t=fz/fm;}printf("1+1/2+2/3+...=%f\n",s);}下面舉一個通項的一部分用直接法描述,另一部分用遞推法描述的級數計算的例子:例3、計算級 數的值,當通項的絕對值小于 eps時計算停止。#include <math.h>float g(float x,float eps);main(){float x,eps;scanf("%f%f",&x,&eps);printf("\n%f,%f\n",x,g(x,eps));}float g(float x,float eps){int n=1;float s,t;s=1; t=1;do { t=t*x/(2*n);s=s+(n*n+1)*t; /*加波浪線的部分為直接法描述部分, t為遞推法描述部分*/n++;}while(fabs(t)>eps);return s;}2.一元非線性方程求根(1)牛頓迭代法牛頓迭代法又稱牛頓切線法:先任意設定一個與真實的根接近的值 x0作為第一次近似根,由x0求出f(x0), 過(x0,f(x0)) 點做f(x)的切線,交x軸于x1,把它作為第二次近似根,再由x1求出f(x1), 過(x1,f(x1)) 點做f(x)的切線,交x軸于x2,??如此繼續下去,直到足夠接近(比如|x- x0|<1e-6時)真正的根 x*為止。而f '(x0)=f(x0)/( x1- x0) 所以 x1= x0- f(x0)/ f ' (x0)精彩文檔例如,用牛頓迭代法求下列方程在 1.5附近的根:2x3-4x2+3x-6=0。#include "math.h"main(){float x,x0,f,f1; x=1.5;do{x0=x;f=2*x0*x0*x0-4*x0*x0+3*x0-6;f1=6*x0*x0-8*x0+3;x=x0-f/f1;}while(fabs(x-x0)>=1e-5);printf ("%f\n",x);}(2)二分法算法要領是:先指定一個區間 [x1, x2],如果函數 f(x)在此區間是單調變化的,則可以根據f(x1)和 f(x2)是否同號來確定方程 f(x)=0 在區間[x1, x2]內是否有一個實根;如果f(x1)和 f(x2)同號,則f(x) 在區間[x1, x2]內無實根,要重新改變 x1和x2的值。當確定f(x) 在區間[x1, x2]內有一個實根后,可采取二分法將 [x1, x2]一分為二,再判斷在哪一個小區間中有實根。如此不斷進行下去,直到小區間足夠小為止。具體算法如下:1)輸入x1和x2的值。2)求f(x1)和f(x2)。(3)如果f(x1)和f(x2)同號說明在[x1, x2] 內無實根,返回步驟(1),重新輸入x1和x2的值;若f(x1)和f(x2)不同號,則在區間[x1, x2]內必有一個實根,執行步驟(4)。(4)求x1和x2的中點:x0=(x1+ x2)/2。(5)求f(x0)。(6)判斷f(x0)與f(x1) 是否同號。①如果同號,則應在[x0, x2]中尋找根,此時x1已不起作用,用x0代替x1,用f(x0)代替f(x1)。②如果不同號,則應在[x1, x0]中尋找根,此時x2已不起作用,用x0代替x2,用f(x0)代替f(x2)。精彩文檔實用標準文案7)判斷f(x0)的絕對值是否小于某一指定的值(例如10-5)。若不小于10-5,則返回步驟(4)重復執行步驟(4)、(5)、(6);否則執行步驟(8)。8)輸出x0的值,它就是所求出的近似根。例如,用二分法求方程 2x3-4x2+3x-6=0在(-10,10)之間的根。#include "math.h"main(){float x1,x2,x0,fx1,fx2,fx0;do {printf("Enter x1&x2");scanf("%f%f",&x1,&x2);fx1=2*x1*x1*x1-4*x1*x1+3*x1-6;fx2=2*x2*x2*x2-4*x2*x2+3*x2-6;}while(fx1*fx2>0);do {x0=(x1+x2)/2;fx0=2*x0*x0*x0-4*x0*x0+3*x0-6;if((fx0*fx1)<0) {x2=x0; fx2=fx0; }else {x1=x0; fx1=fx0; }}while(fabs(fx0)>1e-5);printf("%f\n",x0);}3.梯形法計算定積分定積分 的幾何意義是求曲線 y=f(x)、x=a、x=b以及x軸所圍成的面積。可以近似地把面積視為若干小的梯形面積之和。例如,把區間 [a, b]分成n個長度相等的小區間,每個小區間的長度為h=(b-a)/n,第i個小梯形的面積為[f(a+(i-1)·h)+f(a+i·h)]·h/2,將n個小梯形面積加起來就得到定積分的近似值:根據以上分析,給出“梯形法”求定積分的 N-S結構圖:輸入區間端點:a,b輸入等分數nh=(b-a)/2, s=0從1到nsi=(f(a+(i-1)*h)+f(a+i*h))*h/2s=s+si輸出s精彩文檔實用標準文案上述程序的幾何意義比較明顯,容易理解。但是其中存在重復計算,每次循環都要計算小梯形的上、下底。其實,前一個小梯形的下底就是后一個小梯形的上底,完全不必重復計算。為此做出如下改進:矩形法求定積分則更簡單,就是將等分出來的圖形當作矩形,而不是梯形。例如:求定積分 的值。等分數n=1000。#include "math.h"float DJF(float a,float b){float t,h; int n,i;float HSZ(float x);n=1000; h=fabs(a-b)/n;t=(HSZ(a)+HSZ(b))/2;for(i=1;i<=n-1;i++) t=t+HSZ(a+i*h);t=t*h;return(t);}float HSZ(float x){return(x*x+3*x+2); }main(){float y;y=DJF(0,4);精彩文檔實用標準文案printf("%f\n",y);}四、其他常見算法1.迭代法其基本思想是把一個復雜的計算過程轉化為簡單過程的多次重復。每次重復都從舊值的基礎上遞推出新值,并由新值代替舊值。例如,猴子吃桃問題。猴子第一天摘下若干個桃子,當即吃了一半,還不過癮,又多吃了一個。第二天早上又將剩下的桃子吃掉一半,又多吃了一個。以后每天早上都吃了前一天剩下的一半零一個。到第10天早上想再吃時,就只剩一個桃子了。編程求第一天共摘多少桃子。main(){int day,peach;peach=1;for(day=9;day>=1;day--) peach=(peach+1)*2;printf("The first day:%d\n",peach);}又如,用迭代法求 x= 的根。求平方根的迭代公式是: xn+1=0.5×(xn+a/ xn )[算法]1)設定一個初值x0。2)用上述公式求出下一個值x1。3)再將x1代入上述公式,求出下一個值x2。(4)如此繼續下去,直到前后兩次求出的 x值(xn+1和xn)滿足以下關系:| xn+1- xn|<10-5#include "math.h"main(){float a,x0,x1;scanf("%f",&a);x0=a/2; x1=(x0+a/x0)/2;do{x0=x1;x1=(x0+a/x0)/2;}while(fabs(x0-x1)>=1e-5);printf("%f\n",x1);}2.進制轉換(1)十進制數轉換為其他進制數精彩文檔實用標準文案一個十進制正整數m轉換成r進制數的思路是,將m不斷除以r取余數,直到商為0時止,以反序輸出余數序列即得到結果。注意,轉換得到的不是數值,而是數字字符串或數字串。例如,任意讀入一個十進制正整數,將其轉換成二至十六任意進制的字符串。void tran(int m,int r,char str[],int *n){char sb[]="0123456789ABCDEF"; int i=0,g;do{g=m%r;str[i]=sb[g];m=m/r;i++;}while(m!=0);*n=i;}main(){int x,r0; /*r0 為進制基數*/int i,n; /*n中存放生成序列的元素個數 */char a[50];scanf("%d%d",&x,&r0);if(x>0&&r0>=2&&r0<=16){tran(x,r0,a,&n);for(i=n-1;i>=0;i--) printf("%c",a[i]);printf("\n");}else exit(0);}2)其他進制數轉換為十進制數其他進制整數轉換為十進制整數的要領是:“按權展開”,例如,有二進制數101011,則其十進制形式為1×25+0×24+1×23+0×22+1×21+1×20=43。若r進制數an??a2a1(n位數)轉換成十進制數,方法是an×rn-1+??a2×r1+a1×r0。注意:其他進制數只能以字符串形式輸入。例1、任意讀入一個二至十六進制數(字符串),轉換成十進制數后輸出。#include "string.h"#include "ctype.h"main(){char x[20]; int r,d;gets(x); /*輸入一個r進制整數序列*/scanf("%d",&r); /*輸入待處理的進制基數 2-16*/d=Tran(x,r);printf("%s=%d\n",x,d);}精彩文檔實用標準文案int Tran(char *p,int r){int d,i,cr; char fh,c;d=0; fh=*p;if(fh=='-')p++;for(i=0;i<strlen(p);i++){c=*(p+i);if(toupper(c)>='A') cr=toupper(c)-'A'+10;else cr=c-'0';d=d*r+cr;}if(fh=='-') d=-d;return(d);}3.矩陣轉置矩陣轉置的算法要領是:將一個 m行n列矩陣(即m×n矩陣)的每一行轉置成另一個 n×m矩陣的相應列。例1、將以下2×3矩陣轉置后輸出。即將 1 2 3 轉置成 1 44 5 62 53 6main(){int a[2][3],b[3][2],i,j,k=1;for(i=0;i<2;i++)for(j=0;j<3;j++)a[i][j]=k++;/*以下將a的每一行轉存到 b的每一列*/for(i=0;i<2;i++)for(j=0;j<3;j++)b[j][i]=a[i][j];for(i=0;i<3;i++) /*輸出矩陣b*/{for(j=0;j<2;j++)printf("%3d",b[i][j]);printf("\n");}}精彩文檔實用標準文案4.字符處理1)字符統計:對字符串中各種字符出現的次數的統計。典型例題:任意讀入一個只含小寫字母的字符串,統計其中每個字母的個數。#include "stdio.h "main(){char a[100]; int n[26]={0}; int i; /*定義26個計數器并置初值 0*/gets(a);for(i=0;a[i]!= '\0' ;i++) /*n[0] 中存放’a’的個數,n[1] 中存放’b’的個數??*/n[a[i]-'a' ]++; /*各字符的ASCII碼值減’a’的ASCII碼值,正好得對應計數器下標*/for(i=0;i<26;i++)if(n[i]!=0) printf("%c :%d\n ", i+'a', n[i]);}2)字符加密例如、對任意一個只含有英文字母的字符串,將每一個字母用其后的第三個字母替代后輸出(字母X后的第三個字母為 A,字母Y后的第三個字母為 B,字母Z后的第三個字母為 C。)#include "stdio.h"#include "string.h"main(){char a[80]= "China"; int i;for(i=0; i<strlen(a); i++)if(a[i]>='x'&&a[i]<='z'||a[i]>='X'&&a[i]<='Z') a[i]= a[i]-26+3;else a[i]= a[i]+3;puts(a);}5.整數各數位上數字的獲取算法核心是利用“任何正整數整除10的余數即得該數個位上的數字”的特點,用循環從低位到高位依次取出整數的每一數位上的數字。例1、任意讀入一個5位整數,輸出其符號位及從高位到低位上的數字。main(){long x; int w,q,b,s,g;scanf("%ld",&x);if(x<0) {printf("-,"); x=-x;}w=x/10000; /*求萬位上的數字*/q=x/1000%10; /*求千位上的數字*/精彩文檔實用標準文案b=x/100%10; /*求百位上的數字*/s=x/10%10; /*求十位上的數字*/g=x%10; /*求個位上的數字*/printf("%d,%d,%d,%d,%d\n",w,q,b,s,g);}例2、任意讀入一個整數,依次輸出其符號位及從低位到高位上的數字。[分析]此題讀入的整數不知道是幾位數,但可以用以下示例的方法完成此題:例如讀入的整數為3796,存放在x中,執行x%10后得余數為6并輸出;將x/10得379后賦值給x。再執行x%10后得余數為9并輸出;將x/10得37后賦值給x??直到商x為0時終止。main(){long x; scanf("%ld",&x);if(x<0) {printf("- "); x=-x;}do { /*為了能正確處理0,要用do_while循環*/printf("%d ", x%10);x=x/10;}while(x!=0);printf("\n");}例3、任意讀入一個整數,依次輸出其符號位及從高位到低位上的數字。[分析]此題必須借助數組將依次求得的低位到高位的數字保存后,再逆序輸出。main(){long x; int a[20],i,j;scanf("%ld",&x);if(x<0) {printf("- "); x=-x;}i=0;do {a[i]=x%10;x=x/10; i++;}while(x!=0);for(j=i-1;j>=0;j--)printf("%d ",a[j]);printf("\n");}6.輾轉相除法求兩個正整數的最大公約數該算法的要領是:假設兩個正整數為a和b,先求出前者除以后者的余數,存放到變量r中,若r不為0,則將b的值得賦給a,將r的值得賦給b;再求出a除以b的余數,仍然存放到變量r中??如此反復,直至r為0時終止,此時b中存放的即為原來兩數的最大公約數。精彩文檔實用標準文案例1、任意讀入兩個正整數,求出它們的最大公約數。[法一:用while循環時,最大公約數存放于b中]main(){int a,b,r;do scanf("%d%d",&a,&b);while(a<=0||b<=0); /*確保a和b為正整數*/r=a%b;while(r!=0){a=b;b=r;r=a%b;}printf("%d\n",b);}[ 法二:用do?while循環時,最大公約數存放于 a中]main(){int a,b,r;do scanf("%d%d",&a,&b);while(a<=0||b<=0); /*確保a和b為正整數*/do {r=a%b;a=b;b=r;}while(r!=0);printf("%d\n",a);}【引申】可以利用最大公約數求最小公倍數。提示:兩個正整數 a和b的最小公倍數=ab/最大公約數。例2、任意讀入兩個正整數,求出它們的最小公倍數。[法一:利用最大公約數求最小公倍數 ]main(){int a,b,r,x,y;do scanf("%d%d",&a,&b);while(a<=0||b<=0); /*確保a和b為正整數*/x=a; y=b; /*保留a、b原來的值*/r=a%b;while(r!=0) {a=b;b=r;r=a%b;}printf("%d\n",x*y/b);}[法二:若其中一數的最小倍數也是另一數的倍數,該最小倍數即為所求 ]main(){int a,b,r,i;do scanf("%d%d",&a,&b);while(a<=0||b<=0); /*確保a和b為正整數*/i=1;while(a*i%b!=0) i++;精彩文檔實用標準文案printf("%d\n",i*a);}7.求最值即求若干數據中的最大值(或最小值)。算法要領是:首先將若干數據存放于數組中,通常假設第一個元素即為最大值(或最小值),賦值給最終存放最大值(或最小值)的max(或min)變量中,然后將該量max(或min)的值與數組其余每一個元素進行比較,一旦比該量還大(或小),則將此元素的值賦給max(或min)??所有數如此比較完畢,即可求得最大值(或最小值)。例1、任意讀入10個數,輸出其中的最大值與最小值。#define N 10main(){int a[N],i,max,min;for(i=0;i<N;i++) scanf("%d",&a[i]);max=min=a[0];for(i=1;i<N;i++)if(a[i]>max) max=a[i];else if(a[i]<min) min=a[i];printf("max=%d,min=%d\n",max,min);}8.判斷素數素數又稱質數,即“只能被1和自身整除的大于1的自然數”。判斷素數的算法要領就是依據數學定義,即若該大于1的正整數不能被2至自身減1整除,就是素數。例1、任意讀入一個正整數,判斷其是否為素數。main(){int x,k;do scanf("%d",&x);while(x<=1); /*確保讀入大于1的正整數*/for(k=2;k<=x-1;k++)if(x%k==0)break; /*一旦能被2~自身-1整除,就不可能是素數*/if(k==x) printf("%d is sushu\n",x);else printf("%d is not sushu\n",x);}以上例題可以用以下兩種變形來解決(需要使用輔助判斷的邏輯變量):【變形一】將“2~自身-1”的范圍縮小至“2~自身的一半”main(){int x,k,flag;do scanf("%d",&x); while(x<=1);精彩文檔實用標準文案flag=1; /*先假設x就是素數*/for(k=2;k<=x/2;k++)if(x%k==0){flag=0; break;}/* 一旦不可能是素數,即置 flag 為0*/if(flag==1) printf("%d is sushu\n",x);else printf("%d is not sushu\n",x);}【變形二】將“2~自身-1”的范圍縮小至“2~自身的平方根”#include "math.h"main(){int x,k,flag;do scanf("%d",&x); while(x<=1);flag=1; /*先假設x就是素數*/for(k=2;k<=(int)sqrt(x);k++)if(x%k==0){flag=0; break;}/* 一旦不可能是素數,即置 flag 為0*/if(flag==1) printf("%d is sushu\n",x);else printf("%d is not sushu\n",x);}例2、用篩選法求得100以內的所有素數。算法為:(1)定義一維數組 a,其初值為:2,3,??,100;(2)若a[k]不為0,則將該元素以后的所有 a[k]的倍數的數組元素置為0;( 3 ) a 中 不 為 0 的 元 素 , 均 為 素數。#include <math.h>#include <stdio.h>main( ){int k,j,a[101];clrscr(); /*清屏函數*/for(k=2;k<101;k++)a[k]=k;for(k=2;k<sqrt(101);k++)for(j=k+1;j<101;j++)if(a[k]!=0&&a[j]!=0)if(a[j]%a[k]==0)a[j]=0;for(k=2;k<101;k++)if(a[k]!=0)printf("%5d",a[k]);}9.數組元素的插入、刪除精彩文檔實用標準文案1)數組元素的插入此算法一般是在已經有序的數組中再插入一個數據,使數組中的數列依然有序。算法要領是:假設待插數據為 x,數組a中數據為升序序列。①先將x與a數組當前最后一個元素進行比較,若比最后一個元素還大,就將 x放入其后一個元素中;否則進行以下步驟;②先查找到待插位置。從數組 a的第1個元素開始找到不比 x小的第一個元素,設其下標為i ;③將數組a中原最后一個元素至第i個元素依次一一后移一位,讓出待插數據的位置,即下標為i的位置;④將x存放到a(i)中。例題參見前面“‘排序’中插入法排序的例 1”。(2)數組元素的刪除此算法的要領是:首先要找到(也可能找不到)待刪除元素在數組中的位置 (即下標),然后將待刪元素后的每一個元素向前移動一位,最后將數組元素的個數減 1。例1、數組a中有若干不同考試分數,任意讀入一個分數

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論