zoukankan      html  css  js  c++  java
  • 基于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、注释代表个人理解有歧义请指教,谢谢

  • 相关阅读:
    golang1.8
    用jmeter测试mogonDd数据库
    Memcache课程
    appium 处理滑动的方法
    【MVC 2】MVC+EF框架结构实例:注册ID号验证
    【Ajax 3】JavaScript封装Ajax
    【Ajax 2】封装Ajax的核心对象:XMLHttpRequest对象
    【Ajax 1】Ajax与传统Web开发的区别
    【软工7】软件工程中的文档
    【软考10】计算机网络基础知识拾遗
  • 原文地址:https://www.cnblogs.com/melodyzhy/p/4659963.html
Copyright © 2011-2022 走看看