axure通用元件庫 Pc、Web端原型圖組件庫高保真UI rp源文件
時間:2023-07-23 11:12:01 | 來源:網(wǎng)站運(yùn)營
時間:2023-07-23 11:12:01 來源:網(wǎng)站運(yùn)營
axure通用元件庫 Pc、Web端原型圖組件庫高保真UI rp源文件:【實(shí)例簡介】axure通用元件庫 Pc、Web端原型圖組件庫高保真UI rp源文件
文件:
590m.com/f/25127180-487470652-fb6c16(訪問密碼:551685)
【實(shí)例截圖】
以下內(nèi)容無關(guān):
-------------------------------------------分割線---------------------------------------------
一.算法效率
算法效率分析分為兩種:
1.時間效率
時間效率又叫做時間復(fù)雜度,它衡量的主要是一個算法的運(yùn)行速度。
2.空間效率
空間效率又叫做空間復(fù)雜度,它衡量的主要是一個算法所需要的額外空間。在計算機(jī)發(fā)展的早期,因?yàn)榭萍妓接邢蓿嬎銠C(jī)的容量很少,但如今科技急速發(fā)展,計算機(jī)的存儲容量已經(jīng)達(dá)到了很高的程度。所以我們?nèi)缃褚呀?jīng)不需要再特別關(guān)注一個算法的空間復(fù)雜度。
二.時間復(fù)雜度
1.概念
在計算機(jī)科學(xué)中,算法的時間復(fù)雜度是一個函數(shù),它定量描述了該算法的運(yùn)行時間。一 個算法執(zhí)行所耗費(fèi)的時間,從理論上說,是不能算出來的,只有你把你的程序放在機(jī)器上跑起來,才能知道。但是我們需要每個算法都上機(jī)測試嗎?是可以都上機(jī)測試,但是同一個算法在不同性能的機(jī)器上也會有不同的差異,所以才有了時間復(fù)雜度這個分析方式。
因一個算法所花費(fèi)的時間與其中語句的執(zhí)行次數(shù)成正比例,所以,算法中的基本操作的執(zhí)行次數(shù),為算法的時間復(fù)雜度。
比如所如下代碼,它的執(zhí)行次數(shù)為多少呢?
復(fù)制代碼
#include <stdio.h>
void Func1(int N)
{
int count = 0;
for (int i = 0; i < N ; ++ i)
{
for (int j = 0; j < N ; ++ j)
{
++count;
}
}
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M–)
{
++count;
}
printf("%d/n", count);
}
復(fù)制代碼
顯而易見,它的執(zhí)行次數(shù)為 F=N
N+2N+10;
往往我們在計算時間復(fù)雜度的時候,我們寫的是一個概數(shù),為什么呢?
我們不妨設(shè)想一下,對于上面的執(zhí)行次數(shù)函數(shù),當(dāng)N趨向于無窮大時,那個10對于它的影響微乎其微。如果是一個高階函數(shù),這個函數(shù)的大小往往取決于表達(dá)式中次數(shù)最高的項(xiàng),所以我們的時間復(fù)雜度也采取這種思想。
我們不妨來測試一下:
復(fù)制代碼
#include <stdio.h>
#include <time.h>
void Func1(int N)
{
int start = clock();
int count = 0;
for (int i = 0; i < N ; ++ i)
{
for (int j = 0; j < N ; ++ j)
{
++count;
}
}
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M–)
{
++count;
}
int end = clock();
printf("%d/n", end - start);//單位為毫秒
}
int main()
{
Func1(0);//0
Func1(100);//0
Func1(10000);//386
return 0;
}
復(fù)制代碼
我們發(fā)現(xiàn),差異主要是在最高次上面。所以接下來我們來介紹大O的漸進(jìn)表示法。
2.大O的漸進(jìn)表示法
實(shí)際中我們計算時間復(fù)雜度時,我們其實(shí)并不一定要計算精確的執(zhí)行次數(shù),而只需要大概執(zhí)行次數(shù),那么這里我們使用大O的漸進(jìn)表示法。
大O符號(Big O notation):是用于描述函數(shù)漸進(jìn)行為的數(shù)學(xué)符號。
推導(dǎo)大O階方法:
1、用常數(shù)1取代運(yùn)行時間中的所有加法常數(shù)。
2、在修改后的運(yùn)行次數(shù)函數(shù)中,只保留最高階項(xiàng)。
3、如果最高階項(xiàng)存在且不是1,則去除與這個項(xiàng)目相乘的常數(shù)。得到的結(jié)果就是大O階。
所以,使用大O的漸進(jìn)表示法以后,F(xiàn)unc1的時間復(fù)雜度為:O(N^2);
通過上面,我們可以得到現(xiàn)大O的漸進(jìn)表示法去掉了那些對結(jié)果影響不大的項(xiàng),簡潔明了的表示出了執(zhí)行次數(shù)。
另外有些算法的時間復(fù)雜度存在最好、平均和最壞情況:
最壞情況:任意輸入規(guī)模的最大運(yùn)行次數(shù)(上界)
平均情況:任意輸入規(guī)模的期望運(yùn)行次數(shù)
最好情況:任意輸入規(guī)模的最小運(yùn)行次數(shù)(下界)
例如:
復(fù)制代碼
//描述:傳遞一個數(shù)組,給定一個數(shù),查找該數(shù)組中是否含有這個數(shù)
int FindNum(int* arr,int N,int search_num)
{
int i = 0;
for(i=0;i<len;i++)
{
if(search_num == arr[i])
return 1;//找到則返回 1
}
return 0;//找不到則返回 0
}
復(fù)制代碼
它的最好情況為 1 ,即只執(zhí)行一次就找到了
平均情況:N/2
最差情況: N ,遍歷了整個數(shù)組。
那么,對于這個算法,它的時間復(fù)雜度是多少呢?答案是: O(N)
在計算時間復(fù)雜度時,我們往往取得是它的最差情況。
3.示例
復(fù)制代碼
// 1.計算Func2的時間復(fù)雜度?
void Func2(int N)
{
int count = 0;
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M–)
{
++count;
}
printf("%d/n", count);
}
復(fù)制代碼
它的時間復(fù)雜度為多少呢? ---- O(N)
復(fù)制代碼
// 2.計算Func3的時間復(fù)雜度?
void Func3(int N, int M)
{
int count = 0;
for (int k = 0; k < M; ++ k)
{
++count;
}
for (int k = 0; k < N ; ++ k)
{
++count;
}
printf("%d/n", count);
}
復(fù)制代碼
答案是:O(N+M) ,因?yàn)樵谶@個式子中,我們并不知道M和N的大小情況,如果N>>M,那這題的時間復(fù)雜度就是O(N)
復(fù)制代碼
//3. 計算Func4的時間復(fù)雜度?
void Func4(int N)
{
int count = 0;
for (int k = 0; k < 100; ++ k)
{
++count;
}
printf("%d/n", count);
}
復(fù)制代碼
對于它,執(zhí)行次數(shù)為一個確定的常數(shù):100,所以它的時間復(fù)雜度為 O(1)
復(fù)制代碼
// 4.計算BubbleSort的時間復(fù)雜度?
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}
復(fù)制代碼
對于實(shí)例4基本操作執(zhí)行最好N次,最壞執(zhí)行了(N*(N+1)/2次,通過推導(dǎo)大O階方法+時間復(fù)雜度一般看最壞,所以時間復(fù)雜度為 O(N^2)
復(fù)制代碼
// 5.計算BinarySearch的時間復(fù)雜度?
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n-1;
while (begin < end)
{
int mid = begin + ((end-begin)>>1);
if (a[mid] < x)
begin = mid+1;
else if (a[mid] > x)
end = mid;
else
return mid;
}
return -1;
}
復(fù)制代碼
實(shí)例5基本操作執(zhí)行最好1次,最壞O(logN)次,時間復(fù)雜度為 O(logN)(我們可以通過折紙查找的方式理解logN是怎么計算出來的)
注:
logN在算法分析中表示是底數(shù)為2,對數(shù)為N。有些地方會寫成lgN。
// 6.計算階乘遞歸Factorial的時間復(fù)雜度?
long long Factorial(size_t N)
{
return N < 2 ? N : Factorial(N-1)*N;
}
對于遞歸的時間復(fù)雜度我們怎么算呢?
遞歸的時間復(fù)雜度 = 遞歸次數(shù)*每次遞歸中的次數(shù)
對于上題,一共遞歸了N次,每次遞歸中只有一次,所以時間復(fù)雜度為O(N)
//7. 計算斐波那契遞歸Fibonacci的時間復(fù)雜度?
long long Fibonacci(size_t N)
{
return N < 2 ? N : Fibonacci(N-1)+Fibonacci(N-2);
}
在這個例中,一共遞歸了N次,而在遞歸中的次數(shù)為2N-1,所以最后的時間復(fù)雜度為:O(N2)
注:
如果有一個遞歸有N層,且每一層中又有N次,那么它最后的時間復(fù)雜度為 O(N^2)
三.空間復(fù)雜度
1.概念
空間復(fù)雜度是對一個算法在運(yùn)行過程中臨時占用存儲空間大小的量度 。空間復(fù)雜度不是程序占用了多少 bytes的空間,因?yàn)檫@個也沒太大意義,
所以空間復(fù)雜度算的是變量的個數(shù)。
空間復(fù)雜度計算規(guī)則基本跟實(shí)踐 復(fù)雜度類似,也使用大O漸進(jìn)表示法。(估算)
2.示例
復(fù)制代碼
//1. 計算BubbleSort的空間復(fù)雜度?
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}
復(fù)制代碼
我們要注意在計算時,我們計算的是算法需要的額外空間,不考慮數(shù)組輸入的空間。并且我們要注意,空間是可以復(fù)用的,比如所某個算法需要創(chuàng)建一個變量并不斷的為這個變量賦值,這時這個空間復(fù)雜度為O(1);
所以,因?qū)嵗?使用了常數(shù)個額外空間,所以空間復(fù)雜度為 O(1)
復(fù)制代碼
//2. 計算生成的Fibonacci數(shù)組的空間復(fù)雜度?
long long* Fibonacci(size_t n)
{
if(n==0)
{
return NULL;
}
long long * fibArray = (long long *)malloc((n+1) * sizeof(long long));fibArray[0] = 0;//斐波那契數(shù)的第一個fibArray[1] = 1;//斐波那契數(shù)的第二個for (int i = 2; i <= n ; ++i)//利用循環(huán)來生成斐波那契數(shù){ fibArray[i ] = fibArray[ i - 1] + fibArray [i - 2];}return fibArray ;
}
復(fù)制代碼
實(shí)例 2動態(tài)開辟了N個空間來放N個斐波那契數(shù),所以空間復(fù)雜度為 O(N)
//3. 計算階乘遞歸Factorial的空間復(fù)雜度?
long long Factorial(size_t N)
{
return N < 2 ? N : Factorial(N-1)*N;
}
遞歸算法的空間復(fù)雜度通常情況下為 遞歸的深度 (遞歸的次數(shù))
實(shí)例3遞歸調(diào)用了N次,開辟了N個棧幀,每個棧幀使用了常數(shù)個空間。所以空間復(fù)雜度為O(N).
那么在最后我們再來看一張圖:
這就說明有時候 不同的時間復(fù)雜度在N小的時候都還接近,當(dāng)N越來越大時差距越來越多!