算法分析工具

10 篇文章 0 订阅

算法分析工具可以用于观察数组的变化,变量的计算过程,能够辅助分析排序算法,STL算法,数值算法等

源码下载地址: http://pan.baidu.com/s/1kT9smSf

最后给出了使用手册,并不完整, 具体的细节可以参照源文件中的 "gt.h", “GuardConfig.h”, "manual.hpp" 


关于数值计算

#include "gt.h"

int main(void)
{
    AddId("id_Pi")("id_r");     // 为后面的变量命名用于跟踪输出到控制台,函数后面可以添加任意个参数
    Double Pi = 3.1415926, r;
    r = 4.1;
    
    AddId("id_perimeter")("id_area");   // 为后面的变量命名用于跟踪输出到控制台
    Double perimeter, area;
    perimeter = 2 * Pi * r;
    area = Pi * pow(r, 2);
    return 0;
}

控制台自动输出

				EXPRES:id_Pi = 3.141593
				EXPRES:id_r = 4.1
				EXPRES:id_perimeter = (2*3.141593)*4.1
				EXPRES:id_area = 3.141593*pow(4.1, 2)


希尔排序代码

#include "gt.h"

const unsigned int N = 4;                       // 下面数组的长度
const unsigned int SellNum[N] = {7, 3, 1};  // 最后一个数值必须是 1

void ShellSort(IntPtr arr, int length) {
    for(int n=0; n<N; n++) {
        int increase=SellNum[n];
        for(int i=0; i<increase; i++) {
            for(int j=i+increase; j<length; j+=increase) {
                for(int k=j; arr[k-increase]>arr[k]; k-=increase) {
                    int temp = arr[k];
                    arr[k] = arr[k-increase];
                    arr[k-increase] = temp;
                    if(k-2*increase < 0)break;
                }
            }
        }
    }
}

int main(void)
{
    int a[] = {3, 1, 3, 63, 11,2, 5,23, 51};
    IntArr arr(a);
    ShellSort(arr, 9);
    for(int i=0; i<9; i++) {
        printf("%d  ", arr[i]);
    }
    return 0;
}

希尔排序对应控制台的输出

				EXPRES:GT[6] = GT[3]
  3   1   3   63   11   2  [63]  23   51 

				EXPRES:GT[3] = 5
  3   1   3  [5]  11   2   63   23   51 

				EXPRES:GT[5] = GT[2]
  3   1   3   5   11  [3]  63   23   51 

				EXPRES:GT[2] = 2
  3   1  [2]  5   11   3   63   23   51 

				EXPRES:GT[1] = GT[0]
  3  [3]  2   5   11   3   63   23   51 

				EXPRES:GT[0] = 1
 [1]  3   2   5   11   3   63   23   51 

				EXPRES:GT[2] = GT[0]
  1   3  [3]  5   11   3   63   23   51 

				EXPRES:GT[1] = 2
  1  [2]  3   5   11   3   63   23   51 

				EXPRES:GT[5] = GT[4]
  1   2   3   5   11  [11]  63   23   51 

				EXPRES:GT[4] = 3
  1   2   3   5  [3]  11   63   23   51 

				EXPRES:GT[4] = 5
  1   2   3   5  [5]  11   63   23   51 

				EXPRES:GT[3] = 3
  1   2   3  [3]  5   11   63   23   51 

				EXPRES:GT[7] = GT[3]
  1   2   3   3   5   11   63  [63]  51 

				EXPRES:GT[6] = 23
  1   2   3   3   5   11  [23]  63   51 

				EXPRES:GT[8] = GT[3]
  1   2   3   3   5   11   23   63  [63]

				EXPRES:GT[7] = 51
  1   2   3   3   5   11   23  [51]  63 


程序具有许多的可配置项,可以观察各种效果

在 main 添加上一句  

TurnTrace(ON);

