算法複習提綱
題型
一、選擇(2*7=14分)
二、填空(2*7=14分)
三、判斷(2*7=14分)
四、算法理解(3題,26分)
五、算法設計與分析題(2題,17分)
六、綜合題(1題,15分)
第一章 算法概述
1.算法的定義
- 算法是指解決問題的一種方法或一個過程。
- 算法是若干指令的有窮序列,每一條指令表示一個或多個操作 。
- 算法是求解一個問題類的無二義性的有窮過程。
2.算法時間複雜度的分類,計算及規則
3.算法的性質
- :有0個或多個外部提供的量作爲算法的輸入
- :算法產生至少一個量作爲輸出
- :組成算法的每條指令是清晰,無歧義的
- :算法中每條指令的執行次數是有限的,執行每條指令的時間也是有限的
程序設計:
- 行爲特性設計: 處理數據的步驟設計
- 結構性設計: 對輸入輸出數據存儲結構的設計
4.時間複雜度和空間複雜度的計算
時間複雜度
平均時間複雜度
算法複雜度
漸進上界符號------O
漸進下界符號------
漸進確界符號------
第二章 遞歸與分治
1.分治的基本思想
將一個規模爲n的問題分解爲k個規模較小的子問題,所有子問題互相獨立且與原問題相同;
遞歸地解決所有子問題,各子問題的解合併得到原問題的解
2.分治的基本步驟、特點
分治基本步驟
- 分解: 將原問題分解成一系列子問題
- 解決: 遞歸的解各個子問題,若子問題足夠小,則直接求解
- 合併: 將子問題的結果合併成原問題的解
分治法的特徵:
- 該問題的規模縮小到一定的程度就可以容易地解決
- 該問題可以分解爲若干個規模較小的性質相同問題,即該問題具有最優子結構性質
- 利用該問題分解出的子問題的解可以合併爲該問題的解
- 該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子問題。
3.遞歸公式的推導(過程、結論)
分治法複雜性分析
將一個規模爲n的問題分解成K個規模爲n/m的子問題
通過迭代法解得
4.應用:找假幣、正整數劃分(遞歸關係 ,算法)、二分搜索(算法)、快速排序、大整數乘法、歸併排序
- 找假幣:
- 正整數劃分:
- 大整數乘法:
- 矩陣乘法
int q(int n, int m)
{
if ( (n<1||(m<1) )
return 0;
if ( (n==1||(m==1) )
return 1;
if (n<m))
return q(n, n);
if (n==m)
return q(n, m-1)+1;}
return q(n, m-1)+q(n-m, m);
}
- 二分搜索:
while (l<=r){
int m = (l + r)/2;
if (x == a[m])
return m;
if (x < a[m]){
r = m-1;
}
else {
l = m+1;
}
}
- 快速排序:
平均時間:
最慢時間:
佔用空間:
void QuickSort (Type a[], int p, int r)
{
if (p<r) {
int q=Partition(a,p,r);
QuickSort (a,p,q-1); //對左半段排序
QuickSort (a,q+1,r); //對右半段排序
}
}
int Partition (Type a[], int p, int r)
{
int i = p, j = r + 1;
Type x=a[p];
while (true) {
//J向左找小於X的數
while (a[--j] > x && i < r);
//從i向右找大於X的數
while (a[++i] < x );
if (i >= j) break;
Swap(a[i], a[j]);
}
a[p] = a[j];
a[j] = x;
return j;
}
- 歸併排序:
平均時間:
最慢時間:
佔用空間:
void MergeSort(Type a[], int left, int right)
{
if (left<right) { //至少有2個元素
int i=(left+right)/2; //取中點
MergeSort(a, left, i);
MergeSort(a, i+1, right);
Merge(a, b, left, i, right); //合併到數組b
copy(a, b, left, right); //複製回數組a
}
}
void Merge (Type c[],Type d[], int left, int middle,int right)
{
//合併c[left:middle]和c[middle+1:right]到d[left:right]
int i=left,j=middle+1,k=1;
while((i<=middle) && (j<=right)) {
//如果i<j則複製c[i],i右移
if(c[i]<=c[j])
d[k++]=c[i++];
else
d[k++]=c[j++];
}
//i>middle i已經排完了,此時j部分剩餘全部移入d[]
if(i>middle){
for( q=j;q<=right;q++)
d[k++]=c[q];
}else{
for(q=i;q<=middle;q++)
d[k++]=c[q];
}
}
第三章 貪心算法
1.貪心法的基本思想
找出整體當中每個小的局部的最優解,並且將所有的這些局部最優解合起來形成整體上的一個最優解
2.貪心法的特點、基本要素
貪心算法總是作出在當前看來最好的選擇
它並不是從總體最優上加以考慮,他所作出的選擇只是在某種意義上的局部最優選擇
單源最短路徑問題,最小生成樹問題等,可獲得整體最優解
貪心算法有兩個基本要素:
- 貪心選擇性質:通過一系列局部最優解得到整體的解
- 最優子結構性質:一個算法的最優解包括其子問題的最優解
3.應用:哈夫曼編碼、最小生成樹、單源最短路徑、最優裝載問題、分數揹包問題(算法)、活動安排(算法、正確性證明)——所有算法時間複雜度
- 活動安排問題
void GreedySelector(int n, Type s[], Type f[], bool A[])
{
//把1活動加入,其中S是按照結束時間排序過的,S[1]最早結束
A[1]=true;
int j=1;
for (int i=2;i<=n;i++){
if (s[i]>=f[j]) { A[i]=true; j=i; }
else A[i]=false;
}
}
-
0-1揹包問題
先按照v/m計算出單位體積的價值,按順序依次裝入
-
哈夫曼編碼