北航軟工項目作業(一)


博客三

項目 內容
這個作業屬於哪個課程 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);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM