基于C语言的算法总结(不定时更新)

这篇博客我准备写一些我见过的算法,虽然现在我见过的还很少,但我相信会越来越多,方便日后自己查阅

好了 开始了

求解最大子序列和的最有效的算法

 1 int MaxSubsequenceSum(const int A[], int N)
 2 {
 3   int ThisSum, MaxSum, j;
 4   // 定义本次循环的和 与 最大和 为0
 5   ThisSum = MaxSum = 0;  
 6   // 循环求和
 7   for (j = 0; j < N; j++)
 8   {
 9        ThisSum += A[j];
10        // 判断本次的和与最大和的大小,如果本次和比最大和大,把本次和的值赋值给最大和
11        if (ThisSum > MaxSum)
12         MaxSum = ThisSum;
13        /* 如果本次和小于0,将本次和赋值为0 因为加到小于0了肯定不是最大子序列和了
14         将其赋值为0 从新进行最大子序列和的比较 */
15        else if ( ThisSum < 0)
16        ThisSum = 0;
17   }
18       return MaxSum;
19 }
20 // 这个算法只循环了一次数组就求出了最大子序列和

 已知排序好的数组,求某个值的下标---->对分查找

 1 int BinarySearch( const int A[], int X, int N)
 2 {
 3     // 定义最小坐标,中间坐标,最大坐标
 4     int Low, Mid, High;
 5     Low = 0; High = N - 1;
 6     // 循环条件 最小坐标<=最大坐标
 7     while (Low <= High) {
 8         // 中间坐标算出来
 9         Mid = (Low + High) / 2;
10         // 判断中间坐标对应的值是否小于要找到的值
11         if (A[Mid] < X) {
12             /* 如果小于让最小坐标变成中间坐标 + 1
13             (也就是不用考虑中间坐标前面的数了) */
14             Low = Mid + 1;
15         } else if (A[Mid] > X) {
16             /* 如果大于让最大坐标变成中间坐标 - 1
17              (也就是不用考虑中间坐标后面的数了) */
18             High = Mid - 1;
19         } else {
20             // 循环找到坐标
21             return Mid;  // Found
22         }
23     }
24     return -1;   // Not Found
25 }

计算最大公因数(欧几里德算法)

两个整数的最大公因数(Gcd)是同时整除二者的最大整数 例:Gcd(50, 15) = 5

 1 unsigned int Gcd (unsigned int M, unsigned int N)
 2 {
 3     unsigned int Rem;
 4     while ( N > 0) {
 5         Rem = M % N;
 6         M = N;
 7         N = Rem;
 8     }
 9     return M;
10 }
11 // 算法通过连续计算余数直到余数是0为止,最后的非零余数就是最大公因数

高效率的取幂算法

 1 /*
 2  如果N是偶数,我们有 X的N次方 = X的N/2次方 * X的N/2次方
 3  如果N是奇数,我们有 X的N次方 = X的(N - 1)/2次方 * X的(N - 1)/2次方 * X
 4  */
 5 long int Pow (long int x, int N)
 6 {
 7     if (N == 0) {
 8         return 0;
 9     }
10     if (N == 1) {
11         return x;
12     }
13     if (N % 2 == 0) {
14         return Pow(x*x, N/2);
15     } else {
16         return Pow(x*x, N/2) * x;
17     }
18 }
19 // 此算法运用到了递归

数组排序:冒泡排序

 1 void sortArray(int a[], int len)
 2 {
 3     for (int i = 0; i < len-1; i++) {
 4         /*
 5          每趟排序都会确定一个数,所以需要再循环len-i次,但因为每次都是
 6          相邻的两个数比较,为了a[j + 1]不越界,让j循环到len-i-1时停止
 7          */
 8         for (int j = 0; j < len-i-1; j++) {
 9             int tmp;
10             // 如果条件满足,交换a[j]和a[j+1]两个相邻数的值
11             if (a[j] > a[j+1]) {
12                 tmp = a[j];
13                 a[j] = a[j+1];
14                 a[j+1] = tmp;
15             }
16         }
17     }
18 }

数组排序:选择排序

 1 void selectSort(int a[], int len)
 2 {
 3     // 确定需要排序的次数
 4     for (int i = 0; i < len - 1; i++) {
 5         // 每一次都是拿一个元素与后面其他的元素进行比较,找到最小值
 6         for (int j = i + 1; j < len; j++) {
 7             if (a[i] > a[j]) {
 8                 int tmp = a[i];
 9                 a[i] = a[j];
10                 a[j] = tmp;
11             }
12         }
13     }
14 }

