文章目錄
- 第四章-篩法與查找
-
- 4.1 插花遊戲
-
- 筆記
- 代碼實作
- 4.2 篩法
-
- 筆記
- 4.2.3 代碼實作
- 4.2.5 代碼實作
- 4.2.7 代碼實作
- 4.2.7 韓信點兵問題的數學了解
- 4.3 線性查找
-
- 筆記
- 4.3.2 代碼實作
- 4.3.4 代碼實作
- 4.4 折半查找
-
- 筆記
- 代碼實作
- 4.5 排序問題
-
- 筆記
- 4.5.1 代碼實作
- 4.5.1 代碼簡化
- 4.5.2 代碼實作
- 4.5.3 代碼實作
- 4.5.3 代碼拓展
- 4.5.4 代碼實作
- 文法自測-試題答案
第四章-篩法與查找
4.1 插花遊戲
筆記
函數(function)是一個具有特定的功能的、相對獨立的子產品,能夠被多次使用。
函數設計的要素:
功能:函數的定義(definition)
子產品:函數的聲明(declaration)-->函數名,輸入類型,輸出類型
使用:函數的調用(call)
代碼實作
#include <iostream>
using namespace std;
bool isPrime(int);
int main()
{
for (int n = 2; n <= 100; n++)
if (isPrime(n))
cout << n <<endl;
return 0;
}
bool isPrime(int n)
{
for (int i = 2; i*i <= n; i++)
if (n % i == 0)
return false;
return true;
}
4.2 篩法
筆記
數組定義:數組的類型,數組的名稱,變量的個數;
篩法思路:埃拉托斯特尼篩法
初始化“篩子”-->枚舉-->用篩子篩選
4.2.3 代碼實作
#include <iostream>
using namespace std;
const int N=100;
bool seive[N+1];
int main()
{
for (int i = 2; i <= N; i++)
seive[i] = true;
for (int d = 2; d*d <= N; d++)
if (seive[d])
for (int n = d*d; n <= N; n +=d)
seive[n] = false;
for (int n =2; n <= N; n++)
if (seive[n])
cout << n <<endl;
return 0;
}
4.2.5 代碼實作
#include <iostream>
using namespace std;
int main()
{
int r3 = 0, r5 = 0, r7 = 0;
int seive[200];
cin >> r3 >> r5 >> r7;
for (int i = 0; i < 200; i++)
seive[i] = 0;
for (int i = r3; i < 200; i = i + 3)
seive[i]++;
for (int i = r5; i < 200; i = i + 5)
seive[i]++;
for (int i = r7; i < 200; i = i + 7)
seive[i]++;
for (int i = 0; i < 200; i++)
if (seive[i] == 3)
cout << i <<endl;
return 0;
}
注意:循環中的 i 需要 小于 數組中變量個數,因為200個變量的數組最後一個位seive[199]
4.2.7 代碼實作
#include <iostream>
using namespace std;
int main()
{
int r3 = 0, r5 = 0, r7 = 0;
cin >> r3 >> r5 >> r7;
int res = (r3 * 70 + r5 * 21 + r7 * 15) % 105;
cout << res <<endl;
return 0;
}
4.2.7 韓信點兵問題的數學了解
- 能被 5,7 除盡數是 35k,其中 k=2,即70除3正好餘1,70a 除3正好餘a。
- 能被 3,7 除盡數是 21k,其中 k=1,即21除5正好餘1,21b 除5正好餘b。
- 能被 3,5 除盡數是 15k,其中 k=1,即15除7正好餘1,15c 除7正好餘c。
是以
- 70a + 21b + 15c 除3正好餘a。
- 70a + 21b + 15c 除5正好餘b。
- 70a + 21b + 15c 除7正好餘c。
是以
(70a + 21b + 15c)%(3 * 5 * 7)為最小值
以上内容摘自網絡
4.3 線性查找
筆記
線性查找:撲克牌問題
初始化-->枚舉-->判定查找-->找到跳出-->輸出
查找最小值/最大值:
初始化-->枚舉-->判定查找-->更新判定值-->輸出
4.3.2 代碼實作
#include <iostream>
using namespace std;
int main()
{
int cards[13] = {101,112,109,107,202,209,
213,212,313,303,403,412,402};
int pos = -1;
for (int i =0; i < 13; i++)
if (cards[i] == 112)
{
pos = i;
break;
}
if (pos != -1)
cout << "黑桃Q是第" << pos + 1 << "張牌" <<endl;
else
cout << "沒找到" <<endl;
return 0;
}
4.3.4 代碼實作
#include <iostream>
using namespace std;
int main()
{
int cards[13] = {101,112,109,107,202,209,
213,212,313,303,403,412,402};
int last_card = 7;
int min = 14;
int pos = -1;
for (int i =0; i < 13; i++)
if ((cards[i] % 100) > 7)
if ((cards[i] % 100) < min)
{
pos = i;
min = cards[i] % 100;
}
if (pos != -1)
cout << "比" << last_card << "大的最小牌是第"
<< pos + 1 << "張牌" <<endl;
else
cout << "沒找到" <<endl;
return 0;
}
注意到,本例中有兩張 9 均符合結果,判定為 小于 是以輸出的是第一個符合條件的牌的位置
4.4 折半查找
筆記
已知查找目标是有序排列的
選擇目标最中間的資料作為判定目标,每次判定篩選掉一半資料,是以是折半查找
初始化-->選取中間資料判定-->找到跳出,未找到更新範圍-->範圍内無牌-->輸出
代碼實作
#include <iostream>
using namespace std;
int main()
{
int target_card = 112;
int cards[13] = {101,107,109,112,202,209,
212,213,303,313,402,403,412};
int pos = -1;
int low = 0, high = 12;
while (low <= high)
{
int middle = (low + high) / 2;
if (cards[middle] == target_card)
{
pos = middle;
break;
}
else if (cards[middle] > target_card)
high = middle -1;
else
low = middle +1;
}
if (pos != -1)
cout << target_card << "是第"
<< pos + 1 << "張牌" <<endl;
else
cout << "沒找到" <<endl;
return 0;
}
4.5 排序問題
筆記
插入排序:将第 i 個元素 插入 之前的資料中的比自己大的資料之前
選擇排序: 選取 第 i 個之後的最小值放在 i 的位置
折半插入排序:在插入排序中,第 i 個元素之前的資料已經被排序,是以進行插入時可以使用折半查找
4.5.1 代碼實作
//插入排序
#include <iostream>
using namespace std;
int main()
{
int cards[13] = {101,112,109,107,202,209,
213,212,313,303,403,412,402};
for (int i =0; i < 13; i++)
{
int pos = -1, min = 500, target = cards[i];
for (int j = 0; j < i; j++)
if(cards[j] > target)
if(cards[j] < min)
{
min = cards[j];
pos = j;
}
if (pos != -1)
{
for (int j = i; j >pos; j--)
cards[j] = cards[j - 1];
cards[pos] = target;
}
}
for (int i =0; i < 13; i++)
cout << cards[i] << " ";
cout <<endl;
return 0;
}
4.5.1 代碼簡化
因為第 i 個資料之前的值,已經從小到大排列過,是以當按照順序找到的第一個比 cards[i] 大的數時,這個數肯定是期望的最小數,是以可以簡化掉對 min 的處理
for (int i =0; i < 13; i++)
{
int pos = 0, target = cards[i];
while (target > cards[pos])
pos++;
for (int j = i; j >pos; j--)
cards[j] = cards[j - 1];
cards[pos] = target;
}
4.5.2 代碼實作
//選擇排序
#include <iostream>
using namespace std;
int main()
{
int cards[13] = {101,112,109,107,202,209,
213,212,313,303,403,412,402};
for (int i =0; i < 13; i++)
{
int min = cards[i],pos = i;
for (int j = i + 1; j < 13; j++)
if (cards[j] < min)
{
min = cards[j];
pos = j;
}
cards[pos] = cards[i];
cards[i] = min;
}
for (int i =0; i < 13; i++)
cout << cards[i] << " ";
cout <<endl;
return 0;
}
4.5.3 代碼實作
//函數寫法
#include <iostream>
using namespace std;
void insertsort(int cards[], int n);
void selectsort(int cards[], int n);
int main()
{
int cards[13] = {101,112,109,107,202,209,
213,212,313,303,403,412,402};
// insertsort(cards, 13);
selectsort(cards, sizeof(cards) / sizeof(int));
for (int i =0; i < 13; i++)
cout << cards[i] << " ";
cout <<endl;
return 0;
return 0;
}
void insertsort(int cards[], int n)
{
for (int i =0; i < n; i++)
{
int pos = 0, target = cards[i];
while (target > cards[pos])
pos++;
for (int j = i; j >pos; j--)
cards[j] = cards[j - 1];
cards[pos] = target;
}
}
void selectsort(int cards[], int n)
{
for (int i =0; i < n; i++)
{
int min = cards[i],pos = i;
for (int j = i + 1; j < n; j++)
if (cards[j] < min)
{
min = cards[j];
pos = j;
}
cards[pos] = cards[i];
cards[i] = min;
}
}
4.5.3 代碼拓展
數組的長度,使用 sizeof() 提取數組長度,因為數組是一個 int 類型的數組,是以需要除以 sizeof(int) 才是最終的數組長度。
4.5.4 代碼實作
//折半插入排序
#include <iostream>
using namespace std;
int main()
{
int cards[13] = {101,112,109,107,202,209,
213,212,313,303,403,412,402};
for (int i =0; i < 13; i++)
{
int pos = -1,target = cards[i];
int low = 0, high = i - 1;
while (low <= high)
{
int middle = (low + high) / 2;
if((cards[middle] < target) && (cards[middle + 1] > target))
{
pos = middle + 1;
break;
}
else if (cards[middle] > target)
high = middle -1;
else
low = middle +1;
}
if (pos != -1)
{
for (int j = i; j >pos; j--)
cards[j] = cards[j - 1];
cards[pos] = target;
}
}
for (int i =0; i < 13; i++)
cout << cards[i] << " ";
cout <<endl;
return 0;
}
文法自測-試題答案
本題中 i-j 為負數