之后的希尔排序输出效果

				TRACE: GT[0] > GT[7] = 0
				TRACE: GT[1] > GT[8] = 0
				TRACE: GT[0] > GT[3] = 0
				TRACE: GT[3] > GT[6] = 1
				EXPRES:GT[6] = GT[3]
  3   1   3   63   11   2  [63]  23   51 

				TRACE: GT[3] = 5
				EXPRES:GT[3] = 5
  3   1   3  [5]  11   2   63   23   51 

				TRACE: GT[0] > GT[3] = 0
				TRACE: GT[1] > GT[4] = 0
				TRACE: GT[4] > GT[7] = 0
				TRACE: GT[2] > GT[5] = 1
				EXPRES:GT[5] = GT[2]
  3   1   3   5   11  [3]  63   23   51 

				TRACE: GT[2] = 2
				EXPRES:GT[2] = 2
  3   1  [2]  5   11   3   63   23   51 

				TRACE: GT[5] > GT[8] = 0
				TRACE: GT[0] > GT[1] = 1
				EXPRES:GT[1] = GT[0]
  3  [3]  2   5   11   3   63   23   51 

				TRACE: GT[0] = 1
				EXPRES:GT[0] = 1
 [1]  3   2   5   11   3   63   23   51 

				TRACE: GT[1] > GT[2] = 1
				EXPRES:GT[2] = GT[0]
  1   3  [3]  5   11   3   63   23   51 

				TRACE: GT[1] = 2
				EXPRES:GT[1] = 2
  1  [2]  3   5   11   3   63   23   51 

				TRACE: GT[0] > GT[1] = 0
				TRACE: GT[2] > GT[3] = 0
				TRACE: GT[3] > GT[4] = 0
				TRACE: GT[4] > GT[5] = 1
				EXPRES:GT[5] = GT[4]
  1   2   3   5   11  [11]  63   23   51 

				TRACE: GT[4] = 3
				EXPRES:GT[4] = 3
  1   2   3   5  [3]  11   63   23   51 

				TRACE: GT[3] > GT[4] = 1
				EXPRES:GT[4] = 5
  1   2   3   5  [5]  11   63   23   51 

				TRACE: GT[3] = 3
				EXPRES:GT[3] = 3
  1   2   3  [3]  5   11   63   23   51 

				TRACE: GT[2] > GT[3] = 0
				TRACE: GT[5] > GT[6] = 0
				TRACE: GT[6] > GT[7] = 1
				EXPRES:GT[7] = GT[3]
  1   2   3   3   5   11   63  [63]  51 

				TRACE: GT[6] = 23
				EXPRES:GT[6] = 23
  1   2   3   3   5   11  [23]  63   51 

				TRACE: GT[5] > GT[6] = 0
				TRACE: GT[7] > GT[8] = 1
				EXPRES:GT[8] = GT[3]
  1   2   3   3   5   11   23   63  [63]

				TRACE: GT[7] = 51
				EXPRES:GT[7] = 51
  1   2   3   3   5   11   23  [51]  63 

				TRACE: GT[6] > GT[7] = 0
1  2  3  3  5  11  23  51  63


使用手册

#ifndef MANUAL_HPP
#define MANUAL_HPP
#include <numeric>
#include "gt.h"
using namespace std;

/**
 * @brief 算法分析器使用方法
 *
 * 1.将文件解压到工作目录 并在工作文件中 #include "gt.h"
 *
 * 2.修改对应的变量定义 例如: int i; 改成 Int i;
 *
 * 示例如下程序
 *
 * @return
 */



// 函数传递数组的三种方式
// 方式一通过指针传递 IntPtr p 类似于 int * p;
void func(IntPtr p) {
    for(int i=0; i<3; i++)
        p[i] = i;
}

// 通过 C++ 引用传递数组
void func2(IntArr& arr) { // 注意这里的 “&”
    // 这里数组的改变将会被传递到函数外部,就好像是在使用数组指针
    arr[1] = 1;
}


