zoukankan      html  css  js  c++  java
  • 2021.1.5 算法实训

    这两天进行了学校安排的算法实训,总的感觉就是对算法的复习和具体项目的练习。

    一、什么是算法

    1.算法:

    算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制(百度解释)

    2.程序等于算法加数据结构

    3.算法的优劣一般使用空间复杂度和时间复杂度来计算

    空间复杂度:算法当中使用到的内存空间大小

    空间复杂度的计算:一般直接判断使用的数据结构是什么,大小用数学模型来表示,比如使用了一个数组,则为n,使用了二维数组则为n2

    时间复杂度:算法运算过程中所花费的时间,时间复杂度一般使用公式来表达,比如O(n2)和O(logn),时间复杂度的数学图像越陡,斜率越高,说明时间复杂度越高。越平缓,则时间复杂度较低。

    二、常见的算法有哪些

    1.蛮力法

    A.蛮力排序算法——使用最直接的遍历,循环等方式解决问题,即正向思维暴力破解

    蛮力法的经典体现——冒泡排序,此时可以利用冒泡排序的例子进行算法的讲解

    2.迭代

    A.斐波拉契的迭代算法——迭代的含义为:当前算式的结果将成为下一次算式的输入,即数据不断的更迭代替,最终得到结果。迭代的难点在于如何停止。

    3.递归

    斐波拉切的递归算法结合其数学表达式比较好解释![img](file:///C:/Users/23857/AppData/Local/Temp/msohtmlclip1/01/clip_image003.gif)该表达式表达的即为当前的结果等于前两次计算结果的和

    4.分治法

    A.查找算法-二分查找

    二分查找法分治法中的经典算法,算法思想:在已排好序的数列中(假设升序)

    1. 利于对半分的思想将当前数列分为两个部分

    2. 比较目标数字与中位数的大小,如果目标大,则舍弃左半部分,如果目标小则舍弃右半部分,并将剩下的另一部分作为当前数列

    3. 重复1,2直到找到目标数字或者找不到返回空。

    B.排序算法-归并排序

    归并排序算法是排序算法中较难的一种,主要运用了两种算法,分治法和递归。基本思想:归并,即将问题化为最小的单元来解决后再合并,对应在排序算法中就是——一次排序多个较为复杂则将问题化为两个数字排序,即将数列变为多个成对数字比较后合并为一个大的数列。

    5.动态规划

    A.寻找最佳子序列

    算法含义:动态规划和分治法的基本含义相同,不同点在于动态规划中每一个分部都是独立解决某一个问题。比如要解决1 +……+100,1加到100,分步骤解法就是先1+2再加3在加4,每一步都可以独立存在。

    6.贪心算法——找到局部最优解

    A.局部最优解

    算法含义:在某些算法或业务要求中,需要的是根据当前所得到的信息去寻找当前认为最优的解,它不一定是最值点,但是一定是极值点。

    三、项目案例讲解

    1.贪心法求解最佳分票数

    代码

    #include <iostream>
    using namespace std;
    
    // 一张发票最多只能开 100块
    
    int piao(int a[], int n) {
    	//发票数量
    	int sum = 0;
    	//余数 数组
    	int* ys = new int[n];
    
    	for (int i = 0; i < n; i++) {
    		sum += a[i] / 100;
    		ys[i] = a[i] % 100;
    	}
    
    	// 贪心
    	for (int i = 0; i < n-1; i++) {
    		int t = ys[i] + ys[i + 1];
    		if (t > 100) {
    			sum++;
    			ys[i] = 0;
    		}
    		else {
    			ys[i+1] = t;
    		}
    	}
    
    	//判断最后一次的余数和
    	if (ys[n - 1] > 0)
    		sum++;
    
    	return sum;
    }
    
    int main() {
    	// 报销金额
    	const int n = 5;
    	int m[n] = {960,105,99,101,806};
    	cout << "总发票数为:" << piao(m, n) << endl;
    
    	return 0;
    }
    

    2.文本相识度匹配

    1.参考资料:

    https://www.cnblogs.com/dogecheng/p/11470196.html

    https://zhuanlan.zhihu.com/p/33164335

    http://www.ruanyifeng.com/blog/2013/03/cosine_similarity.html (很详细)

    2.流程思路

    image-20210105190506480

    3.非常详细的代码

    #include <iostream>
    #include <cmath>
    #include <string>
    using namespace std;
    
    //字符串转单词数组
    int toSrtArry(string a, string* StrA) {
        //字符串数组长度 单词数量
        int len = 0;
        //原文本字符串 下标
        int index = 0;
        //临时 单词字符串
        string temp_word;
    
        //遍历整个文本字符串
        while (a[index] != '') {
            //当前字符的 ASCII码
            int int_c1 = (int)a[index];
            //判断当前字符是否为字母
            if ((int_c1 >= 97 && int_c1 <= 122) || (int_c1 >= 65 && int_c1 <= 90)) {
                //将字母添加至临时字符串 做单词
                temp_word.push_back(a[index]);
            }
            //一个单词结束
            else if (temp_word != "") {
                //将单词加入 单词数组
                StrA[len] = temp_word;
                len++;
    
                //清空单词串
                temp_word = "";
            }
            //下标++
            index++;
        }
    
        //返回单词数
        return len;
    }
    
    //计算词袋
    int toModdle(string a, string b, string* moddle) {
        int len = 0;
        //字符串数组 保存 单词
        string* StrA1 = new string[sizeof(string)];
        string* StrA2 = new string[sizeof(string)];
        //调用 toSrtArry 函数 返回单词数
        int len1 = toSrtArry(a, StrA1);
        int len2 = toSrtArry(b, StrA2);
    
        //遍历单词数组 形成词袋
        int i = 0;
        for (; i < len1; i++) {
            int j = 0;
            for (; j < len; j++) {
                if (moddle[j] == StrA1[i]) {
                    break;
                }
            }
            if (j == len)
                moddle[len++] = StrA1[i];
        }
    
        i = 0;
        for (; i < len2; i++) {
            int j = 0;
            for (; j < len; j++) {
                if (moddle[j] == StrA2[i]) {
                    break;
                }
            }
            if (j == len)
                moddle[len++] = StrA2[i];
        }
    
        return len;
    }
    
    //计算余弦相似度
    double cosin(int a[], int b[], int n) {
    
        double divisor1 = 0; //除数
        double divisor2 = 0; //除数
        double dividend = 0; //被除数
    
        for (int i = 0; i < n; i++) {
            dividend += (a[i] * b[i]);
    
            divisor1 += (a[i] * a[i]);
            divisor2 += (b[i] * b[i]);
        }
    
        double d1 = sqrt(divisor1);
        double d2 = sqrt(divisor2);
    
        return dividend / (d1 * d2);
    }
    
    //相似度函数
    double xsd(string a, string b, string* moddle, int len) {
        //向量
        int* t1 = new int[len];
        int* t2 = new int[len];
        //单词数组
        string* text1 = new string[sizeof(string)];
        string* text2 = new string[sizeof(string)];
        //单词数
        int len1 = toSrtArry(a, text1);
        int len2 = toSrtArry(b, text2);
    
        //遍历词袋 计算向量
        for (int i = 0; i < len; i++) {
            //向量初始化
            t1[i] = 0;
            t2[i] = 0;
    
            //遍历单词数组
            for (int j = 0; j < len1; j++) {
                if (moddle[i] == text1[j])
                    t1[i]++;
            }
            for (int k = 0; k < len2; k++) {
                if (moddle[i] == text2[k])
                    t2[i]++;
            }
        }
    
        //输出向量
        //for(int i = 0; i < len; i++) {
        //    cout << t1[i] << ends;
        //}
        //cout << endl;
        //for(int i = 0; i < len; i++) {
        //    cout << t2[i] << ends;
        //} 
        //cout << endl;
    
        //调用余弦函数,返回相似度
        return cosin(t1, t2, len);
    }
    
    
    int main() {
        //模板字符串数组
        string* moddle = new string[sizeof(string)];
    
        string text1 = "John likes to watch movies. Mary likes too.";
        string text2 = "John also likes to watch football games.";
        cout << "文本1:" << text1 << endl;
        cout << "文本2:" << text2 << endl;
        cout << "余弦相似度:" << xsd(text1, text2, moddle, toModdle(text1, text2, moddle)) << endl;
    
        return 0;
    }
    

  • 相关阅读:
    C++ 类 构造函数 constructor
    数据库——关系代数
    海明码
    C++ this指针
    C++ 类的定义与实现
    C++ 函数 内联函数
    C++ 函数 函数的重载 有默认参数的函数
    2017年第八届蓝桥杯【C++省赛B组】
    2018年第九届蓝桥杯【C++省赛B组】
    C++ 函数 参数传递方式
  • 原文地址:https://www.cnblogs.com/Liwker/p/14237574.html
Copyright © 2011-2022 走看看