tft每日頭條

 > 生活

 > 樹與二叉樹的基本知識

樹與二叉樹的基本知識

生活 更新时间:2025-02-01 13:57:46

def: 樹是n個結點的有限集合

非空樹應該滿足一下幾點

1)有且隻有一個特定的稱為根的結點.

2)當n>1,其餘結點可分為m個互不相交的有限集合

樹的定義是遞歸的

樹适合表示具有層次結構的數據

樹的性質

樹與二叉樹的基本知識(樹與二叉樹基本操作)1

已經調整過了,但還是歪啦

二叉樹

def: 是另外一種樹形結構,特點是每個結點嘴都隻有2棵子樹,子樹有左右之分,順序不能颠倒

特殊形式(滿二叉樹 完全二叉樹 二叉排序樹 平衡二叉樹)

性質:

樹與二叉樹的基本知識(樹與二叉樹基本操作)2

二叉樹遍曆(算法模闆片段)

void PreOrder(BiTree T)//先序遍曆 { if (T != NULL); { visit(T); PreOrder(T->lchild); preOrder(T->rchild); } } void InOrder(BiTree T)//中序遍曆 { if (T != NULL); { PreOrder(T->lchild); visit(T); PreOrder(T->rchild); } } void PostOrder(BiTree T)//後序遍曆 { if (T != NULL); { PreOrder(T->lchild); PreOrder(T->rchild); visit(T); } } void LevelOrder(BiTree T)//層次遍曆 { InitQueue(Q);//初始化輔助隊列 BiTree p; EnQueue(Q, T);//根節點入隊 while (!IsEmpty(Q))//隊列不空循環 { DnQueue(Q, p);//隊頭元素出隊 visit(p); if (p->lchild = NULL) EnQueue(Q, p->lchild);//左子樹不空,則入隊 if (p->rchild = NULL) EnQueue(Q, p->rchild);//右子樹不空,則入隊 } }

樹的遍曆實例代碼(簡單的先,中,後遍曆,所以沒有注釋)

#include<stdio.h> #include<stdlib.h> #include<string.h> struct BiTNode { int data; struct BiTNode *lchild, *rchild; }; typedef struct BiTNode BiTNode; typedef struct BiTNode BiTree; void preOrder(BiTNode *root) { if (root == NULL) { return; } printf("%d", root->data); preOrder(root->lchild); preOrder(root->rchild); } void inOrder(BiTNode *root) { if (root == NULL) { return; } inOrder(root->lchild); printf("%d", root->data); inOrder(root->rchild); } void postOrder(BiTNode *root) { if (root == NULL) { return; } postOrder(root->lchild); postOrder(root->rchild); printf("%d", root->data); } void main() { BiTNode t1, t2, t3, t4, t5; memset(&t1, 0, sizeof(BiTNode)); memset(&t2, 0, sizeof(BiTNode)); memset(&t3, 0, sizeof(BiTNode)); memset(&t4, 0, sizeof(BiTNode)); memset(&t5, 0, sizeof(BiTNode)); t1.data = 1; t2.data = 2; t3.data = 3; t4.data = 4; t5.data = 5; t1.lchild = &t2; t1.rchild = &t3; t2.lchild = &t4; t3.lchild = &t5; preOrder(&t1); inOrder(&t1); postOrder(&t1); printf("hello...\n"); system("pause"); return; }

計算葉子節點個數(核心代碼)

把全局變量變成參數

void coutLeaf(BiTNode *T,int *sum)//指針做函數參數 { if (T != NULL) { if (T->lchild == NULL&& T->rchild == NULL) { (*sum) ;//指針所指向的内存空間的數據 1,不是指針 1.一定要加括号 } if (T->lchild) { coutLeaf(T->lchild,sum); } if (T->rchild) { coutLeaf(T->rchild,sum); } } }

求樹的高度(也相當于是遍曆的過程)

int Depth(BiTNode *T) { int deptleft = 0; int deptright = 0; int deptval = 0; if (T == NULL) { deptval = 0; return deptval ; } deptleft = Depth(T->lchild); deptright = Depth(T->rchild); deptval = 1 (deptleft > deptright) ? deptleft : deptright; return deptval; }

樹的拷貝

BiTNode *CopyTree(BiTNode*T)//拷貝 { BiTNode *newNode = NULL; BiTNode *newLp = NULL; BiTNode *newRp = NULL; if (T == NULL) { return NULL; } if (T->lchild != NULL) { newLp = CopyTree(T->lchild); } else { newLp = NULL; } if (T->rchild != NULL) { newRp = CopyTree(T->rchild); } else { newRp = NULL; } newNode = (BiTNode*)malloc(sizeof(BiTNode)); if (newNode == NULL) { return NULL; } newNode->lchild = newLp; newNode->rchild = newRp; newNode->data = T->data; return NULL; }

