目次
時間の複雑さと空間の複雑さ::
データ構造とは
データ構造とは、コンピューターがデータを保存および編成する方法を指し、相互に 1 つ以上の特定の関係を持つデータ要素の集合を指します。
アルゴリズムとは
アルゴリズムは、入力として値または値のセットを取り、出力として値または値のセットを生成する明確に定義された計算プロセスです. 簡単に言えば、アルゴリズムは、入力データを変換するために使用される一連の計算ステップです
.出力結果に。
例: データ構造は、メモリ内のデータを管理することです。データベースの追加、削除、チェック、および変更は、ディスク内のデータを管理することです。追加、削除、チェック、変更します。
B ツリーは、二分探索アルゴリズムを使用して検索ツリーを使用します。
1. アルゴリズム効率
アルゴリズムが実行可能なプログラムに書き込まれた後、実行時に時間リソースと空間 (メモリ) リソースを消費する必要があるため、アルゴリズムの品質は通常、時間と空間の 2 つの次元、つまり時間複雑度と空間複雑度から測定されます
。時間複雑度は主にアルゴリズムの実行速度を測定し、
空間複雑度は主にアルゴリズムを実行するために必要な余分なスペースを測定します.
コンピュータ開発の初期には、コンピュータのストレージ容量は非常に小さかったので、彼らは非常に心配していました.スペースの複雑さ, しかし、コンピューター産業の急速な発展に伴い
、コンピューターのストレージ容量は非常に高いレベルに達したため、アルゴリズムのスペースの複雑さに特別な注意を払う必要がなくなりました. ムーアの法則: の数
集積回路に収容できるトランジスタの数は、約 18 個ごとに 1 か月で 2 倍になります。
2. 時間の複雑さ
時間複雑度の概念:
時間複雑度の定義: コンピューター サイエンスでは、アルゴリズムの時間複雑度は、アルゴリズムの実行時間を定量的に説明する関数です. アルゴリズムの実行にかかる時間は、理論的に計算することはできません
。マシンを知ることができます.
しかし、マシンで各アルゴリズムをテストする必要がありますか?はい、マシンですべてのアルゴリズムをテストできますが、非常に面倒なので、時間の複雑さの分析方法があります
.アルゴリズムによる計算量は、ステートメントの実行回数に正比例し、アルゴリズムの基本操作の実行回数は、アルゴリズムの時間計算量になります. つまり、ステートメントと問題サイズの間の数式を見つけることです
. N は、アルゴリズムの時間の複雑さを計算することです。
void Func1(int N)
{
int count = 0;
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++i)
{
++count;
}
}
for (int k = 0; k < 2 * N; ++k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
printf("%d\n", count);
}
时间复杂度为:O(N^2)
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);
}
时间复杂度为:O(N)
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);
}
时间复杂度为:O(M+N)
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;
}
}
时间复杂度为:O(N^2)
void Fun4(int N)
{
int count = 0;
for (int k = 0; k < 100; ++k)
{
++count;
}
printf("%d\n", count);
}
时间复杂度为:O(1)
Big O の漸近記法:
Big O 記法は、関数の漸近的な動作を記述するために使用される数学的な記法です.
Big O の漸近記法を導出するには:
1. 実行時のすべての加法定数を定数 1 に置き換えます.
2. 変更後の数値の後にof runs 関数では、最上位の項目のみが保持されます
3. 最上位の係数が存在し、1 でない場合、この項目に乗算された定数を削除すると、結果はビッグ O オーダーになります。
アルゴリズムの時間計算量には、最良、最悪、および平均のケースが
あります
。
任意の入力サイズで実行 回数 (下限)
例: 長さ N の配列でデータ x を検索する
最良のケース: 検索に 1 回
最悪のケース: 検索に N 回
平均的なケース: 検索に N/2 回
実際の状況では、最も懸念されるのはアルゴリズムの操作が悪いため、配列内のデータを検索する時間の複雑さは O(N) です。
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n - 1;
//[begin,end] begin和end是左闭右闭区间,因此有=号
while (begin <= end)
{
int mid = begin + ((end - begin) >> 1);
if (a[mid] < x)
begin = mid + 1;
else if (a[mid] > x)
end = mid - 1;
else
return mid;
}
return -1;
}
二分查找的最好情况是O(1)
二分查找的最坏情况是找不到 时间复杂度为O(logN)
每查找一次 查找区间个数减少一半(除2)
N/2/2/2.../2 = 1
longlong Fac(size_t N)
{
if (1 == N)
return 1;
return Fac(N - 1) * N;
}
时间复杂度为O(N)
longlong Fib(size_t N)
{
if (N < 3)
return 1;
return Fib(N - 1) + Fib(N - 2);
}
时间复杂度为O(2^N)
longlong Fib(size_t N)
{
if (N < 3)
return 1;
longlong f1 = 1, f2 = 1, f3;
for (size_t i = 3; i <= N; ++i)
{
f3 = f2 + f1;
f1 = f2;
f2 = f3;
}
return f3;
}
时间复杂度为O(N)
3. 空間の複雑さ
スペースの複雑度は、操作中にアルゴリズムによって占有される追加のストレージ スペースの尺度である数式でもあります.
スペースの複雑さは、プログラムが占有するスペースのバイト数ではありません. これはあまり意味がないため、スペースの複雑さは計算されます.変数の数.
空間複雑度の計算規則は基本的に時間複雑度に似ており、大きな O の漸近表現も使用されます.
注: スタック スペース (ストレージ パラメーター、ローカル変数、一部のレジスタ情報など) によって必要とされる実行中の関数) はコンパイル中に決定されるため、スペースの複雑さは主に実行時に関数によって要求される追加スペースによって決まります. 1G は約 10 億バイトです. 1G = 1024*1024*1024 1M は約 100 万バイト
です
. 1M = 1024 *1024
计算BubbleSort的空间复杂度
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;
}
}
空间复杂度为O(1)
计算Fac的空间复杂度
longlong Fac(size_t N)
{
if (N == 0)
return 1;
return Fac(N - 1) * N;
}
空间复杂度为O(N)
每个函数栈帧是常数个 有N+1个Fac栈帧
计算Fib的空间复杂度
longlong Fib(size_t N)
{
if (N < 3)
return 1;
return Fib(N - 1) + Fib(N - 2);
}
空间复杂度为O(N)
4. 一般的な時間の複雑さと複雑さ OJ 演習
一般的なアルゴリズムの一般的な複雑さは次のとおりです。
5201314 | O(1) | 一定の順序 |
3n+4 | の上) | 線形順序 |
3n^2+4n+5 | O(n^2) | 平方オーダー |
3log(2)n+4 | O(ログ) | 対数次数 |
2n+3nlog(2)n+14 | O(n*logn) | nlogn オーダー |
n^3+2n^2+4n+6 | O(n^3) | 立方次数 |
2^n | O(2^n) | 指数順 |
複雑さのための OJ 演習:
消える数字:
int missingNumber(int* nums, int numSize)
{
int x = 0;
for (int i = 0; i < numSize; ++i)
{
x ^= nums[i];
}
for (int j = 0; i < numSize + 1; ++j)
{
x ^= j;
}
return x;
}
void reverse(int* a, int begin, int end)
{
while (begin < end)
{
int tmp = a[begin];
a[begin] = a[end];
a[end] = tmp;
++begin;
--end;
}
}
void rotate(int* num, int numSize, int k)
{
if (k > numSize)
k %= numSize;
reverse(nums, 0, numsSize - k - 1);
reverse(nums, numSize - k, numsSize - 1);
reverse(nums, 0, numsSize - 1);
}