用C語言把一棵普通二叉樹安排得明明白白

1. 樹的相關術語

結點的度:一個結點含有的子樹的個數稱為該結點的度; 如上圖:A的為6

葉結點或終端結點:度為0的結點稱為葉結點; 如上圖:B、C、H、I...等結點為葉結點

非終端結點或分支結點:度不為0的結點; 如上圖:D、E、F、G...等結點為分支結點

雙親結點或父結點:若一個結點含有子結點,則這個結點稱為其子結點的父結點; 如上圖:A是B的父結點

孩子結點或子結點:一個結點含有的子樹的根結點稱為該結點的子結點; 如上圖:B是A的孩子結點

兄弟結點:具有相同父結點的結點互稱為兄弟結點; 如上圖:B、C是兄弟結點

樹的度:一棵樹中,最大的結點的度稱為樹的度; 如上圖:樹的度為6

結點的層次:從根開始定義起,根為第1層,根的子結點為第2層,以此類推;

樹的高度或深度:樹中結點的最大層次; 如上圖:樹的高度為4

堂兄弟結點:雙親在同一層的結點互為堂兄弟;如上圖:H、I互為兄弟結點

結點的祖先:從根到該結點所經分支上的所有結點;如上圖:A是所有結點的祖先

子孫:以某結點為根的子樹中任一結點都稱為該結點的子孫。如上圖:所有結點都是A的子孫

森林:由m(m>0)棵互不相交的樹的集合稱為森林;

滿二叉樹:深度為k且有2^{k}-1個結點的二叉樹。在滿二叉樹中,每層結點都是滿的,即每層結點都具有最大結點數。

滿二叉樹的順序表示:從二叉樹的根開始,按層間從上到下,層內從左到右的順序進行編號(0,1,2,……,n-1)。

完全二叉樹:深度為k,結點數為n的二叉樹,如果其結點0~n-1的位置序號分別與等高的滿二叉樹的結點1~n-1的位置序號一一對應,則為完全二叉樹。完全二叉樹的特點為:(1)葉子結點只可能出現在最后兩層;(2)度數為1的結點個數為0或1。

?2. 二叉樹的性質

性質1:在二叉樹的第i層上至多有2^{i-1}個結點(i>=1)

性質2:深度為k的二叉樹至多有2^{k}-1個結點(k>=1)

性質3:對任意一棵二叉樹T,若終端結點數為n_{1},而其度數為2的結點數為n_{2},則? ? ? ? ? ? ? ? ? ? ? ? ? ? ?n_{1} = n_{2}+1

性質4:具有n個結點的完全二叉樹的深度為(log_{2}n)+1

性質5:對于具有n個結點的完全二叉樹,如果按照從上到下,從左到右的順序對完全二叉樹? ? ? ? ? ? ? ?中的所有結點從0開始編號,則對于任意序號為i的結點,其雙親結點的序號為? ? ? ? ? ? ? ? ? ? ? ? ?(i-1)/2,左孩子的序號為2*i+1,右孩子的序號為2*i+2。

證明略,但是上面的性質5在堆中有較為重要價值,在上一篇文章中有證明:全面詳解堆-CSDN博客?

1. 二叉樹的聲明以及要實現的接口

typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;// 通過前序遍歷的數組"ABD##E#H##CF##G##"構建二叉樹
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉樹銷毀
void BinaryTreeDestory(BTNode** root);
// 二叉樹節點個數
int BinaryTreeSize(BTNode* root);
// 二叉樹葉子節點個數
int BinaryTreeLeafSize(BTNode* root);
// 二叉樹第k層節點個數
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉樹查找值為x的節點
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉樹前序遍歷 
void BinaryTreePrevOrder(BTNode* root);
// 二叉樹中序遍歷
void BinaryTreeInOrder(BTNode* root);
// 二叉樹后序遍歷
void BinaryTreePostOrder(BTNode* root);
// 層序遍歷
void BinaryTreeLevelOrder(BTNode* root);
// 判斷二叉樹是否是完全二叉樹
int BinaryTreeComplete(BTNode* root);
//樹的高度
int TreeHeight(BTNode* root);