int manual() {
    //------------------常用示例----------------------
    
    Int i("i");                 // 将 int型变量 i 命名为 “i” 用于跟踪输出到控制台
    IntArr a1(5, "a1");         // 定义 int 型一维数组 a1 长度为5 并命名为 “a1” 用于跟踪输出到控制台
    IntArr2 a2(2, 3, "a2");     // 定义 int 型二维数组 a2 第一维长度为2 第二维长度为3  并命名为 “a2” 用于跟踪输出到控制台
    IntArr3 a3(2, 3, 4, "a3");  // 定义 int 型三维数组 a3 第一维长度为2 第二维长度为3 第三维长度为4  并命名为 “a3” 用于跟踪输出到控制台
    // 除了 Int 之外 GT.h 中还定义了 Char, Short, Double, LongDouble, String 等类型 和 对应的数组类型 可以直接用来使用
    
    AddId("id_Pi")("id_r");     // 为后面的变量命名用于跟踪输出到控制台,函数后面可以添加任意个参数
    Double Pi = 3.1415926, r;
    r = 4.1;
    
    AddId("id_perimeter")("id_area");   // 为后面的变量命名用于跟踪输出到控制台
    Double perimeter, area;
    perimeter = 2 * Pi * r;
    area = Pi * pow(r, 2);
    
    a1[i]++;
    a2[1][2] *= i;
    a3[1][2][3] <= i;

    a3[1][1][1] = 1;
    for(int i=0; i<5; i++) {
        a1[i] = 5-i;
    }

    //printf("int = %d\n 请输入下一个数值\n", i);
    //scanf("%d", &i);

    
    int ax[] = {1, 2, 3, 4, 5};
    IntArr arr1(ax);            // 构造一个一维数组 arr1 并且把 ax 全部元素复制到 arr
    
    ax[1] = 1;                  // 这里不会改变 ax 的值
    int ax2[2][2] = {
        {1, 2},
        {3, 4}};
    IntArr2 arr2(ax2);          // 构造一个2*2二维数组 arr2 并且把 ax2 全部元素复制到 arr2
    
    
    
    // ------------------指针的用法-----------------------

    IntPtr p = a1;              // 定义 p 为 int 型指针(类似于 int * p;) 并将数组首地址复制给指针
    *(p+1) = 9;                 // 等价于 a1[1] = 9;
    IntPtr2 p2 = a2;            // 定义 p2 为 int 型二级指针(类似于 int ** p;) 并将二维数组首地址复制给指针
    **p2 = 9;                   // 等价于 a2[0][0] = 9;

    

    // ------------------C++ 相关------------------------

    //GuardConfig::TurnAllGuardOff();             // 关闭所有跟踪

    //GuardConfig::rule["="] = true;              // 开启 “=” 跟踪,其他符号类似

    //GuardConfig::TurnArrayOutPutSwitch(true);   // 数组元素变化时,输出整个数组
    
    TurnTrace(ON);              // 将 TRACE 输出到控制台
    TurnExpres(ON);             // 将 EXPRES 输出到控制台
    
    Double j = 3;
    j.SetName("j");

    cout << a1;                                 // 输出方式 1

    for(size_t i=0; i<a1.size(); i++) {
        cout << a1[i] << " ";                   // 输出方式 2
    } cout << endl;

    for(IntArr::iterator iter=a1.begin(); iter != a1.end(); iter++) {
        cout << *iter << " ";                   // 输出方式 3
    } cout << endl;

    copy(a1.begin(), a1.end(), ostream_iterator<IntArr::value_type>(cout, " "));// 输出方式 4

    // 排序
    std::sort(a1.begin(), a1.end());
    
    // 以 0 为初始值 计算累加和
    Int result = accumulate(a1.begin(), a1.end(), 0);
    cout << "accumulate result: " << result << endl;



    // ------------------适配自己需要的跟踪类型-------------------

    // 用 MyInt 类型定义数据, 实际操作的数据类型为 int
    // 并且 自动生成了 一维数组 MyIntArr, 二维数组 MyIntArr2, 三维数组 MyIntArr3
    GT_TYPE(int, MyInt);


    // 自定义 GT跟踪类型 需要的构造函数
    class GT : public Double {
    public :
        GT(const std::string& id = "") : Double(id){ }
        const GT& operator = (const double& data) {
            (Double&)*this = data;
            return *this;
        }
    };

    // 自定义 Vec跟踪类型 需要的构造函数
    class Vec : public DoubleArr {
    public :
        Vec(size_t length, const std::string& id = "") :
            DoubleArr(length, id){ }
    };

    // 自定义 Mat跟踪类型 需要的构造函数
    class Mat : public DoubleArr2 {
    public :
        Mat(size_t m, size_t n, const std::string& id = "") :
            DoubleArr2(m, n, id){ }
    };

    // 自定义 Mat3d跟踪类型 需要的构造函数
    class Mat3d : public DoubleArr3 {
    public :
        Mat3d(size_t m, size_t n, size_t k, const std::string& id = "") :
            DoubleArr3(m, n, k, id){ }
    };
    
    return 0;
}

#endif // MANUAL_HPP


