C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)系列篇二叉樹(shù)的遍歷
前言:
學(xué)習(xí)二叉樹(shù)的基本操作前,需要先創(chuàng)建一顆二叉樹(shù),然后才能學(xué)習(xí)其相關(guān)的基本操作,考慮到我們剛剛接觸二叉樹(shù),為了能夠先易后難地進(jìn)行講解,我們將暫時(shí)手動(dòng)創(chuàng)建一顆簡(jiǎn)單的二叉樹(shù),用來(lái)方便大家學(xué)習(xí)。等二叉樹(shù)結(jié)構(gòu)了解的差不多后,后期我們會(huì)帶大家研究二叉樹(shù)地真正的創(chuàng)建方式。
Ⅰ. 定義二叉樹(shù)
0x00 二叉樹(shù)的概念(回顧)
我們之前講過(guò)二叉樹(shù)的概念了,這里我們簡(jiǎn)單的回顧下二叉樹(shù)的概念。
?? 復(fù)習(xí)鏈接:C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)系列篇二叉樹(shù)的概念及滿二叉樹(shù)與完全二叉樹(shù)
? 二叉樹(shù)是什么?① 空樹(shù) ② 非空:根節(jié)點(diǎn)、根節(jié)點(diǎn)的左子樹(shù)與根節(jié)點(diǎn)的又子樹(shù)組成的。
?? 解讀:從概念中我們不難看出,二叉樹(shù)的定義是遞歸式的。因此后續(xù)基本操作中,我們基本都是按照該概念來(lái)實(shí)現(xiàn)的!我們可以來(lái)看一下,我們不去看 A,我們來(lái)看 A 的左子樹(shù),把 B 看作為根節(jié)點(diǎn),是不是一顆二叉樹(shù)?
?? 所以,我們可以通過(guò)采用遞歸的手法來(lái)玩二叉樹(shù)。
0x00 定義二叉樹(shù)
?? BinaryTree.h:
typedef int BTDataType; typedef struct BinaryTreeNode { struct BinaryTreeNode* left; // 記錄左節(jié)點(diǎn) struct BinaryTreeNode* right; // 記錄右節(jié)點(diǎn) BTDataType data; // 存儲(chǔ)數(shù)據(jù) } BTNode;
?? 解讀:
① 還是老規(guī)矩,我們創(chuàng)建一個(gè)二叉樹(shù)的數(shù)據(jù)類(lèi)型 BTDataType 。
② 由于是鏈?zhǔn)蕉鏄?shù),根據(jù)二叉樹(shù)的概念我們定義出 left 和 right 來(lái)分別記錄根節(jié)點(diǎn)的左子樹(shù)與根節(jié)點(diǎn)的右子樹(shù),再創(chuàng)建一個(gè)變量來(lái)存儲(chǔ)節(jié)點(diǎn)中的數(shù)據(jù)即可。
③ 最后為了方便表達(dá),我們將這個(gè)結(jié)構(gòu)體 typedef 為 BTNode,因?yàn)?nbsp;"struct BinaryTreeNode" 比較麻煩。
0x01 手動(dòng)創(chuàng)建二叉樹(shù)
在學(xué)習(xí)二叉樹(shù)的基本操作前,需要先創(chuàng)建一顆二叉樹(shù),然后才能學(xué)習(xí)其相關(guān)的基本操作。由于我們剛剛接觸二叉樹(shù),為了能夠先易后難地學(xué)習(xí),我們手動(dòng)創(chuàng)建一顆簡(jiǎn)單的二叉樹(shù)來(lái)來(lái)方便大家學(xué)習(xí)。等二叉樹(shù)結(jié)構(gòu)了解后,后期我們會(huì)帶著讀者研究二叉樹(shù)地真正的創(chuàng)建方式。
?? 手動(dòng)創(chuàng)建一顆二叉樹(shù)(以上圖為例來(lái)創(chuàng)建)
/* 創(chuàng)建新節(jié)點(diǎn) */ BTNode* BuyNode(BTDataType x) { BTNode* new_node = (BTNode*)malloc(sizeof(BTNode)); if (new_node == NULL) { printf("malloc failed!\n"); exit(-1); } new_node->data = x; new_node->left = new_node->right = NULL; return new_node; } /* 手動(dòng)創(chuàng)建二叉樹(shù) */ BTNode* CreateBinaryTree() { BTNode* nodeA = BuyNode('A'); BTNode* nodeB = BuyNode('B'); BTNode* nodeC = BuyNode('C'); BTNode* nodeD = BuyNode('D'); BTNode* nodeE = BuyNode('E'); BTNode* nodeF = BuyNode('F'); nodeA->left = nodeB; nodeA->right = nodeC; nodeB->left = nodeD; nodeC->left = nodeE; nodeC->right = nodeF; return nodeA; } int main(void) { BTNode* root = CreateBinaryTree(); }
?? 畫(huà)圖解析:
Ⅱ. 二叉樹(shù)的遍歷
0x00 關(guān)于遍歷
學(xué)習(xí)二叉樹(shù)結(jié)構(gòu),最簡(jiǎn)單的方式就是遍歷。所謂二叉樹(shù)遍歷,就是按照某種特定的規(guī)則,一次對(duì)二叉樹(shù)中的節(jié)點(diǎn)進(jìn)行相應(yīng)的操作,并且每個(gè)節(jié)點(diǎn)只操作一次。 訪問(wèn)節(jié)點(diǎn)所做的操作要看具體的應(yīng)用問(wèn)題。遍歷是二叉樹(shù)上最重要的運(yùn)算之一,也是二叉樹(shù)上進(jìn)行其他運(yùn)算的基礎(chǔ)。
?? 二叉樹(shù)遍歷(Traversal):沿著某條搜索路線,依次對(duì)樹(shù)中每個(gè)結(jié)點(diǎn)均做一次且僅做一次訪問(wèn)。 按照規(guī)則,二叉樹(shù)的遍歷有:前序 / 中序 / 后序 的遞歸結(jié)構(gòu)遍歷。除了前序、中序和后續(xù)遍歷外,我們還可以對(duì)二叉樹(shù)進(jìn)行層序遍歷。
0x01 二叉樹(shù)前序遍歷
?? 前序遍歷(Preorder Traversal):訪問(wèn)根節(jié)點(diǎn)的操作發(fā)生在遍歷其右子樹(shù)之前。
即,首先訪問(wèn)根結(jié)點(diǎn),然后遍歷左子樹(shù),最后遍歷右子樹(shù)。
?? 代碼實(shí)現(xiàn)前序遍歷:
(這里我們用 Ø 符號(hào)來(lái)表示 NULL)
/* 二叉樹(shù)前序遍歷 */ void PreOrder(BTNode* root) { /* 首先判斷根是否為空,為空就返回 */ if (root == NULL) { printf("? "); // 暫時(shí)打印出來(lái),便于觀察 return; } /* 走到這里說(shuō)明不為空,根據(jù)前序遍歷,先訪問(wèn)根節(jié)點(diǎn) */ printf("%c ", root->data); /* 然后遍歷左子樹(shù)(利用遞歸) */ PreOrder(root->left); /* 最后遍歷右子樹(shù)(利用遞歸) */ PreOrder(root->right); }
?? 解讀:
① 首先判斷根是否為空,如果根為空,則返回。這里為了表示,我們把空節(jié)點(diǎn)以 " Ø " 打印出來(lái)。
② 如果跟不為空,這說(shuō)明有數(shù)據(jù)。由于是前序遍歷(Preorder),前序遍歷是先訪問(wèn)根節(jié)點(diǎn),然后遍歷左子樹(shù),最后再遍歷右子樹(shù)。所以,我們這里先要訪問(wèn)的是根節(jié)點(diǎn),我們把根節(jié)點(diǎn)的數(shù)據(jù)打印出來(lái)。
③ 然后我們需要遍歷左子樹(shù),這時(shí)我們利用遞歸就可以實(shí)現(xiàn)。將根節(jié)點(diǎn) root 的左數(shù) left 傳入 PreOrder 函數(shù)(將其左樹(shù)看作根),一直遞歸下去,直到碰到 root == NULL 則返回。
④ 最后,遍歷完左子樹(shù)后遍歷右子樹(shù)。利用遞歸,方法同上。
0x02 二叉樹(shù)中序遍歷
?? 中序遍歷(Inorder Traversal):訪問(wèn)根節(jié)點(diǎn)的操作發(fā)生在遍歷其左右子樹(shù)之中。
即,首先遍歷左子樹(shù),然后訪問(wèn)根結(jié)點(diǎn),最后遍歷右子樹(shù)。
/* 二叉樹(shù)中序遍歷 */ void InOrder(BTNode* root) { /* 首先判斷根是否為空,為空就返回 */ if (root == NULL) { printf("? "); // 暫時(shí)打印出來(lái),便于觀察 return; } /* 走到這里說(shuō)明不為空,根據(jù)中序遍歷,先遍歷左子樹(shù) */ InOrder(root->left); /* 然后訪問(wèn)根節(jié)點(diǎn)(利用遞歸) */ printf("? ", root->data); /* 最后遍歷右子樹(shù)(利用遞歸) */ InOrder(root->right); }
?? 解讀:
① 首先判斷根是否為空,如果根為空,則返回。
② 如果跟不為空,這說(shuō)明有數(shù)據(jù)。由于是中序遍歷(Inorder),中序遍歷是先遍歷左子樹(shù),然后訪問(wèn)根節(jié)點(diǎn),最后遍歷右子樹(shù)。
0x03 二叉樹(shù)后序遍歷
?? 后序遍歷(Postorder Traversal):訪問(wèn)根節(jié)點(diǎn)的操作發(fā)生在遍歷其左右子樹(shù)之后。
即,首先遍歷左子樹(shù),然后遍歷右子樹(shù),最后訪問(wèn)根結(jié)點(diǎn)。
/* 二叉樹(shù)后序遍歷 */ void PostOrder(BTNode* root) { /* 首先判斷根是否為空,為空就返回 */ if (root == NULL) { printf("/ "); return; } /* 走到這里說(shuō)明不為空,根據(jù)后序遍歷,先遍歷左子樹(shù)(利用遞歸) */ PostOrder(root->left); /* 然后遍歷右子樹(shù)(利用遞歸) */ PostOrder(root->right); /* 最后訪問(wèn)根節(jié)點(diǎn) */ printf("%c ", root->data); }
?? 解讀:
① 首先判斷根是否為空,如果根為空,則返回。
② 如果跟不為空,這說(shuō)明有數(shù)據(jù)。由于是后序遍歷(Postorder),后序遍歷是先遍歷左子樹(shù),然后遍歷右子樹(shù),最后訪問(wèn)根節(jié)點(diǎn)。
0x04 層序遍歷
?? 層序遍歷(Level Traversal):設(shè)二叉樹(shù)的根節(jié)點(diǎn)所在的層數(shù)為1的情況下,從二叉樹(shù)的根節(jié)點(diǎn)出發(fā),首先訪問(wèn)第1層的樹(shù)根節(jié)點(diǎn),然后再?gòu)淖蟮接以L問(wèn)第2層上的節(jié)點(diǎn)。接著是第3層的節(jié)點(diǎn)……以此類(lèi)推,自上而下、從左向右地逐層訪問(wèn)樹(shù)的節(jié)點(diǎn)。
? 該如何實(shí)現(xiàn)層序遍歷呢?
?? 我們可以利用隊(duì)列的性質(zhì)來(lái)實(shí)現(xiàn)!
我們之前再講過(guò)隊(duì)列,這里你可以選擇自己實(shí)現(xiàn)一個(gè)隊(duì)列。如果不想實(shí)現(xiàn)就直接 CV 即可,因?yàn)槲覀冞@里重點(diǎn)要學(xué)的是層序遍歷!
?? 鏈接:C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)系列隊(duì)列篇
?? Queue.h:
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <assert.h> typedef int QueueDataType; typedef struct QueueNode { struct QueueNode* next; QueueDataType data; } QueueNode; typedef struct Queue { QueueNode* pHead; QueueNode* pTail; } Queue; void QueueInit(Queue* pQ); //隊(duì)列初始化 void QueueDestroy(Queue* pQ); //銷(xiāo)毀隊(duì)列 bool QueueIfEmpty(Queue* pQ); //判斷隊(duì)列是否為空 void QueuePush(Queue* pQ, QueueDataType x); //入隊(duì) void QueuePop(Queue* pQ); //出隊(duì) QueueDataType QueueFront(Queue* pQ); //返回隊(duì)頭數(shù)據(jù) QueueDataType QueueBack(Queue* pQ); //返回隊(duì)尾數(shù)據(jù) int QueueSize(Queue* pQ); //求隊(duì)列大小
?? Queue.c:
#define _CRT_SECURE_NO_WARNINGS 1 #include "Queue.h" /* 隊(duì)列初始化 */ void QueueInit(Queue* pQ) { assert(pQ); pQ->pHead = pQ->pTail = NULL; } /* 銷(xiāo)毀隊(duì)列 */ void QueueDestroy(Queue* pQ) { assert(pQ); QueueNode* cur = pQ->pHead; while (cur != NULL) { QueueNode* cur_next = cur->next; free(cur); cur = cur_next; } pQ->pHead = pQ->pTail = NULL; } /* 判斷隊(duì)列是否為空 */ bool QueueIfEmpty(Queue* pQ) { assert(pQ); return pQ->pHead == NULL; } /* 入隊(duì) */ QueueNode* CreateNewNode(QueueDataType x) { QueueNode* new_node = (QueueNode*)malloc(sizeof(QueueNode)); if (new_node == NULL) { printf("malloc failed!\n"); exit(-1); } new_node->data = x; new_node->next = NULL; return new_node; } void QueuePush(Queue* pQ, QueueDataType x) { assert(pQ); QueueNode* new_node = CreateNewNode(x); if (pQ->pHead == NULL) { pQ->pHead = pQ->pTail = new_node; } else { pQ->pTail->next = new_node; pQ->pTail = new_node; } } /* 出隊(duì) */ void QueuePop(Queue* pQ) { assert(pQ); assert(!QueueIfEmpty(pQ)); QueueNode* save_next = pQ->pHead->next; free(pQ->pHead); pQ->pHead = save_next; if (pQ->pHead == NULL) { pQ->pTail = NULL; } } /* 返回隊(duì)頭數(shù)據(jù) */ QueueDataType QueueFront(Queue* pQ) { assert(pQ); assert(!QueueIfEmpty(pQ)); return pQ->pHead->data; } /* 返回隊(duì)尾數(shù)據(jù) */ QueueDataType QueueBack(Queue* pQ) { assert(pQ); assert(!QueueIfEmpty(pQ)); return pQ->pTail->data; } /* 求隊(duì)列大小 */ int QueueSize(Queue* pQ) { assert(pQ); int count = 0; QueueNode* cur = pQ->pHead; while (cur != NULL) { count++; cur = cur->next; } return count; }
這里為了方便講解 #include "展開(kāi)" 的特點(diǎn),我們把樹(shù)的定義放到 test.c 中,并且在 test.c 里完成層序遍歷。
?? test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "Queue.h" typedef char BTDataType; typedef struct BinaryTreeNode { struct BinaryTreeNode* left; struct BinaryTreeNode* right; BTDataType data; } BTNode; //#include "Queue.h" 解決方案? /* 創(chuàng)建新節(jié)點(diǎn) */ BTNode* BuyNode(BTDataType x) { BTNode* new_node = (BTNode*)malloc(sizeof(BTNode)); if (new_node == NULL) { printf("malloc failed!\n"); exit(-1); } new_node->data = x; new_node->left = new_node->right = NULL; return new_node; } /* 手動(dòng)創(chuàng)建二叉樹(shù) */ BTNode* CreateBinaryTree() { BTNode* nodeA = BuyNode('A'); BTNode* nodeB = BuyNode('B'); BTNode* nodeC = BuyNode('C'); BTNode* nodeD = BuyNode('D'); BTNode* nodeE = BuyNode('E'); BTNode* nodeF = BuyNode('F'); nodeA->left = nodeB; nodeA->right = nodeC; nodeB->left = nodeD; nodeC->left = nodeE; nodeC->right = nodeF; return nodeA; }
由于是我們的數(shù)據(jù)類(lèi)型是 BTNode,我們需要修改一下 Queue.h 的 QueueDataType,我們之前一直強(qiáng)調(diào)的 typedef 的好處,這里就顯現(xiàn)出來(lái)了。我們只需要把 int 改成 BTNode 就可以了,而不需要改很多地方。
?? Queue.h:
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <assert.h> typedef BTNode* QueueDataType; typedef struct QueueNode { struct QueueNode* next; QueueDataType data; } QueueNode; typedef struct Queue { QueueNode* pHead; QueueNode* pTail; } Queue; void QueueInit(Queue* pQ); //隊(duì)列初始化 void QueueDestroy(Queue* pQ); //銷(xiāo)毀隊(duì)列 bool QueueIfEmpty(Queue* pQ); //判斷隊(duì)列是否為空 void QueuePush(Queue* pQ, QueueDataType x); //入隊(duì) void QueuePop(Queue* pQ); //出隊(duì) QueueDataType QueueFront(Queue* pQ); //返回隊(duì)頭數(shù)據(jù) QueueDataType QueueBack(Queue* pQ); //返回隊(duì)尾數(shù)據(jù) int QueueSize(Queue* pQ); //求隊(duì)列大小
這時(shí)我們運(yùn)行一下代碼會(huì)出現(xiàn)一個(gè)問(wèn)題,我們發(fā)現(xiàn)它報(bào)錯(cuò)了:
它說(shuō),缺少 " { " ,這明顯是胡說(shuō)八道的,咱編譯器也沒(méi)有那么只能,畢竟是也不是VS2077。
? 這里產(chǎn)生問(wèn)題的原因是什么呢?
?? 編譯器原則:編譯器認(rèn)識(shí) int,因?yàn)?int 是一個(gè)內(nèi)置類(lèi)型。但是 BTNode* 編譯器并不認(rèn)識(shí),就需要 "往上面" 去找這個(gè)類(lèi)型。這里顯然往上找,是找不到它的定義的,所以編譯器會(huì)報(bào)錯(cuò)。
如果你要用這個(gè)類(lèi)型,你就需要先定義這個(gè)類(lèi)型。test.c文件中 #include "Queue.h" ,相當(dāng)于把這里的代碼拷貝過(guò)去了。這時(shí),由于BTNode*會(huì)在上面展開(kāi),導(dǎo)致找不到 BTNode* 。
? 我把 #include 移到 定義類(lèi)型的代碼 的后面,可以解決問(wèn)題嗎?
可以!遺憾的是只能解決這里 typedef BTNode* 的問(wèn)題,還有 Queue.c 里的問(wèn)題……
那我們?cè)撛趺醋觯軓氐捉鉀Q呢?
?? 解決方案:前置聲明。 這樣就不會(huì)帶來(lái)問(wèn)題了,滿足了先聲明后使用。
?? Queue.h (修改后):
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <assert.h> // 前置聲明 struct BinaryTreeNode; typedef struct BinaryTreeNode* QueueDataType; typedef struct QueueNode { struct QueueNode* next; QueueDataType data; } QueueNode; typedef struct Queue { QueueNode* pHead; QueueNode* pTail; } Queue; void QueueInit(Queue* pQ); //隊(duì)列初始化 void QueueDestroy(Queue* pQ); //銷(xiāo)毀隊(duì)列 bool QueueIfEmpty(Queue* pQ); //判斷隊(duì)列是否為空 void QueuePush(Queue* pQ, QueueDataType x); //入隊(duì) void QueuePop(Queue* pQ); //出隊(duì) QueueDataType QueueFront(Queue* pQ); //返回隊(duì)頭數(shù)據(jù) QueueDataType QueueBack(Queue* pQ); //返回隊(duì)尾數(shù)據(jù) int QueueSize(Queue* pQ); //求隊(duì)列大小
似乎有些扯遠(yuǎn)了,這塊在《維生素C語(yǔ)言》中沒(méi)有詳細(xì)的說(shuō),所以這里還是需要說(shuō)一下的。解決了這個(gè)報(bào)錯(cuò)的問(wèn)題后,我們就可以正式開(kāi)始寫(xiě)層序遍歷了。
?? 思路如下:
① 讓根節(jié)點(diǎn)先入隊(duì)。
② 記錄當(dāng)前隊(duì)頭后打印,并讓隊(duì)頭出隊(duì),然后檢測(cè),如過(guò)孩子不為空就把孩子帶進(jìn)去。
(上一層節(jié)點(diǎn)出隊(duì)時(shí)帶入下一層節(jié)點(diǎn)入隊(duì))
③ 只要隊(duì)列不為空就說(shuō)明還沒(méi)完。如果隊(duì)列為空,說(shuō)明下面最后一層沒(méi)有節(jié)點(diǎn),遍歷結(jié)束。
?? 注意事項(xiàng):使用完隊(duì)列后別忘了要銷(xiāo)毀!
?? 代碼實(shí)現(xiàn):
void BinaryTreeLevelOrder(BTNode* root) { if (root == NULL) { // 判斷根是否為空 return; } Queue pQ; // 建立隊(duì)列 QueueInit(&pQ); // 初始化隊(duì)列 QueuePush(&pQ, root); // 先讓根進(jìn)入隊(duì)列 while (!QueueIfEmpty(&pQ)) { // 只要隊(duì)列內(nèi)還有元素,就進(jìn)入循環(huán) BTNode* front = QueueFront(&pQ); // 記錄當(dāng)前對(duì)頭數(shù)據(jù) printf("%c ", front->data); // 打印隊(duì)頭數(shù)據(jù) QueuePop(&pQ); // 當(dāng)隊(duì)頭出隊(duì) if (front->left != NULL) { // 如果隊(duì)頭元素的左子樹(shù)不為空 QueuePush(&pQ, front->left); // 讓左子樹(shù)進(jìn)入隊(duì)列 } if (front->right != NULL) { // 如果對(duì)頭元素的右子樹(shù)不為空 QueuePush(&pQ, front->right); // 讓右子樹(shù)進(jìn)入隊(duì)列 } } QueueDestroy(&pQ); // 銷(xiāo)毀隊(duì)列 }
?? 解讀:
① 首先判斷根是否為空,如果為空就沒(méi)有必要往下走了。
② 建立和初始化隊(duì)列后,首先讓根節(jié)點(diǎn)進(jìn)入隊(duì)列。只要隊(duì)列內(nèi)還有元素存在(說(shuō)明還沒(méi)遍歷完)就進(jìn)入循環(huán)。每次循環(huán)進(jìn)入后都記錄一下當(dāng)前隊(duì)頭,這里使用 QueueFront 取隊(duì)頭數(shù)據(jù)即可。之后打印對(duì)頭的數(shù)據(jù)。
③ 打印完后讓隊(duì)頭出隊(duì),隨后判斷它的左子樹(shù)和右子樹(shù),如果不為空就允許它們進(jìn)隊(duì)。我們先判斷 left,再判斷 right,這樣就可以做到一層一層從左往右走的效果了。
④ 最后使用完隊(duì)列后,別忘了銷(xiāo)毀隊(duì)列!
參考資料:
Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .
百度百科[EB/OL]. []. https://baike.baidu.com/.
?? 筆者:王亦優(yōu)
?? 更新: 2022.1.12
? 勘誤: 無(wú)
?? 聲明: 由于作者水平有限,本文有錯(cuò)誤和不準(zhǔn)確之處在所難免,本人也很想知道這些錯(cuò)誤,懇望讀者批評(píng)指正!
本篇完。
到此這篇關(guān)于C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)系列篇二叉樹(shù)的遍歷的文章就介紹到這了,更多相關(guān)C語(yǔ)言 二叉樹(shù)遍歷內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)字符串轉(zhuǎn)浮點(diǎn)函數(shù)的示例
字符串不僅可以轉(zhuǎn)換為整數(shù),也可以轉(zhuǎn)換為浮點(diǎn)數(shù),本文主要介紹了C語(yǔ)言實(shí)現(xiàn)字符串轉(zhuǎn)浮點(diǎn)函數(shù)的示例,具有一定的參考價(jià)值,感興趣的可以了解一下2022-02-02基于c++ ege圖形庫(kù)實(shí)現(xiàn)五子棋游戲
這篇文章主要為大家詳細(xì)介紹了基于c++ ege圖形庫(kù)實(shí)現(xiàn)五子棋游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12C++實(shí)現(xiàn)LeetCode(692.前K個(gè)高頻詞)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(692.前K個(gè)高頻詞),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08C++實(shí)現(xiàn)十大排序算法及排序算法常見(jiàn)問(wèn)題
法是程序的靈魂,無(wú)論學(xué)習(xí)什么語(yǔ)言,做什么工程項(xiàng)目,都要考慮算法的效率實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于C++實(shí)現(xiàn)十大排序算法及排序算法常見(jiàn)問(wèn)題的相關(guān)資料,需要的朋友可以參考下2021-09-09詳解c語(yǔ)言實(shí)現(xiàn)的內(nèi)存池(適用于兩個(gè)線程、不加鎖、效率高)
這篇文章主要介紹了c語(yǔ)言實(shí)現(xiàn)的內(nèi)存池(適用于兩個(gè)線程、不加鎖、效率高),設(shè)計(jì)一個(gè)內(nèi)存池,要求效率比系統(tǒng)調(diào)用的效率要高(測(cè)試1萬(wàn)次),同時(shí)支持一個(gè)線程申請(qǐng),另外一個(gè)線程釋放,需要的朋友可以參考下2024-02-02C++?Boost?MultiArray簡(jiǎn)化使用多維數(shù)組庫(kù)
Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱(chēng)。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開(kāi)發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱(chēng)2022-11-11C++實(shí)現(xiàn)高校教室管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)高校教室管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03