2. 通過前序遍歷數組構建二叉樹

在對二叉樹進行操作之前,我們需要有一棵二叉樹。

根據二叉樹的用途不同,在二叉樹中插入元素的方式繁多且復雜,在初學階段不需要太多的了解。

于是,我們可以采用暴力構建二叉樹的方式,也就是手動實現結點之間的相互鏈接關系:

BTNode* BuyNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->left = NULL;newnode->right = NULL;return newnode;
}BTNode* CreatBinaryTree()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}

但是,按照這種方式來構建樹,每個不同的樹都需要我們編寫邏輯來實現,十分的麻煩。

由于包含空指針表示的前序遍歷序列與二叉樹之間存在著一一對應的關系,所以,我們可以采用將前序遍歷數組還原為樹的方式來構建樹(前序最好理解,中序后序調整子樹創建順序即可):

// 通過前序遍歷的數組"ABD##E#H##CF##G##"構建二叉樹
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{if (*pi >= n || a[*pi] == '#'){(*pi)++;return NULL;}else{BTNode* root = BuyNode(a[*pi]);(*pi)++;root->left = BinaryTreeCreate(a, n, pi);root->right = BinaryTreeCreate(a, n, pi);return root;}
}

a為存放前序遍歷序列的數組,'#'表示當前結點為空指針;

n表示數組a的元素個數;

pi為表示當前數組下標的變量的指針,初始值為0,每有一個元素加入到樹中,(*pi)++。

3. 二叉樹銷毀

?這里采用的是后序遍歷來釋放結點,否則需要定義變量來記錄左右子樹的根結點。

// 二叉樹銷毀
void BinaryTreeDestory(BTNode** root)
{if (*root == NULL)return;else{BinaryTreeDestory(&((*root)->left));BinaryTreeDestory(&((*root)->right));free(*root);*root = NULL;}
}

4. 二叉樹的結點個數

利用遞歸即可解決,整棵樹的結點數 = 左子樹的結點數 + 根結點(1個)+ 右子樹的結點數

同理,左右子樹也是相同的邏輯。

某棵子樹(某結點的左子樹或右子樹)為空時,返回0。

// 二叉樹節點個數
int BinaryTreeSize(BTNode* root)
{if (root == NULL)return 0;return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

5. 二叉樹的葉子結點數

與上面的算法相似,但是此處我們只統計葉子結點數。

葉子結點區別于其他結點的特點是,其左右孩子都為空,如果當前結點符合條件我們就返回1,表示當前結點為葉子結點。

假如當前結點不是葉子結點,那么:

以當前結點為根的子樹的葉子結點數 = 左子樹葉子結點數 + 右子樹葉子結點數。

等式中不再包含根結點。

// 二叉樹葉子節點個數
int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL)return 0;if (root->left == NULL && root->right == NULL)return 1;return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

6. 二叉樹第k層的結點數

同樣的遞歸思路,第k層結點數 = 左子樹第k-1層結點數 + 右子樹第k-1層結點數

但是我們需要一個參數k來判斷當前結點位于第幾層,以及是否需要返回。

每深入一層,k就減1,當k等于1時返回1,表示已找到一個所求結點。

// 二叉樹第k層節點個數
int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL)return 0;if (k == 1)return 1;return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

7. 查找值為x的結點

如果當前結點的值為x,則直接返回當前結點。

否則,先到左子樹進行尋找,若左子樹沒有(返回值為NULL)就找右子樹。

// 二叉樹查找值為x的節點
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL)return NULL;if (root->data == x)return root;BTNode* Find = BinaryTreeFind(root->left, x);if (Find == NULL){Find = BinaryTreeFind(root->right, x);}return Find;
}

8.二叉樹的遞歸與非遞歸遍歷