专题十:算法分析与设计 1.常用的算法设计方法:   1.1 迭代法   1.2 穷举搜索法   1.3 递推法   1.4 递归法   1.5 贪婪法   1.6 分治法   1.7 动态规划法   1.8 回溯法 算法基础部分: 算法是对特定问题求解步骤的一种描述,算法是指令的有限序列,其中每一条指令表示一个或多个操作。 算法具有以下5个属性:   有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。   确定性:算法中每一条指令必须有确切的含义。不存在二义性。只有一个入口和一个出口   可行性:一个算法是可行的就是算法描述的操作是可以通过已经实现的基本运算执行有限次来实现的。   输入:一个算法有零个或多个输入,这些输入取自于某个特定对象的集合。   输出:一个算法有一个或多个输出,这些输出同输入有着某些特定关系的量。 所以对应的算法设计的要求:   正确性:算法应满足具体问题的需求;   可读性:算法应该好读,以有利于读者对程序的理解;   健壮性:算法应具有容错处理,当输入为非法数据时,算法应对其作出反应,而不是产生莫名其妙的输出结果。   效率与存储量需求:效率指的是算法执行的时间;存储量需求指算法执行过程中所需要的最大存储空间。一般这两者与问题的规模有关。 1.1 迭代法: 迭代法是用于求方程或方程组近似根的一种常用的算法设计方法。设方程为f(x)=0,用某种数学方法导出等价的形式x=g(x),然后按以下步骤执行: (1)选一个方程的近似根,赋给变量x0; (2)将x0的值保存于变量x1,然后计算g(x1),并将结果存于变量x0; (3)当x0与x1的差的绝对值还小于指定的精度要求时,重复步骤(2)的计算。 若方程有根,并且用上述方法计算出来的近似根序列收敛,则按上述方法求得的x0就认为是方程的根。上述算法用C程序的形式表示为: 【算法】迭代法求方程的根 { x0=初始近似根; do { x1=x0; x0=g(x1); /*按特定的方程计算新的近似根*/ } while ( fabs(x0-x1)>Epsilon); printf(“方程的近似根是%f\n”,x0); } 迭代算法也常用于求方程组的根,令 X=(x0,x1,…,xn-1) 设方程组为: xi=gi(X) (I=0,1,…,n-1) 则求方程组根的迭代算法可描述如下: 【算法】迭代法求方程组的根 { for (i=0;i<n;i++) x[i]=初始近似根; do { for (i=0;i<n;i++) y[i]=x[i]; for (i=0;i<n;i++) x[i]=gi(X); for (delta=0.0,i=0;i<n;i++) if (fabs(y[i]-x[i])>delta) delta=fabs(y[i]-x[i]); } while (delta>Epsilon); for (i=0;i<n;i++) printf(“变量x[%d]的近似根是 %f”,I,x[i]); printf(“\n”); } 具体使用迭代法求根时应注意以下两种可能发生的情况: (1)如果方程无解,算法求出的近似根序列就不会收敛,迭代过程会变成死循环,因此在使用迭代算法前应先考察方程是否有解,并在程序中对迭代的次数给予限制; (2)方程虽然有解,但迭代公式选择不当,或迭代的初始近似根选择不合理,也会导致迭代失败。 1.2 穷举搜索法: 穷举搜索法是对可能是解的众多候选解按某种顺序进行逐一枚举和检验,并从中找出那些符合要求的候选解作为问题的解。 要解决的问题只有有限种可能,在没有更好算法时总可以用穷举搜索的办法解决,即逐个的检查所有可能的情况。可以想象,情况较多时这种方法极为费时。实际上并不需要机械的检查每一种情况,常常是可以提前判断出某些情况不可能取到最优解,从而可以提前舍弃这些情况。这样也是隐含的检查了所有可能的情况,既减少了搜索量,又保证了不漏掉最优解。 【问题】 将A、B、C、D、E、F这六个变量排成如图所示的三角形,这六个变量分别取[1,6]上的整数,且均不相同。求使三角形三条边上的变量之和相等的全部解。如图就是一个解。 程序引入变量a、b、c、d、e、f,并让它们分别顺序取1至6的整数,在它们互不相同的条件下,测试由它们排成的如图所示的三角形三条边上的变量之和是否相等,如相等即为一种满足要求的排列,把它们输出。当这些变量取尽所有的组合后,程序就可得到全部可能的解。细节见下面的程序。 # include <stdio.h> void main() { int a,b,c,d,e,f; for (a=1;a<=6;a++) //a,b,c,d,e依次取不同的值 for (b=1;b<=6;b++) { if (b==a) continue; for (c=1;c<=6;c++) { if (c==a)||(c==b) continue; for (d=1;d<=6;d++) { if (d==a)||(d==b)||(d==c) continue; for (e=1;e<=6;e++) { if (e==a)||(e==b)||(e==c)||(e==d) continue; f=21-(a+b+c+d+e);//最后一个用减法算 if ((a+b+c==c+d+e))&&(a+b+c==e+f+a)) { printf(“%6d,a); printf(“%4d%4d”,b,f); printf(“%2d%4d%4d”,c,d,e); scanf(“%c”); } } } } } }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值