zoukankan      html  css  js  c++  java
  • 北航软工项目作业(一)

    博客三

    项目 内容
    这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健)
    这个作业的要求在哪里 第一次项目作业
    我在这个课程的目标 不求变强,只求做好,成为一颗有用的螺丝钉。
    这个作业在哪个具体方面帮助我实现目标 使用单元测试以及性能分析工具
    参考资料
    教学班级 005
    项目地址 链接

    PSP

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 5 5
    · Estimate · 估计这个任务需要多少时间 5 0
    Development 开发 345 690
    · Analysis · 需求分析 (包括学习新技术) 0 180
    · Design Spec · 生成设计文档 0 0
    · Design Review · 设计复审 (和同事审核设计文档) 0 0
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 0 0
    · Design · 具体设计 15 60
    · Coding · 具体编码 30 30
    · Code Review · 代码复审 120 120
    · Test · 测试(自我测试,修改代码,提交修改) 180 300
    Reporting 报告 60 45
    · Test Report · 测试报告 25 10
    · Size Measurement · 计算工作量 15 15
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 20 20
    合计 450 775

    思路描述

    考虑最暴力的方法,两两直线求交点,那么时间复杂度是$O(n^2)$,这个时间复杂度肯定是不可以接受的。

    那么有更好的办法吗?除了如果不存在平行和三线共点,那么交点数应该是$n(n-1)/2$。如果新增的一条线与$x$条直线平行,那么会少$x$个交点;如果新增的一条直线与l另外$x(x>2)$条直线共点,那么会少$x$个交点。欲求得平行条件不难,时间复杂度为$O(1)$;欲求共点条件还是会用上遍历,这里的时间开销又回到了$O(n^2)$。

    所以,我放弃了,规规矩矩地使用暴力方法,选择了两点式求直线交点,再去百度上找轮子。

    设计实现过程

    大体的思路是先计算,再把计算结果保存在集合中,由于集合不存在重复的元素,所以对于本次作业来说是一个比较好的数据结构,需要重写比较函数。

    相比于求取斜率的截距式,两点式更加安全,但是计算效率会更低(截距式2个参数,两点式4个参数)。

    首先就是构造Dot类和重写比较函数。然后构造一个 set<Dots, DotsCmp>类。

    计算交点的函数的介绍放在关键代码部分。

    再将这些函数封装起来。

    Dots类:

    class Dots {
    public:
        double DotX;
        double DotY;
        Dots() {
            DotX = 0;
            DotY = 0;
        }
        Dots(double X, double Y) {
            DotX = X;
            DotY = Y;
        }
    };
    

    重写比较函数:

    class DotsCmp {
    public:
        bool operator()(const Dots& dotA, const Dots& dotB) const {
            if (dotA.DotX == dotB.DotX) {
                return (dotA.DotY < dotB.DotY);
            }
            else {
                return (dotA.DotX < dotB.DotX);
            }
        }
    };
    

    计算结果的类:

    class CalDots {
    private:
        DotsSet _set;//交点集合
    public:
        CalDots();
        Dots CalDot(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);//计算两直线交点
        int DotsSize();//返回总交点数
    };
    

    单元测试1——CalDot()函数的正确性

    TEST_METHOD(TestCalDot)
    		{
    			CalDots*cald = new CalDots();
    			int x0 = 0;
    			int y0 = 0;
    			int x1 = 1;
    			int y1 = 1;
    			int x2 = 0;
    			int y2 = 0;
    			int x3 = 0;
    			int y3 = 0;
    			double dotx = 0;
    			double doty = 0;
    			Assert::AreEqual(dotx, cald->CalDot(x0, y0, x1, y1, x2, y2, x3, y3).DotX);
    			Assert::AreEqual(doty, cald->CalDot(x0, y0, x1, y1, x2, y2, x3, y3).DotY);
    		}
    

    单元测试2——时间

    TEST_METHOD(TestTime)
    		{
    			srand(time(NULL));
    			long t = clock();
    			CalDots* cald = new CalDots();
    			int Dot[5000][4];
    			int i, j;
    			for (i = 0; i < 5000; i++) {
    				Dot[i][0] = rand() % 1000;
    				Dot[i][1] = rand() % 1000;
    				Dot[i][2] = rand() % 1000;
    				Dot[i][3] = rand() % 1000;
    			}
    
    			for (i = 0; i < 5000; i++) {
    				for (j = i + 1; j < 4999; j++) {
    					cald->CalDot(Dot[i][0], Dot[i][1], Dot[i][2], Dot[i][3], Dot[j][0], Dot[j][1], Dot[j][2], Dot[j][3]);
    				}
    			}
    			Assert::IsTrue(clock() - t < 60000);
    		}
    

    实测5000条直线耗时54秒,效率很低,大部分用在set排序上。

    时间记录及改进思路

    耗时最大的函数是CalDot()函数(关键代码部分),即计算两直线交点的函数;而其中耗时最多的是将计算得到的点插入set集合中。这一工作是内置函数完成的,暂时想不到改进策略。可以改善的是简化计算步骤,将两点式转换为截距式,但截距式存在k不存在的情况,不仅会增加程序的错误处理,而且对速度提升不大。

    关键代码

    Dots CalDots::CalDot(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
        double k1, k2;
        if (x0 != x1) {
            k1 = (y0 - y1) / (x0 - x1);//if x0 == x1  k1 do not exist
            if (x2 != x3) {
                k2 = (y2 - y3) / (x2 - x3);
                if (k1 != k2) {
                    DotX = (k1 * x0 - k2 * x2 + y2 - y0) / (k1 - k2);
                    DotY = y0 + (DotX - x0) * k1;
                    _set.insert(Dots(DotX, DotY));
                    return Dots(DotX, DotY);
                }
                //else paralle
            }
            else {
                DotX = x2;
                DotY = y0 + ((double)x2 - (double)x0) * k1;
                _set.insert(Dots(DotX, DotY));
                return Dots(DotX, DotY);
            }
        }
        else {
            if (x2 != x3) {
                k2 = (y2 - y3) / (x2 - x3);//k2 exists
                DotX = x0;
                DotY = y2 + ((double)x0 - (double)x2) * k2;
                _set.insert(Dots(DotX, DotY));
                return Dots(DotX, DotY);
            }
            //else paralle
        }
        return Dots(DotX, DotY);
    }
    
  • 相关阅读:
    258. Add Digits 数位相加到只剩一位数
    7. Reverse Integer 反转整数
    9. Palindrome Number 回文数的判断
    824. Goat Latin山羊拉丁文
    819. Most Common Word 统计高频词(暂未被禁止)
    Angular 2 模板语法
    HTML DOM Style opacity 属性
    Basic concepts (C language) – C 中文开发手册
    JavaScript手册 | JS Array 对象中的fill()方法
    HTML <form> 标签
  • 原文地址:https://www.cnblogs.com/buaayzx/p/12456449.html
Copyright © 2011-2022 走看看