二叉樹的遞歸遍歷較為簡單,但是非遞歸算法卻十分復雜,需要用到棧來模擬遞歸進行實現。

在該文章中有詳細介紹:棧與遞歸的實現-CSDN博客

9. 樹的高度

樹的高度指樹中結點的最大層次。

所以樹的高度 = 左子樹與右子樹中較高者的高度 + 1(根結點)。

//樹的高度
int TreeHeight(BTNode* root)
{if (root == NULL)return 0;int leftHeight = TreeHeight(root->left);int rightHeight = TreeHeight(root->right);return (leftHeight > rightHeight ? leftHeight : rightHeight) + 1;
}

?10. 層序遍歷

層序遍歷也就是廣度優先遍歷,實現這個算法需要用到隊列的幫助。

由于C語言不支持隊列,所以在這里寫了一個簡易的隊列。

其中,Get函數會在獲取隊頭結點的同時將其出隊,這樣實現對于我們當前算法的實現來說,使用起來更加方便。

當然,下面這段代碼只是幫助理解,直接忽略也可,只要你知道我對隊列進行了什么操作。

typedef BTNode* QDataType;// 鏈式結構:表示隊列 
typedef struct QListNode
{struct QListNode* _next;QDataType _data;
}QNode;// 隊列的結構 
typedef struct Queue
{QNode* _front;QNode* _rear;int size;
}Queue;//初始化
void Inite(Queue* q)
{q->size = 0;q->_front = NULL;q->_rear = NULL;
}//入隊
void Push(Queue* q, QDataType x)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->_data = x;newnode->_next = NULL;if (q->_rear == NULL){q->_front = q->_rear = newnode;}else{q->_rear->_next = newnode;q->_rear = newnode;}q->size++;
}//出隊
QDataType Get(Queue* q)
{if (q->size == 0)return NULL;QDataType temp = q->_front->_data;QNode* del = q->_front;if (q->size == 1){q->_rear = NULL;}q->_front = q->_front->_next;free(del);q->size--;return temp;
}//銷毀隊列
void DestroyQueue(Queue* q)
{QDataType temp;while (q->_front){temp = Get(q);}
}

基本思路就是:

1. 出隊得到一個結點并訪問。

2. 如果當前結點有孩子,則將其孩子全部入隊。

3. 不斷重復以上兩步,知道隊中無結點。

// 層序遍歷
void BinaryTreeLevelOrder(BTNode* root)
{Queue q;Inite(&q);Push(&q, root);BTNode* cur = NULL;while (cur = Get(&q)){printf("%c ", cur->data);if(cur->left != NULL)Push(&q, cur->left);if(cur->right != NULL)Push(&q, cur->right);}DestroyQueue(&q);
}

?11. 判斷二叉樹是否是完全二叉樹

根據完全二叉樹的特點,我們總結出以下判斷標準:

1. 如果某個結點只有右孩子而沒有左孩子,則該樹一定不是完全二叉樹。

2. 如果某個結點不是滿的(缺少左孩子或右孩子),則位置序號在其之后的結點一定既沒有? ? ? 左孩子,又沒有右孩子,否則就是非完全二叉樹。

// 判斷二叉樹是否是完全二叉樹
int BinaryTreeComplete(BTNode* root)
{Queue q;Inite(&q);Push(&q, root);BTNode* cur = NULL;do{cur = Get(&q);if (cur->left == NULL && cur->right != NULL)return 0;else if(cur->left != NULL && cur->right != NULL){Push(&q, cur->left);Push(&q, cur->right);}} while (cur->right);while (q.size != 0){cur = Get(&q);if (cur->left != NULL || cur->right != NULL)return 0;}return 1;DestroyQueue(&q);
}

12. oj練習

12.1 單值二叉樹. - 力扣(LeetCode)

第一種思路:保存根結點的值,然后用其與所有結點進行比較。

