2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
puu on aepälineaarinen Tietorakenne, joka on joukko hierarkkisia suhteita, jotka koostuvat n:stä (n>=0) rajoitetusta solmusta.NippuSitä kutsutaan puuksi, koska se näyttää ylösalaisin olevalta puulta, mikä tarkoittaa, että sen juuret osoittavat ylöspäin ja lehdet alaspäin.
- Juurisolmu: juurisolmulla ei ole edeltävää solmua.
- Juurisolmua lukuun ottamatta loput solmut on jaettu alipuihin, joiden rakenne on samanlainen kuin puulla. Kunkin alipuun juurisolmulla on yksi ja vain yksi edeltäjä, ja sillä voi olla 0 tai useampia seuraajia.
- Siksi puu onrekursiivinen määritelmä/.
Puurakenne on monimutkaisempi kuin lineaaritaulukko, ja sen tallentaminen ja esittäminen on hankalampaa.Sekä arvoalue että solmujen ja solmujen välinen suhde on tallennettava., itse asiassa on monia tapoja esittää puita, kuten:Vanhemman merkintä, lapsimerkintä, lapsen vanhemman merkintä ja lapsivelimerkintäodota.
Seuraavan tallennusrakenteen käyttöönotossa otamme seuraavan puun esimerkkinä.
Oletetaan, että puun solmut on tallennettu joukkoon jatkuvia tiloja, ja samaan aikaanJokaisessa solmussa on osoitin, joka osoittaa sen pääsolmun sijainnin linkitetyssä luettelossa. . Toisin sanoen, sen lisäksi, että jokainen solmu tietää kuka se on, se tietää myös missä sen vanhemmat ovat.
Niiden joukossa data on tietokenttä, joka tallentaa solmun datatiedot. Ja vanhempi on osoitinkenttä, joka tallentaa solmun vanhempien alaindeksit taulukkoon.
Seuraava on solmurakenteen määrityskoodi ylätason esityksellemme.
/*树的双亲表示法结点结构定义*/
#define MAX_TREE_SIZE 100
typedef int TElemType; //树结点的数据类型,目前暂定为整型
/*结点结构*/
typedef struct TreeNode
{
TElemType data; //结点数据
int parent; //双亲位置
}TreeNode;
/*树结构*/
typedef struct
{
TreeNode nodes[MAX_TREE_SIZE]; //结点数组
int r, n; //根的位置和结点数
}PTree;
Tällaisella tallennusrakenteella voimme helposti löytää sen pääsolmut käytetyn solmun pääosoittimen mukaanAika monimutkaisuus on 0(1) , kunnes vanhempi on -1, mikä osoittaa, että puusolmun juuri on löydetty. Mutta jos haluamme tietää, mitä solmun lapset ovat, sorry, käy läpi koko rakenne.
Juuri nyt tutkimme puun säilytysrakennetta vanhempien ja lapsen näkökulmasta. Entä jos tarkastelemme puun solmujen veljiä Solmujen veljet Havainnon jälkeen havaitsimme, että sen solmun ensimmäinen lapsi on ainutlaatuinen, jos se on olemassa, ja sen oikea veli on myös ainutlaatuinen. Siksi asetamme kaksi osoitinta, jotka osoittavat solmun ensimmäistä lasta ja solmun oikeaa sisarusta.
/*树的孩子兄弟表示法结构定义*/
typedef struct TreeNode
{
TElemtype data;
struct TreeNode *firstchild, *rightsib;
} TreeNode,* pTreeNode;
Binääripuu on äärellinen joukko solmuja, joka on:
- tai tyhjä
- Se koostuu juurisolmusta ja kahdesta binääripuusta, jotka tunnetaan myös nimellä vasen alipuu ja oikea alipuu.
Kuten yllä olevasta kuvasta näkyy:
- Binääripuussa ei ole solmua, jonka aste on suurempi kuin 2
- Binääripuun alipuut voidaan jakaa vasempaan ja oikeaan alipuuhun, eikä järjestystä voida kääntää, joten binääripuu ontilattu puu
Huomautus: Mikä tahansa binääripuu koostuu seuraavista tilanteista:
Binääripuita voidaan yleensä tallentaa käyttämällä kahta rakennetta:Peräkkäinen rakenne, ketjurakenne.
Tavalliset binaaripuut eivät sovellu varastointiin ryhmissä, koska siellä voi olla paljon hukkaan heitettyä tilaa.jaTäydelliset binaaripuut sopivat paremmin peräkkäiseen rakenteiden varastointiin .Todellisuudessa me yleensäKasa (binääripuu) käyttää tallentamiseen joukkoa peräkkäisiä rakenteita, on huomattava, että kasa tässä ja käyttöjärjestelmän virtuaalisen prosessin osoiteavaruudessa ovat kaksi eri asiaa, toinen on tietorakenne ja toinen aluesegmentointi, joka hallitsee käyttöjärjestelmän muistia.
Katso tarkempi toteutus ja sovellus:[Tietorakenne] 08. Kasa ja kasasovellukset
Yksinkertaisin tapa oppia binääripuurakenne on kulkea sen läpi.niin sanottuBinääripuun läpikulku (Traversal) on suorittaa vastaavat toiminnot binääripuun solmuille järjestyksessä tiettyjen sääntöjen mukaisesti, ja jokaista solmua käytetään vain kerran. . Solmuihin pääsyn suorittamat toiminnot riippuvat tietystä sovellusongelmasta. Traversal on yksi tärkeimmistä binääripuun operaatioista ja myös muiden binääripuun toimintojen perusta.
//根 左子树 右子树
void PrevOrder(pTreeNode root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->val);
PrevOrder(root->left);
PrevOrder(root->right);
}
Alla oleva kuva näyttää rekursiivisen prosessin:
//左子树 根 右子树
void InOrder(pTreeNode root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->val);
InOrder(root->right);
}
Seuraava on rekursiivinen prosessi:
//左子树 右子树 根
void PostOrder(pTreeNode root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->val);
}
Seuraava on rekursiivinen prosessi:
Tasojärjestyksen läpikulku: Ennakkotilauksen, tilauksen läpikulun ja tilauksen jälkeisen läpikulun lisäksi tasojärjestyksen läpikulku voidaan suorittaa myös binääripuille. Oletetaan, että binääripuun juurisolmun tasonumero on 1. Tasojärjestyksen läpikulku alkaa binääripuun juurisolmusta. Ensin se vierailee ensimmäisen tason juurisolmussa ja sitten toisen tason solmuissa taso vasemmalta oikealle ja sitten kolmas taso Tason solmut ja niin edelleen,Menettely puun solmuissa kerros kerrokselta ylhäältä alas ja vasemmalta oikealle on kerrosjärjestyksen läpikulku.。
Kuva:
Tässä puutumme jonoon suorittaaksemme binääripuun ennakkotilauksen läpikäynnin.
// 层序遍历
void LevelOrder(pTreeNode root)
{
Queue q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
pTreeNode front = QueueFront(&q);
QueuePop(&q);
if (front == NULL)
{
printf("NULL ");
}
else
{
printf("%d ", front->val);
QueuePush(&q, front->left);
QueuePush(&q, front->right);
}
}
QueueDestory(&q);
}
Käytämme binääripuun luomiseen ja tuhoamiseenBinaaripuun läpikulkuEsimerkiksi.
//二叉树的创建
struct TreeNode* Creat(char* arr,int n,int* i)
{
if(*i<n&&arr[*i]=='#')
{
(*i)++;
return NULL;
}
TreeNode* newnode=(TreeNode*)malloc(sizeof(TreeNode));
newnode->left=NULL;
newnode->right=NULL;
newnode->val=arr[(*i)++];
newnode->left=Creat(arr,n,i);
newnode->right=Creat(arr,n,i);
return newnode;
}
//二叉树的销毁
void TreeDestroy(struct TreeNode* root)
{
if(root==NULL)
{
return;
}
TreeDestroy(root->left);
TreeDestroy(root->right);
free(root);
}
Seuraavat toiminnot suoritetaan kaikki läpikulkuajatuksella.
// 二叉树节点个数
int TreeSize(pTreeNode root)
{
if (root == NULL)
{
return 0;
}
return TreeSize(root->left) + TreeSize(root->right) + 1;
}
// 二叉树叶子节点个数
int TreeLeafSize(pTreeNode root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
// 二叉树第k层节点个数
int TreeLevelKSize(pTreeNode root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return TreeLevelKSize(root->left, k - 1) + TreeLevelKSize(root->right, k - 1);
}
// 二叉树查找值为x的节点
pTreeNode TreeFind(pTreeNode root, TreeDataType x)
{
if (root == NULL)
{
return NULL;
}
//相等就返回
if (root->val == x)
return root;
//找左子树
pTreeNode left=TreeFind(root->left, x);
if (left)
{
return left;
}
//找右子树
pTreeNode right = TreeFind(root->right, x);
if (right)
{
return right;
}
//都没找到
return NULL;
}
//二叉树的高度
int TreeHeight(pTreeNode root)
{
if (root == NULL)
{
return 0;
}
int max_left = TreeHeight(root->left) ;
int max_right = TreeHeight(root->right);
return max_left > max_right ? max_left + 1 : max_right + 1;
}
//判断是否是完全二叉树
bool TreeComplete(pTreeNode root)
{
Queue q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
pTreeNode front = QueueFront(&q);
QueuePop(&q);
if (front == NULL)
{
break;
}
else
{
QueuePush(&q, front->left);
QueuePush(&q, front->right);
}
}
while (!QueueEmpty(&q))
{
pTreeNode front = QueueFront(&q);
QueuePop(&q);
if (front)
{
QueueDestory(&q);
return false;
}
}
QueueDestory(&q);
return true;
}