我的創作紀念日——《驚變256天》
- 機緣
- 收獲
- 日常
- 成就
- 憧憬
最近,博主收到了 CSDN 發來的系統消息,這才驚覺,自上次第128天創作紀念日之后,竟又悄然走過了 128 天。站在 256 天這個頗具意義的里程碑前回望,博主在2023 年 8 月 29 日那天創作第一篇博客的情景依然歷歷在目。
彼時,博主懷著忐忑又興奮的心情,敲下了第一篇博客:講解LeetCode第1題:兩數之和(完整代碼)。未曾想,這看似尋常的舉動,竟成了漫漫創作之旅的起點。
起初,博主每一次點擊 “發布” 鍵,都像把精心打磨的作品置于眾目睽睽之下,既期待共鳴,又害怕被否定。但是連續幾次的發布并沒有什么回應,慢慢的博主的創作越來越少,但是在幾近放棄時候博主選擇了堅持下來,而如今回望卻發現自己已經走了很遠。
機緣
博主是于 2023 年 9 月 1 日踏入大學校門,從入學伊始呢博主便確定了本科畢業后直接就業的選擇。因此,平日空閑的時候,博主便常通過手機了解一些計算機專業學生的就業情況,也正是在這樣的探索中,博主慢慢知曉了 CSDN 這個 APP,然后就在 2023 年 10 月 11 日注冊了賬號。不過,起初博主只是偶爾打開瀏覽,并未深入使用。
后來,博主從一些過來人分享的經驗中得知,經常撰寫博客在面試時能成為加分項,從那時起,以就業為目標的博主心里便萌生了寫博客的念頭。但由于完全不懂如何寫博客,起初并未真正付諸行動。
時光流轉,轉眼間時間就到了大一結束的那個暑假。某一天,博主突然想起寫博客這件事,于是便在 B 站上學習如何寫博客。這才了解到,需要先掌握一種名為 Markdown 的輕量型標記語言。當學完這門語言后,博主又面臨新的困惑:該創作什么類型的文章呢?
這時,眼前記錄著 LeetCode 題解和知識要點的筆記本引發了博主的思考:“本子上記了這么多知識點,自己又翻開看過幾次呢?”,于是,博主翻開筆記本的第一頁,看到 “兩數之和” 的題目,靈感涌現,就此誕生了第一篇博客:講解LeetCode第1題:兩數之和(完整代碼)。此后,博主又陸續撰寫了幾篇 LeetCode 習題講解,當然也都反響平平,不過博主還在不定期的更新。
那時,博主還只是獨自在 CSDN 上發布零散的 LeetCode 或洛谷題解,關注者寥寥,更新也毫無規律,全憑興致所至。
因此,博主還沒發幾篇博客,上半學期就結束了。在寒假里的某一天,博主忽然發現自己對之前學過的一些內容已經記憶模糊了,卻又因沒有學習記錄而只能重新翻書。基于此,博主萌生了將從 C 語言開始的所有學習內容都寫成博客的想法,目的是方便自己隨時回顧,同時通過不斷總結來牢固已經掌握的知識點。秉持著這一信念,即便平時再忙,博主睡前也要堅持寫一點博客,因此現在博主的博客大都是這樣一天一點、積少成多積累而來的。
然而,C 語言的內容還差兩章未更新完,寒假便結束了,新學期如期而至。在新學期里,博主通過 CSDN 平臺結識了一群同樣通過博客記錄學習過程的小伙伴。大家彼此支持,此前博主博客評論區總是一片冷清,如今卻多了許多互動。每天看到自己的博客能得到小伙伴們的支持,博主心中便充滿了繼續更新的動力。同時,看到同齡小伙伴每周都能創作出多篇優質博文,博主也深受激勵,不再像從前那樣隨意更新,而是給自己定下規矩:每周必須完成兩篇高質量的博客。
收獲
截止到目前,博主在 CSDN 平臺已收獲 720 多名粉絲,累計獲得 1700 多個點贊、1400 多次收藏以及 500 多條評論。這些數據于博主而言,絕非冰冷的數字,而是無數個日夜堅持創作的鮮活記錄。每當看到粉絲數量從三位數突破至新的臺階,每當注視著點贊、收藏的數字一點點的變大,博主總能清晰感受到時間的流淌。
博主通過之前持續的博客創作,在知識梳理與文字表達上積累了許多經驗,現在博主對內容質量的把控也愈發嚴格。從最初對 Markdown 語法的生疏運用,到如今能流暢地將復雜知識點拆解為邏輯清晰的技術博文,每一次創作都是對自我的打磨與提升。
在創作的過程中,博主的努力也多次獲得認可 —— 除了獲得許多小伙伴的支持,也得到了CSND平臺的認可:(例如一下幾個:)
博主深知,沒有大家的認可,便沒有這些榜單上的成績,也沒有持續創作的熱情。因此,在今后的日子里,博主定會繼續力求每篇博客都做到邏輯清晰、干貨滿滿,讓大家能博客中收獲更多。
同時,也會更加注重與大家的互動,傾聽大家的需求與建議,讓博客真正成為一個共同學習、共同進步的平臺。
日常
日常里,博主主要專注于專業課的學習(當然,博主的學習范圍并不局限于學校課程所涵蓋的內容)。一般每學完一到兩個章節,便會停下腳步,悉心梳理所學知識點,將其整理成博客與大家分享。
當然創作博客這件事情確實還是挺費時間和精力的,但是經過這段時間的堅持,博主愈發覺得用創作博客來鞏固之前的學習內容的這種學習方法行之有效 —— 譬如:對學過的知識印象比以往更加清晰深刻,知識體系也在整理過程中逐漸脈絡分明。因此,博主下定決心,會將寫博客這一習慣長期堅持下去,創作博客也早已成為博主日常學習中不可或缺的一部分。
倘若你同樣是一名大學生,且打算未來從事 C++ 相關崗位,不妨關注博主。你可以通過博主的博客查漏補缺,梳理知識盲區,同時也能提前了解后續的學習方向,明晰技術進階路徑。
在此,博主鄭重許諾:只要今后博主仍在 IT 行業深耕,持續學習計算機相關知識,就一定會將所學內容整理成文,以博客的形式分享給大家,與大家共同成長。
所以,歡迎大家關注博主,讓博主成為你漫長學習道路上的同行者與見證者。博主期待以博客為橋梁,結識更多志同道合的朋友,一起在代碼的世界里披荊斬棘,攜手進步!
成就
在這段持續創作的時光里,博主撰寫了許多代碼示例,而《數據結構初階》系列博客中關于棧、隊列、鏈表等基礎數據結構的實現代碼,對于博主而言頗具特殊意義。
回想起初次接觸數據結構的經歷,那時的博主僅僅停留在書本上的名詞概念 —— 知道 “鏈表” 是一種鏈式存儲結構,“隊列” 遵循先進先出原則,卻從未真正動手實現過任何一個數據結構。
那些看似清晰的理論,在脫離文字描述后,往往暴露出許多模糊的細節:鏈表的頭指針該如何初始化?循環隊列的隊滿條件為何要設計為(rear + 1) % capacity == front
?這些問題一直縈繞在博主的腦海里,最后博主也醒悟了過來:我的目標是要找到的一個不錯的軟件開發工作,不應該只是跟著學校的教學要求走,作為一名合格的開發程序員,這些數據結構的實現應該都是信手捏來的事情。
而這次通過博客分享數據結構的實現代碼,對博主來說既是一場充滿挑戰的 “通關之旅”,也是見證成長的 “成就解鎖” 過程。
以鏈表為例,從最初頻繁出現的指針越界錯誤,到逐步理清malloc
分配內存與指針指向的邏輯。記得在實現循環隊列時,為了避免 “假溢出” 問題,反復推敲隊頭與隊尾指針的移動邏輯,甚至在草稿紙上畫出環形數組的狀態變化圖,最終才提煉出通過取模運算實現循環存儲的核心邏輯。這種從 “紙上談兵” 到 “落地成碼” 的轉變,不僅讓抽象概念變得觸手可及,更讓博主深刻體會到:數據結構的靈魂不在于定義,而在于如何用代碼讓其‘活起來’。
這些代碼或許不夠完美,卻真實記錄了博主從 “理論學習者” 到 “實踐創作者” 的蛻變。每一個malloc
與free
的配對,每一次條件判斷的調整,博主都能清晰地感覺到自己正在變得越來越熟練。
之前有看過博主寫的博客的小伙伴的都知道,博主的代碼片段中的經常會添加一些“注意:XXXXXXXXX。“,這樣的內容—— 這些看似瑣碎的提醒,實則是博主踩過無數 “坑” 后的經驗沉淀。對博主而言,它們不僅是技術的輸出,更是對曾經懵懂的自己的一次致敬:那些曾經覺得晦澀難懂的知識,如今竟能以代碼的形式清晰呈現,并成為幫助他人理解數據結構的橋梁。
博主撰寫的代碼示例中若要展示一段代碼的話,博主愿以循環隊列的 C 語言實現為例:
-----------------------------CircularQueue.c-----------------------------#include "CircularQueue.h"/*-----------------------------------------輔助工具函數-----------------------------------------*/
/*** @brief 檢查并擴容循環隊列的存儲空間** @param pcque 指向循環隊列的指針** @note 該函數完成以下工作:* 1. 檢查隊列是否已滿* 2. 計算新容量(初始為0時設為4,否則2倍擴容)* 3. 使用realloc擴容存儲數組* 4. 更新隊列的容量字段** @warning 擴容后不處理元素位置的調整(循環隊列可能需要特殊處理)*/
//1.實現:“循環隊列的擴容”輔助函數
void CQCheckCapacity(CQ* pcque)
{if (pcque->capacity == 0) //特殊處理初始情況{int newCapacity = 4;CQDataType* tmp = (CQDataType*)malloc(newCapacity * sizeof(CQDataType));if (!tmp) {perror("malloc fail");exit(EXIT_FAILURE);}pcque->a = tmp;pcque->capacity = newCapacity;}else if (pcque->size == pcque->capacity-1) //容量為capacity的循環隊列最多只能存儲capacity-1個元素{//1.1:判斷需要擴容的容量的大小int newCapacity = pcque->capacity * 2;//1.2:使用realloc進行擴容CQDataType* tmp = (CQDataType*)realloc(pcque->a, newCapacity*sizeof(CQDataType));if (tmp == NULL){perror("realloc fail");return;}//更新數組的指針 + 循環隊列的容量pcque->a = tmp;pcque->capacity = newCapacity;}
}//2.實現:“打印循環隊列”的輔助函數
void CQPrint(CQ* pcque)
{assert(pcque); //斷言檢查:確保隊列指針有效,防止對空指針進行解引用//情況1:循環隊列為空隊列if (CQEmpty(pcque)) return;//情況2:循環隊列非空隊列//2.1:定義一個變量記錄打印循環隊列中的元素的數量int count = 0;//2.2:循環打印隊列中的元素int pcur = pcque->front; //注意:這里一定要使用一個臨時的指針進行遍歷循環隊列,防止pcque指針的移動導致隊列結構錯亂while (count < pcque->size) {printf("%d ", pcque->a[pcur]);pcur = (pcur + 1) % pcque->capacity;count++;}printf("\n");
}/*-----------------------------------------核心功能函數-----------------------------------------*/
/*** @brief 初始化循環隊列** @param pcque 指向需要初始化的循環隊列結構體的指針** @note 該函數完成以下工作:* 1. 檢查指針有效性(斷言保護)* 2. 初始化隊列的基本狀態:* - 當前元素數量(size)置為0* - 當前隊列容量(capacity)置為0* - 隊頭指針(front)置為0* - 隊尾指針(rear)置為0* - 數據存儲數組指針(a)置為NULL** @warning* - 使用前必須確保pcque指針有效* - 該初始化不會分配存儲空間,首次插入元素時會自動擴容*/
//1.實現:“循環隊列的初始化”操作
void CQInit(CQ* pcque)
{assert(pcque); //斷言檢查:確保隊列指針有效,防止對空指針進行解引用pcque->size = 0;pcque->capacity = 0;pcque->front = 0;pcque->rear = 0;pcque->a = NULL;
}//2.實現:“循環隊列的銷毀”操作
void CQDestroy(CQ** ppcque)
{assert(ppcque); //斷言檢查1:確保傳入的指針是非空指針,防止對空指針進行解引用assert(*ppcque); //斷言檢查2:確保隊列指針有效,防止對空指針進行解引用(建議加上)/*----------第一步:釋放動態數組內存----------*/free((*ppcque)->a);(*ppcque)->a = NULL;/*----------第一步:重置隊列狀態----------*/(*ppcque)->size = (*ppcque)->capacity = 0;(*ppcque)->front = (*ppcque)->rear = 0;/*----------第一步:釋放隊列結構體內存----------*/free(*ppcque);*ppcque = NULL; //真正修改外部指針//(函數的形參需要是二級指針,如果使用的是一級指針,參數是值傳遞,在函數內部將ppcque置空,對外部指針無影響,外部指針將變為野指針)
}/*** @brief 判斷循環隊列是否為空** @param pcque 指向循環隊列結構體的指針(需確保非NULL)* @return bool 返回true表示隊列為空,false表示非空** @note 該函數實現循環隊列的判空邏輯:* 1. 使用斷言確保指針有效性(調試階段捕獲空指針)* 2. 直接比較隊頭指針(front)和隊尾指針(rear)* 3. 當front == rear時判定為空隊列*///3.實現:“循環隊列的判空”操作
bool CQEmpty(CQ* pcque)
{assert(pcque); //斷言檢查:確保隊列指針有效,防止對空指針進行解引用//判滿的核心邏輯:隊尾指針和隊頭指針指向同一個位置return pcque->front == pcque->rear; //循環隊列:空為true;非空為false
}/*** @brief 判斷循環隊列是否已滿** @param pcque 指向循環隊列結構體的指針* @return bool 返回true表示隊列已滿,false表示未滿** @note 該函數實現循環隊列的判滿邏輯:* 1. 使用取模運算實現循環指針計算* 2. 通過(rear+1) % capacity == front判斷隊列滿* 3. 預留一個空位區分隊列空和滿的狀態** @details 循環隊列判滿的數學原理:* - 隊列容量為capacity時,實際可以使用的是capacity-1個空間* - 當(rear+1) % capacity == front時:* a) 若front == rear,隊列為空* b) 否則,隊列已滿* - 這樣設計避免了使用額外標志位*/
//4.實現:“循環隊列的判滿”操作
bool CQFull(CQ* pcque)
{assert(pcque);//斷言檢查:確保隊列指針有效,防止對空指針進行解引用//判滿的核心邏輯:隊尾指針的下一個位置(取模后)等于隊頭指針return (pcque->rear + 1) % (pcque->capacity) == pcque->front; //循環隊列:滿為true;不滿為false/* 示例說明:* 假設capacity=4(實際可使用的是3個位置):** 情況1:隊列滿* front=0, rear=3* (3+1)%4 = 0 == front → 滿** 情況2:隊列未滿* front=0, rear=1* (1+1)%4 = 2 != front → 未滿** 情況3:隊列空* front=0, rear=0* (0+1)%4 = 1 != front → 未滿(與判空條件區分)*/
}/*** @brief 向循環隊列尾部插入一個元素** @param pcque 指向循環隊列的指針(需確保非NULL)* @param x 要插入的元素值** @note 該函數執行以下操作:* 1. 檢查隊列指針有效性(調試階段斷言保護)* 2. 檢查并擴容隊列容量(通過CQCheckCapacity)* 3. 在隊尾位置存入元素* 4. 更新隊尾指針(實現循環移動)*/
//5.實現:“循環隊列的入隊”操作
void CQPush(CQ* pcque, CQDataType x)
{assert(pcque); //斷言檢查:確保隊列指針有效,防止對空指針進行解引用CQCheckCapacity(pcque);//1.將入隊的元素的存儲在動態數組中pcque->a[pcque->rear] = x;//2.將循環隊列的尾指針向后移動pcque->rear++;//3.更新尾指針指向的正確的位置(處理越界的情況)pcque->rear = pcque->rear % (pcque->capacity);//4.更新當前循環隊列中元素的數量pcque->size++;
}/*** @brief 從循環隊列頭部移除一個元素(出隊操作)** @param pcque 指向循環隊列的指針(需確保非NULL)** @note 該函數執行以下操作:* 1. 檢查隊列指針有效性(斷言保護)* 2. 檢查隊列是否為空(空隊列直接返回)* 3. 移動隊頭指針實現出隊* 4. 處理指針越界(循環修正)*/
//6. 實現:“循環隊列的出隊”操作
void CQPop(CQ* pcque)
{assert(pcque);//斷言檢查:確保隊列指針有效,防止對空指針進行解引用//情況1:循環隊列為空if (CQEmpty(pcque)) return;//情況2:循環隊列非空//1.將循環隊列的頭指針向后移動pcque->front++;//2.更新頭指針指向正確的位置(處理越界的情況)pcque->front = pcque->front % (pcque->capacity);//3.更新當前循環隊列中元素的數量pcque->size--;
}//7.實現:“循環隊列的獲取隊頭的元素”操作
CQDataType CQFront(CQ* pcque)
{assert(pcque); //斷言檢查:確保隊列指針有效,防止對空指針進行解引用//情況1:循環隊列為空if (CQEmpty(pcque)) return -1;//情況2:循環隊列非空return pcque->a[pcque->front];
}/*** @brief 獲取循環隊列的隊尾元素** @param pcque 指向循環隊列的指針(需確保非NULL)* @return CQDataType 返回隊尾元素的值,隊列為空時返回-1(需根據實際數據類型調整)** @note 該函數執行以下操作:* 1. 檢查隊列指針有效性(斷言保護)* 2. 檢查隊列是否為空(空隊列返回-1)* 3. 計算隊尾元素的實際位置* 4. 返回隊尾元素值*/
//8.實現:“循環隊列的獲取隊尾的元素”操作
CQDataType CQRear(CQ* pcque)
{assert(pcque); //斷言檢查:確保隊列指針有效,防止對空指針進行解引用//情況1:循環隊列為空if (CQEmpty(pcque)) return -1;//情況2:循環隊列非空//返回隊尾的元素比返回隊頭的元素要復雜://原因:front指針指向的是隊頭的元素的位置;rear指針指向的是隊尾的元素的后一個位置//怎么讓隊尾指針指向它的前一個位置?真的是pcirque->tail--;這么簡單嗎?//情況1:rear指向數組索引為0的位置(特殊情況-->rear應該指向的是capacity的位置,而不是數組下標為-1的位置)//情況2:rear指向數組索引的其他位置(正常情況)return pcque->a[(pcque->rear - 1 + pcque->capacity) % (pcque->capacity)];/* 關鍵計算:獲取隊尾元素的實際位置1. pcque->rear - 1 :理論上隊尾元素在前一個位置2. + pcque->capacity :防止負數(當rear=0時)3. % pcque->capacity :確保結果在合法范圍內示例:- 當capacity=5, rear=0時:(0-1+5)%5=4- 當capacity=5, rear=3時:(3-1+5)%5=2*/
}
這段代碼通過數組模擬隊列空間,利用取模運算讓隊列在邏輯上形成環形結構,解決了普通隊列 “假溢出” 的問題,能高效完成入隊和出隊操作。
代碼里用front
和rear
兩個指針分別表示隊頭和隊尾位置,通過(rear + 1) % capacity == front
判斷隊列是否已滿,用front == rear
判斷是否為空,還設計了擴容函數在隊列滿時自動擴展空間,同時有打印函數方便查看隊列狀態,整體實現了循環隊列的基本功能和動態管理,讓隊列空間得到充分利用,操作也更高效。
上面的這段代碼不僅是《數據結構初階》系列的一個縮影,更體現了博主在梳理知識時的思考:如何用簡潔的邏輯實現復雜的數據結構?如何通過注釋和命名讓代碼更易讀?
未來,博主還將在博客中分享更多類似的實戰代碼與解析,希望能幫助讀者理解數據結構的底層邏輯,為進階學習打下堅實基礎。(如果你感覺這個博主還不錯,對你有幫助的話,也可以關注一下博主,紀念日里也不會忘記宣傳自己)
憧憬
前面博主也提到過,博主的打算是本科直接就業,所以博主也一直在為這一目標默默奮斗。
但是在漫長的學習準備階段,博主經常從網上聽到類似的聲音:“本科生找實習難于登天,僅有極少數人能成功,大部分學生只能落空” 和“C++ 崗位少之又少,本科生畢業根本找不到相關工作,學 C++ 等于‘畢業即失業’”和 “非 985、211 院校的學生就別碰 C++ 了,這門語言貼近底層,你們根本學不透,就算勉強學會,學歷不夠也會被篩掉”…… 諸如此類的言論,曾讓博主心生疑慮:自己真的能找到實習嗎?是否不該執著于 C++,轉而去學 Java 會更好?
但在聽取了 CSDN 上小伙伴的建議后,博主最終選擇繼續深耕 C++。畢竟 “打鐵還需自身硬”,外界的聲音或許反映了部分現實,但決定個人發展的核心始終是自身實力。或許 C++ 的就業形勢并非一片坦途,但博主堅信,只要全力以赴、專注深耕,就一定能有所收獲。
就業環境的好壞受社會周期影響,我們無法回到互聯網行業的 “黃金時代”,我們唯一可以做的就是把握當下 —— 努力提升技術能力,在競爭中積累優勢,為未來可能出現的機遇儲備足夠的底氣。
正因為打算直接就業,所以博主必須提前找到實習,確保在秋招前至少擁有一段實習經歷。因此,博主如今也是正在爭分奪秒地學習,力求盡快完善技術棧,如同游戲中 “快速發育、點滿技能點”,以便在未來的 “職場團戰” 中更具競爭力。
不過,在加速學習的同時,博主也面臨時間分配的挑戰 —— 為了保證博客能按時創作出來,博主經常感覺到時間不夠用。所以這一學期一些水課的平時分博主可能拿不到了,但是這個影響不大,請大家放心,博客更新絕不會中斷。目前仍有大量知識內容待梳理,后續博主會將每周更新頻率提升至 3 次,且會繼續保持高質量輸出,確保每一篇博文內容詳實、干貨滿滿。
好了,紀念日就紀念到這里吧,在此,想再和大家真誠地 “安利” 一番:
如果你目前還是學生,并且計劃未來從事 C++ 相關方向的工作,強烈建議關注博主!博主后續分享的博客內容,將緊密圍繞 C++ 就業所需的核心知識展開,涵蓋 C++ 基礎原理、數據結構與算法實戰、操作系統底層邏輯、項目開發經驗等關鍵領域。
即便現在,博主分享的內容與你的發展方向暫時不一致,也歡迎保持關注!博主始終相信,計算機技術的各個領域存在共通的底層邏輯與學習方法論。例如:數據結構的思維可遷移至任何編程語言,算法的優化思路能應用于各類場景。更何況,技術的發展日新月異,博主也會在深耕 C++ 的同時,持續探索其他領域,博主相信今后分享的內容一定會和你所在的領域不謀而合。
總之,關注博主不僅能獲取當下所需的 C++ 就業干貨,更能解鎖一個長期陪伴的技術成長伙伴~