bool judge(struct TreeNode* root, int com)
{if(root == NULL)return true;if(root->val != com)return false;return judge(root->left, com) && judge(root->right, com);
}bool isUnivalTree(struct TreeNode* root) {int com = root->val;return judge(root, com);
}

為了提高代算法的效率,也可以將com變量改為全局變量。

第二種思路:我們找到題目要求的一個等價條件——除了葉子結點,所有結點的值都與自己孩子的值相等。

bool isUnivalTree(struct TreeNode* root) {if(root == NULL)return true;if(root->left && root->left->val != root->val || root->right && root->right->val != root->val)return false;return isUnivalTree(root->left) && isUnivalTree(root->right);
}

12.2 相同的樹. - 力扣(LeetCode)

采用遞歸的思路,兩棵樹相同意味著他們:根結點相同,左子樹相同,右子樹相同。

左右子樹相同,包括左右子樹都為空的情況。

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {if(p == NULL && q == NULL)return true;if(p == NULL || q == NULL || p->val != q->val)return false;return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

12.3 對稱的樹. - 力扣(LeetCode)

?

觀察示例可以發現,這道題可以采用與上道題如出一轍的思路,只不過我們要比較的兩棵樹是根結點的左右子樹。

同時,比較的邏輯也需要更改,左子樹的右孩子應該與右子樹的左孩子比較,左子樹的左孩子應該與右孩子的右子樹比較。

bool judge(struct TreeNode* root1, struct TreeNode* root2)
{if(root1 == NULL && root2 == NULL)return true;if(root1 == NULL || root2 == NULL || root1->val != root2->val)return false;return judge(root1->left, root2->right) && judge(root1->right, root2->left);
}bool isSymmetric(struct TreeNode* root) {return judge(root->left, root->right);
}

12.4 另一棵樹的子樹. - 力扣(LeetCode)

這道題可以利用到“相同的樹”那道題的函數,我們只需要遍歷root,然后將其的子樹依次與subRoot進行比較即可。

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {if(p == NULL && q == NULL)return true;if(p == NULL || q == NULL || p->val != q->val)return false;return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){if(root == NULL)return false;if(isSameTree(root, subRoot))return true;return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

12.5 二叉樹的前序遍歷. - 力扣(LeetCode)

?這道題并不是簡單地對二叉樹進行前序遍歷,而是要求我們返回存儲前序遍歷序列的數組。

首先需要動態開辟一個存儲結果的數組,但問題是開辟多少合適呢?

當然,在這道題中我們可以直接開辟100個空間的數組。

假如我們不知道這么一個條件呢?

可以用動態的順序表來管理,但鑒于需要我們自己實現,似乎就有點麻煩。

這時,我們就可以用到上面的BinaryTreeSize函數了,先求出樹中的結點個數,再進行我們接下來的操作。

與利用前序遍歷數組構建二叉樹相同,我們這里也需要一個pi來指示數組當前的下標。

下面的這段代碼中,直接用returnSize來充當了這個pi。

int TreeSize(struct TreeNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}void pretraversal(struct TreeNode* root, int* arr, int* pi)
{if(root == NULL)return;arr[*pi] = root->val;(*pi)++;pretraversal(root->left, arr, pi);pretraversal(root->right, arr, pi);
}int* preorderTraversal(struct TreeNode* root, int* returnSize) {int* arr = (int*)malloc(sizeof(arr) * TreeSize(root));*returnSize = 0;pretraversal(root, arr, returnSize);return arr;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13557.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13557.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13557.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Linux】-Tomcat安裝部署[12]

目錄 簡介 安裝 安裝部署JDK環境 解壓并安裝Tomcat 簡介 Tomcat是由Apache開發的一個Servlet容器,實現了對Servlet和JSP的支持,并提供了作為Web服務器的一些特有功能,如Tomcat管理和控制平臺、安全域管理和Tomcat閥等。 簡單來說&#…

使用 mysql-binlog-connector 監聽處理 MySQLBinlog 文件

1. 需求概述 業務開發中經常需要根據一些數據變更實現相對應的操作。例如,一些用戶注銷自己的賬戶,系統可以給用戶自動發短信確認,這時有兩種解決方案,一種是耦合到業務系統中,當用戶執行注銷操作的時候,執…

【軟件工程】【23.10】p2

關鍵字: 軟件復用技術、過程途徑、特定需求是文檔核心、數據字典條目、高內聚低耦合獨立性、數據流圖映射模塊結構圖、UML依賴、用例圖關系、RUB迭代、程序規格說明等價類劃分、有效性測試的目標、噴泉模型面向對象、軟件驗證過程、CMMI

算法提高之程序自動分析

算法提高之程序自動分析 核心思想&#xff1a;并查集 離散化 因為不是每個數都會用到 所以離散化一下**(不需要保留順序)**對于每一個值為1的等式 優先處理之后處理值為0的等式時 若ab已經連在一起 即為矛盾 #include <iostream>#include <cstring>#include &l…

【Linux】Centos7安裝RabbitMQ

【Linux】Centos7安裝RabbitMQ 下載 從 rabbitmq 的 GitHub 倉庫下載 https://github.com/rabbitmq/rabbitmq-server/releases rabbitmq 是 erlang 語言編寫的&#xff0c;需要先安裝 erlang https://github.com/rabbitmq/erlang-rpm/releases 安裝 使用rz命令上傳 erlang 和 …

Polar 網站被黑

Polar 網站被黑 開題&#xff0c;挺好看的前端&#xff0c;可惜啥也沒有。 信息搜集一波&#xff0c;掃目錄出現幾個敏感目錄&#xff0c;但是沒什么用。 繼續搜集&#xff0c;在返回包中發現了HINT F5XDAXZQNZSV6ZRRNZSF63JTF4base32解碼后是一個路由/n0_0ne_f1nd_m3/&#x…

數據倉庫實驗四:聚類分析實驗

目錄 一、實驗目的二、實驗內容和要求三、實驗步驟1、建立數據表2、建立數據源視圖3、建立挖掘結構Student.dmm4、部署項目并瀏覽結果5、挖掘模型預測 四、實驗結果分析五、實驗總結體會 一、實驗目的 通過本實驗&#xff0c;進一步理解基于劃分的、基于層次的、基于密度的聚類…

Easy-poi 和 EasyExcel 選型

目錄 共同點地址如何選 共同點 easy-poi 和 easyexcel 都是基于 apache poi 進行二次開發的&#xff0c;底層都是依賴的 apache poi使用簡單&#xff0c;都可以通過簡單的注解實現excel文件的導入導出 地址 esay poi 是一個開源的 excel,word 處理框架。鏈接 easy excel 是…

Xed編輯器開發第二期:使用Rust從0到1寫一個文本編輯器

第三篇 這部分接著處理用戶退出命令以及一些其他新功能&#xff1b; 3.1 使用CtrlQ退出 modifiers: event::KeyModifiers::CONTROL,使用CONTROL替換之前的NONE值即可&#xff1b; 3.2 重構鍵盤輸入 讓我們重構我們的代碼&#xff0c;以便我們有一個用于低級按鍵讀取的函數&…

《Rust奇幻之旅:從Java和C++開啟》第1章Hello world 2/5

講動人的故事,寫懂人的代碼 很多程序員都在自學Rust。 ??但Rust的學習曲線是真的陡,讓人有點兒怵頭。 程序員工作壓力大,能用來自學新東西的時間簡直就是鳳毛麟角。 ??目前,在豆瓣上有7本Rust入門同類書。它們雖有高分評價,但仍存在不足。 首先,就是它們介紹的Rust新…

【前端面經】BFC

BFC BFC什么是 BFC&#xff1f;元素開啟 BDC 后的特殊布局效果元素開啟 BFC 的方式 BFC 什么是 BFC&#xff1f; 官方解釋&#xff1a;A block formatting context (BFC) is a part of a visual CSS rendering of a web page. It’s the region in which the layout of block…

什么是谷歌爬蟲?

其實就是谷歌用來瀏覽網絡信息的一個自動化程序&#xff0c;他們會在你的網站爬取&#xff0c;尋找和搜集信息&#xff0c;谷歌爬蟲可以說決定著一個網站在谷歌的生死 谷歌爬蟲的作用機制就在于發現新網站以及新網頁&#xff0c;然后他會把網頁的內容帶回去&#xff0c;更新到…

PikaUnsafe upfileupload

1.client check 客戶端檢測&#xff0c;前端js檢測&#xff0c;禁用js和修改后綴名即可。 php格式不能上傳&#xff0c;我們修改后綴上傳。 蟻劍成功連接。 2.MIME type 這個就是 content-type 規定上傳類型&#xff0c;上面的方法也能成功&#xff0c;也可以修改 conten-ty…

面試框架【面試準備】

前言 2023-9-12 12:12:04 2023-09-14 16:13:04 公開發布于 2024-5-22 00:16:21 以下內容源自《【面試準備】》 僅供學習交流使用 版權 禁止其他平臺發布時刪除以下此話 本文首次發布于CSDN平臺 作者是CSDN日星月云 博客主頁是https://blog.csdn.net/qq_51625007 禁止其他平…

奇偶數遞增遞減-第13屆藍橋杯選拔賽Python真題精選

[導讀]&#xff1a;超平老師的Scratch藍橋杯真題解讀系列在推出之后&#xff0c;受到了廣大老師和家長的好評&#xff0c;非常感謝各位的認可和厚愛。作為回饋&#xff0c;超平老師計劃推出《Python藍橋杯真題解析100講》&#xff0c;這是解讀系列的第70講。 奇偶數遞增遞減&a…

vite+ts+mock+vue-router+pinia實現vue的路由權限

0.權限管理 前端的權限管理主要分為如下&#xff1a; 接口權限路由權限菜單權限按鈕權限 權限是對特定資源的訪問許可&#xff0c;所謂權限控制&#xff0c;也就是確保用戶只能訪問到被分配的資源 1.項目搭建 創建vite項目 yarn create vite配置別名 npm install path -…

4. C++入門:內聯函數、auto關鍵字、范圍for及nullptr

內聯函數 概念 以inline修飾的函數叫做內聯函數&#xff0c;編譯時C編譯器會在調用內聯函數的地方展開&#xff0c;沒有函數調用建立棧幀的開銷&#xff0c;內聯函數提升程序運行的效率 對比C的宏 C語言不足&#xff1a;宏 #define ADD(x, y) ((x)(y))int main() {int ret…

python實現520表白圖案

今天是520哦&#xff0c;作為程序員有必要通過自己的專業知識來向你的愛人表達下你的愛意。那么python中怎么實現繪制520表白圖案呢&#xff1f;這里給出方法&#xff1a; 1、使用圖形庫&#xff08;如turtle&#xff09; 使用turtle模塊&#xff0c;你可以繪制各種形狀和圖案…

Docker 安裝kingbase V8r6

下載 官網下載&#xff0c;注意&#xff1a;這里下載 Docker 版本v8r6 安裝 # 導入鏡像 docker load -i kingbase.tar# 重命名 docker tag [image-name]:[tag] [new-image-name]:[new-tag]# 刪除 docker rmi [image-name]:[tag]# 創建容器 docker run -tid \ --privileged \…

python實現繪制煙花代碼

在Python中&#xff0c;我們可以使用多個庫來繪制煙花效果&#xff0c;例如turtle庫用于簡單的繪圖&#xff0c;或者更復雜的庫如pygame或matplotlib結合動畫。但是&#xff0c;由于turtle庫是Python自帶的&#xff0c;我們可以使用它來繪制一個簡單的煙花效果。 下面是一個使…