插入法排序

 1 //插入法排升序
 2 /*
 3  插入算法把要排序的数组分成两部分:
 4     第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置)
 5     第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。
 6  */
 7 #include <stdio.h>
 8 
 9 void InsertionSort(int a[], int len)
10 {
11     int i, j, tmp;
12     // i=1是为了让数组多一个空间方便插入
13     for (i = 1; i<len; i++) {
14         // 将数组第i+1个数取出来
15         tmp = a[i];
16         // 循环从数组第i+1个数开始,判断前面的数是否大于这个数
17         for (j = i; j>0 && a[j-1]>tmp; j--) {
18             // 如果前面的数大于这个数,将前面的数移动到它后面一位,使前面留出位置
19             a[j] = a[j-1];
20         }
21         // 将这个数插入这个留出的位置
22         a[j] = tmp;
23     }
24     
25     for (int i = 0; i<7; i++) {
26         printf("%d	",a[i]);
27     }
28     printf("
");
29 }
30 
31 int main()
32 {
33 //  插入排序的思想是数组是部分有序的,然后将无序的部分循环插入到已有序的序列中
34     int b[]={1,2,3,4,18,32,12};
35     InsertionSort(b, 7);
36 }

为了方便理解插入一张图片,配合上面代码理解(如下)

有两个数组a,b,大小都为n,数组元素的值任意整形数,无序; 

要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小

    当前数组a和数组b的和之差为
    A = sum(a) - sum(b)

    a的第i个元素和b的第j个元素交换后,a和b的和之差为
    A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
           = sum(a) - sum(b) - 2 (a[i] - b[j])
           = A - 2 (a[i] - b[j])
    设x = a[i] - b[j]

    |A| - |A'| = |A| - |A-2x|

    假设A > 0,

    当x 在 (0,A)之间时,做这样的交换才能使得交换后的a和b的和之差变小,x越接近A/2效果越好,

    如果找不到在(0,A)之间的x,则当前的a和b就是答案。

    所以算法大概如下:

    在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。

 1 int sum1,sum2,a;          // 分别表示 a[]的和 b[]的和 以及2者之差
 2     int temp;     
 3     bool dayu0;                  // 和之差是否大于0
 4     int pos1,pos2;               // 等待交换的a[i]和b[j]的下标 i j
 5     float minn;                // 最接近a/2的a[i]-b[j]值
 6     bool have1 ;               // 是否能有解
 7     while (1)
 8     {
 9         sum1 = 0;
10         sum2 = 0;
11         for (int i = 0 ; i < n;++i)             // 求两个数组的和
12         {
13             sum1 += ar1[i];
14             sum2 += ar2[i];
15         }
16         a = sum1 - sum2;                    // 和之差
17         dayu0 = a>0?true:false;                  // 和之差是大于0还是小于0
18         have1 = false;                           // 是否能找到解
19         for (int i = 0 ; i < n;++i)            // 找最接近a/2的 a[i]-b[j]
20         {
21             for (int j = 0;j < n;++j)
22             {
23                 temp = ar1[i] - ar2[j];
24                 if ((dayu0&&temp > 0&&temp < a)||(!dayu0&&temp < 0 && temp > a))      // 如果a[i]-b[j] 在(0,a)之间  (超出的就没有意义了)   
25                 {
26                     if (have1&&abs(temp - a/2.0) < minn)                 // 若比之前的a[i]-b[j]更接近a/2 则更新
27                     {
28                         minn = abs(temp - a/2.0);
29                         pos1 = i;
30                         pos2 = j;
31                     }
32                     else                                               
33                     {
34                         have1 = true;
35                         minn = abs(temp - a/2.0);
36                         pos1 = i;
37                         pos2 = j;
38                     }
39                 }
40             }
41         }
42         if (!have1)         // 若找不到符合条件的a[i]-b[j]了 则结束
43         {
44             break;
45         }
46         swap(ar1[pos1],ar2[pos2]);       // 交换a b中的元素
47     }

-----------------------------------------------未完待续-----------------------------------------------

提示:1、代码由本人手打如有失误请麻烦提醒下,我将及时改正

            2、注释代表个人理解有歧义请指教,谢谢

原文地址:https://www.cnblogs.com/melodyzhy/p/4659963.html