《資料結構與演算法分析》學習筆記-第一章-引論
自述
自從工作之後,就沒有再寫部落格了,一方面是因為自己初入職場還不能很好的適應職場生活。另一方面也是對前途有些不知所措。現在工作已經快三年了,我慢慢找到了自己的節奏,也許還是有很多不成熟的地方,但是我已經想開啦。做自己真正喜歡的事就好了,遵循自己的內心。在職場的這些年我寫了很多筆記,但是沒有時間整理出來,後面慢慢都會發表出來分享給大家。感覺自己在技術上還是有很多不足,有很多基礎的東西掌握的還是不好呀。所以想踏踏實實的重新學習這些基本知識。包括C語言基礎、資料結構與演算法、作業系統。還希望能更進一步,掌握python、java。學習並整理設計模式、網路、檔案系統、記憶體管理、多執行緒開發等等。請大家敬請期待吧。好了,話不多說。
我,CrazyCatJack又回來啦!
1.1 本書討論的內容
- 一個可以執行的程式並不夠,如果在巨大的資料集執行,執行時間就變成了相當重要的問題。
- 學習如何估計程式的執行時間,尤其是在未編碼的情況下預估兩個演算法的執行時間。
- 學習徹底改程序序速度和確定程式瓶頸的方法,這些方法使我們能夠找到需要大力優化的程式碼段
書上上來就提出了一個演算法問題,並提出了兩個解決方案,我實現了具體的程式碼,大家可以嘗試將這兩個檔案編譯後,檢視列印瞭解具體的執行過程。還可以在linux命令列下使用time ./a.out 命令檢視兩個程式的執行時間,進行比較。我將程式碼上傳到了github上。https://github.com/CrazyCatJack/structureAlgorithm
設有一組N個數而要確定其中第K個最大的數。兩種方法實現如下:
- 法1:將N個數讀進一個數組,再通過氣泡排序進行遞減排序,最後返回k位置上的元素
// SPDX-License-Identifier: GPL-2.0-only /* * sort1.c * * Copyright (C) 2020 xuri.All rights reserved. */ #include <stdio.h> #define ARRAY_SIZE 1000 #define MAXKNUM 500 int sortK(int *array, int arraySize, int MaxKnum) { if (array == NULL || arraySize <= 0 || MaxKnum <= 0) { return -1; } int subscript, sortTimes; for (sortTimes = 0; sortTimes < arraySize - 1; sortTimes++) { for (subscript = 1; subscript < arraySize - sortTimes; subscript++) { if (array[subscript] > array[subscript - 1]) { int temp; temp = array[subscript]; array[subscript] = array[subscript - 1]; array[subscript - 1] = temp; } } #if 0 printf("NO %d sort:", sortTimes); int prtCnt; for (prtCnt = 0; prtCnt < arraySize; prtCnt++) { printf("%d ", array[prtCnt]); } printf("\n"); #endif } return array[MaxKnum - 1]; } void main() { int array[ARRAY_SIZE]; int assignCnt; for (assignCnt = 0; assignCnt < ARRAY_SIZE; assignCnt++) { array[assignCnt] = assignCnt; } int K = sortK(array, ARRAY_SIZE, MAXKNUM); printf("K = %d\n", K); }
- 法2:可以先把前K個元素讀入陣列並以遞減的順序進行排序。再將剩下的元素逐個讀入,用新元素與當前陣列中第K個元素進行比較,如果它小於則忽略,如果它大於,則將它放到陣列中正確的位置上,同時擠出一個元素。當演算法終止,第k個元素就是正確答案
// SPDX-License-Identifier: GPL-2.0-only
/*
* sort2.c
*
* Copyright (C) 2020 xuri.All rights reserved.
*/
#include <stdio.h>
#define ARRAY_SIZE 1000
#define MAXKNUM 500
void MaoPaoSort(int *localArray, int MaxKnum)
{
int subscript, sortTimes;
for (sortTimes = 0; sortTimes < MaxKnum - 1; sortTimes++) {
for (subscript = 1; subscript < MaxKnum - sortTimes; subscript++) {
if (localArray[subscript] > localArray[subscript - 1]) {
int temp;
temp = localArray[subscript];
localArray[subscript] = localArray[subscript - 1];
localArray[subscript - 1] = temp;
}
}
#if 0
printf("NO %d sort:", sortTimes);
int prtCnt;
for (prtCnt = 0; prtCnt < MaxKnum; prtCnt++) {
printf("%d ", localArray[prtCnt]);
}
printf("\n");
#endif
}
}
int sortK(int *array, int arraySize, int MaxKnum)
{
if (array == NULL || arraySize <= 0 || MaxKnum <= 0) {
return -1;
}
// assign MaxKnum number in localArray
int localArray[MaxKnum];
int assignCnt;
for (assignCnt = 0; assignCnt < MaxKnum; assignCnt++) {
localArray[assignCnt] = array[assignCnt];
}
// sort localArray
MaoPaoSort(localArray, MaxKnum);
// get remain number in array add to in localArray for sort
for (assignCnt = MaxKnum; assignCnt < arraySize; assignCnt++) {
if (array[assignCnt] > localArray[MaxKnum - 1]) {
int temp = 0;
temp = array[assignCnt];
array[assignCnt] = localArray[MaxKnum - 1];
localArray[MaxKnum - 1] = temp;
MaoPaoSort(localArray, MaxKnum);
}
}
return localArray[MaxKnum - 1];
}
void main()
{
int array[ARRAY_SIZE];
int assignCnt;
for (assignCnt = 0; assignCnt < ARRAY_SIZE; assignCnt++) {
array[assignCnt] = assignCnt;
}
int K = sortK(array, ARRAY_SIZE, MAXKNUM);
printf("K = %d\n", K);
}
1.2 數學知識複習
因為數學格式很難打出來,所以乾脆手寫啦,這裡委屈大家看我的醜字了-_-||
好記性不如爛筆頭,CCJ也建議大家親自演算一下,自己演算出來的才算是自己的東西。
1.2.5 證明方法
1)歸納法
- 基準情形:確定某些小值得正確性
歸納假設:假設定理對於小於有限數k的所有情況成立,用這個定理證明k+1也是成立的
2) 反證法
通過假設定理不成立,然後證明該假設導致某個已知的性質而不成立,從而說明原假設是錯誤的
1.3 遞迴簡論
- 當一個函式用它自己來定義時,就稱為是遞迴的。不是所有的數學遞迴函式都能有效的(或正確的)由C的遞迴模擬來實現。
- C中的遞迴函式==若無基準情況,也是毫無意義的==
- 跟蹤掛起的函式呼叫(即這些呼叫已經開始但是正等待著遞迴呼叫來完成)以及它們中變數的記錄工作都是由計算機自動完成的。遞迴呼叫將==反覆進行直到基準情形出現==
- 遞迴組成
- 基準情形:不用遞迴就能求解的情形
- 不斷推進:對於需要遞迴求解的情形,遞迴呼叫必須總能朝著產生基準情形的方向推進
- 設計法則:假設所有的遞迴呼叫都能執行。不必追蹤所有的遞迴呼叫,很困難且沒必要。使用遞迴能簡化演算法設計並設計出簡潔的程式碼
合成效益法則: 在求解一個問題的同一例項時,切勿在不同的遞迴呼叫中做重複性的工作。例如計算斐波那契數列用遞迴就不是很好的選擇
```
// 本書例程include <stdio.h>
int F(int x)
{
if (0 == x) {
return 0;
} else (0 > x) {
return (2 * F(x-1) + x * x);
}
}
void main()
{
printf("F(1)=%d, F(2)=%d, F(3)=%d\n", F(1), F(2), F(3));
}
列印輸出數
// 本書例程
include <stdio.h>
int printDigit(int x)
{
if (x >= 10) {
printDigit((x / 10));
}
printf("%d", (x % 10));
}
void main()
{
int a = 123456789;
printDigit(a);
}
```
***
敬告:
本文原創,歡迎大家學習轉載^_^
==轉載請在顯著位置註明:==
博主ID:CrazyCatJack
原始博文連結地址:https://www.cnblogs.com/CrazyCatJack/p/12545591.html
***
第一章到此結束,接下來會進行課後習題的講解。希望能給正在學習資料結構與演算法的朋友帶來幫助。我們一起來構築一個更好的世界!
覺得好的話請幫忙點個推薦,謝謝大家的支援!嘿嘿~