二個輔助指針變量挖字符串(這個是為了二叉樹線索化的預備知識)

int spitString(const char *buf1, const char c, char buf[18][30], int *nycount) { char *p = NULL; int count = 0; char *pTmp = NULL; int tmpcount = 0; char buf2[1024]; pTmp = buf1; p = buf1; do { p = strchr(p, c); if (p != NULL) { tmpcount - p = pTmp; memcpy(buf[count], pTmp, tmpcount);//行成差值,然後歸并 buf[count][tmpcount] = '\0'; printf("%s\n", buf2); pTmp = p = p 1; count ; } else { break; } } while (*p != '\0'); } void main() { char *p = "aefasergazksdksakaddaweraerdfzdfzjfszg"; char c = ','; char buf[18][30]; int ncount; spitString(p, c, buf, &ncount); system("pause"); }

樹的存儲結構

雙親表示法(順存)

#define MAX_TREE_SIZE 100 //最多結點數 typedef struct //樹的結點定義 { ElemType data;//數據元素 int parent;//雙親位置域 }PTNode; typedef struct //樹的類型定義 { PTNode nodes(MAX_TREE_SIZE);//雙親表示 int n; }PTree;

孩子表示法(順 鍊)

樹與二叉樹的基本知識(樹與二叉樹基本操作)3

孩子兄弟表示法(鍊)

樹與二叉樹的基本知識(樹與二叉樹基本操作)4

樹的遍曆

先根遍曆

樹與二叉樹的基本知識(樹與二叉樹基本操作)5

後根遍曆

樹與二叉樹的基本知識(樹與二叉樹基本操作)6

樹的應用

并查集(支持三種操作)

#define SIZE 100 int UFSets[SIZE]; void Initial(int S[]) { for (int i = 0; i<size; i )//每個自成單元素集合 S[i] = -1; } int Find(int S[], int x) { while (S[x] >= 0)//循環尋找x的根 x = S[x]; return x; } void Union(int S[], int Root1, int Root2)//求兩個不相交子集合的名字 { S[Root2] = Root1; }

平衡二叉樹(左<根<右)

失衡以後調整方法(簡單介紹,不是重點)

LL(右單旋轉)

RR(左單旋轉)

RL(先右後左雙旋轉)

LR(先左後右雙旋轉)

隻有左孩子才能右上旋(孩子變爹,爹變孩子)

隻有右孩子才能左上旋(孩子變爹,爹變孩子)

紅黑樹以及其查找複雜

答:(1)紅黑樹來源于二叉搜索樹,其在關聯容器如map中應用廣泛,主要優勢在于其查找、删除、插入時間複雜度小,但其也有缺點,就是容易偏向一邊而變成一個鍊表。

紅黑樹是一種二叉查找樹,但在每個結點上增加一個存儲位表示結點的顔色,可以是Red或Black。也就是說,紅黑樹是在二叉

查找樹基礎上進一步實現的;

紅黑樹的五個性質:

性質1. 節點是紅色或黑色;

性質2. 根節點是黑色;

性質3 每個葉節點(指樹的末端的NIL指針節點或者空節點)是黑色的;

性質4 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點);

性質5. 從任一節點到其每個尾端NIL節點或者NULL節點的所有路徑都包含相同數目的黑色節點。

(注:上述第3、5點性質中所說的NIL或者NULL結點,并不包含數據,隻充當樹的路徑結束的标志,即此葉結點非常見的葉子結點)。

樹與二叉樹的基本知識(樹與二叉樹基本操作)7

因為一棵由n個結點随機構造的二叉查找樹的高度為lgn,所以順理成章,二叉查找樹的一般操作的執行時間為O(lgn)。但二叉查

找樹若退化成了一棵具有n個結點的線性鍊後,則這些操作最壞情況運行時間為O(n);

紅黑樹雖然本質上是一棵二叉查找樹,但它在二叉查找樹的基礎上增加以上五個性質使得紅黑樹相對平衡,從而保證了

紅黑樹的查找、插入、删除的時間複雜度最壞為O(log n)。

(2)左旋右旋

紅黑樹插入或删除後,一般就會改變紅黑樹的特性,要恢複紅黑樹上述5個性質,一般都要那就要做2方面的工作:

1、部分結點顔色,重新着色

2、調整部分指針的指向,即左旋、右旋。

左旋右旋如圖所示:

樹與二叉樹的基本知識(樹與二叉樹基本操作)8

左旋,如圖所示(左->右),以x->y之間的鍊為“支軸”進行,使y成為該新子樹的根,x成為y的左孩子,而y的左孩子則成為x的右孩

子。算法很簡單,旋轉後各個結點從左往右,仍然都是從小到大。

左旋代碼實現,分三步:

(1) 開始變化,y的左孩子成為x的右孩子;

(2) y成為x的父結點;

(3) x成為y的左孩子;

右旋類似,不再累述;

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved