聽課筆記---資料結構(浙江大學)MOOC---第一週
阿新 • • 發佈:2019-01-30
第一週:預備知識—演算法與資料結構
解決問題的策略效率與什麼有關?
資料組織方式
圖書館插入新書和查詢書籍,用不同的資料組織方式,對應的操作就會有不同的時間複雜度。
資料組織方式好壞的分析,與它所相關的操作有直接聯絡。
空間利用效率
觀察兩段用於輸出1到N的數字的程式碼
其一迴圈演算法:
void PrintN(int N) { int i; for (i = 1; i <= N; i++) { printf("%d\n", i); } return; }
其二遞迴演算法:
void PrintN(int N) { if (N) { PrintN(N - 1
第二段程式碼在資料過大時由於不斷堆疊,空間爆炸,異常終止。
演算法巧妙程度
計算多項式在給定點x處的值,兩段程式碼
其一:
f(x)=a0+a1x+⋯+an−1xn−1+anxn double f(int n, double a[], double x) { int i; double p = a[0]; for (i = 1; i <= n; i++) { p += (a[i] * pow(x,i)); } return p; }
其二;
f(x)=a0+x(a1+x(⋯(an−1+x(an double f(int n, double a[], double x) { int i; double p = a[n]; for (i = n; i > 0; i--) { p = a[i - 1] + x * p; } return p; }
兩段程式碼在執行時間上有很大區別,究其原因,將乘法視為關鍵操作,冪次視作多次乘法,則第一段程式碼演算法
O(n2) , 第二段程式碼O(n) .
測試(比較)演算法執行效率小方法
#include<stdio.h>
#include<time.h>
#include<math.h>
#define MAX 100
double poly1(int n, double a[], double x) // 坊間演算法
{
double p = 0;
for (int i = 0; i <= n; i++) {
p += a[i] * pow(x, i);
}
return p;
}
double poly2(int n, double a[], double x) // 專業演算法
{
double p = a[0];
for (int i = n; i > 0; i--) {
p += a[i - 1] + p * x;
}
return p;
}
int main()
{
double coef[MAX], x = 1.1;
clock_t start, stop;
for (int i = 0; i < MAX; i++) {
coef[i] = i / 3.0;
}
start = clock();
for (int i = 0; i < MAX; i++)
poly1(MAX - 1, coef, x);
stop = clock();
printf("Polynomial Algorithm 1---plain Algorithm\n"
"used ticks: %f\n\n", (double)(stop - start));
start = clock();
for (int i = 0; i < MAX; i++)
poly2(MAX - 1, coef, x);
stop = clock();
printf("Polynomial Algorithm 2---professional Algorithm\n"
"used ticks: %f\n\n", (double)(stop - start));
return 0;
}
資料結構與抽象資料結構
資料結構
- 資料物件在計算機中的組織方式
- 邏輯結構
- 物理儲存結構
- 資料物件與施加於其上的操作相關聯
- 實現操作的就是演算法
抽象資料結構
- 資料結構
- 資料物件集
- 與資料物件集相關的操作集
- 抽象
- 與物理儲存方式無關
- 與實現的演算法和程式語言無關
只定義了物件集和操作集,不涉及如何實現。如下例:
演算法與最大子列和問題
熟悉問題,只敲了程式碼,在QuizCode裡有
初識PTA
PTA是資料結構這門課採用的OJ系統。
- 會將各個樣例的特徵標在Wrong Answer的標籤旁邊,便於Debug。
- 函式填空題會將一些部分隱藏起來,因此看上去沒有不代表沒有,需仔細讀題。
最大子列和(課堂演算法)程式碼
課上講的演算法
#include<stdio.h>
#include<stdlib.h> // for malloc
int MaximumSubSum(int Data[], int s, int e); // 尋找最大和
int max(int a, int b, int c);
int MaxCrossing(int Data[], int s, int e); // Conquer 尋找跨越中間元素的最大和
int main()
{
int * Data = NULL, Size = 0;
scanf("%d", &Size);
Data = malloc(sizeof(int) * Size); // 動態分配記憶體
for (int i = 0; i < Size; i++) {
scanf("%d", &Data[i]);
}
int Max = MaximumSubSum(Data, 0, Size - 1); // 尋找
printf("%d\n", Max);
return 0;
}
int MaximumSubSum(int Data[], int s, int e)
{
if (s == e) { // Base Case 只有一個元素
if (Data[s] <= 0) {
return 0;
}
else {
return Data[s];
}
}
int mid = (s + e) / 2;
int Max1 = MaximumSubSum(Data, s, mid);
int Max2 = MaximumSubSum(Data, mid + 1, e); // Divide, 遞迴求解
int Max3 = MaxCrossing(Data, s, e); // Conquer
return max(Max1, Max2, Max3);
}
int max(int a, int b, int c)
{
int result = a;
if (result < b) {
result = b;
}
if (result < c) {
result = c;
}
return result;
}
int MaxCrossing(int Data[], int s, int e)
{
int mid = (s + e) / 2, maxl = 0, maxr = 0, curr = 0;
for (int i = mid; i >= s; i--) { // 左側最大
curr += Data[i];
if (curr > maxl) {
maxl = curr;
}
}
curr = 0; // initialize
for (int i = mid + 1; i <= e; i++) {// 右側最大
curr += Data[i];
if (curr > maxr) {
maxr = curr;
}
}
return maxl + maxr; // 和為最大
}
演算法
#include<stdio.h>
int main()
{
int Size = 0, max = 0, curr = 0, Data = 0; // O(1) extra space
scanf("%d", &Size);
for (int i = 0; i < Size; i++) {
scanf("%d", &Data);
curr += Data;
if (curr > max) { // refresh max
max = curr;
}
if (curr < 0) { // discard curr
curr = 0;
}
}
printf("%d\n", max);
return 0;
}
最大子列和(課後習題)程式碼
#include<stdio.h>
#include<stdlib.h> // for malloc
int main()
{
int Bool = 0, Size = 0, max = 0, curr = 0, curr_s = 0, curr_e = 0, s = 0, e = 0;
int * Data; // O(n) extra space
scanf("%d", &Size);
Data = malloc(sizeof(int) * (Size + 1));
for (int i = 0; i < Size; i++) {
scanf("%d", &Data[i]);
}
curr_s = curr_e = s = e = Data[0];
for (int i = 0; i < Size; i++) {
curr += Data[i];
curr_e = Data[i];
if (curr < 0) {
curr = 0;
curr_s = Data[i + 1];
}
if (curr > max) {
max = curr;
s = curr_s;
e = curr_e;
}
}
if (max == 0) { // 為0特判
s = Data[0];
e = Data[Size - 1];
for (int i = 0; i < Size; i++) {
if (Data[i] == 0) {
s = e = 0;
break;
}
}
}
printf("%d %d %d\n", max, s, e);
return 0;
}