Jak převést binární strom binárního vyhledávacího stromu v místě, tedy nemůžeme použít žádný další prostor.
Jak převést binární strom binárního vyhledávacího stromu na místě, tedy nemůžeme použít žádný další prostor
Binární strom obvykle je binární vyhledávací strom, přičemž v tomto případě není nutná žádná konverze.
Možná, že je třeba vyjasnit strukturu, co se konverze z. Je váš zdroj strom nevyvážený? Je to nenařídil klíčem, který chcete hledat v? Jak jste se dostali na zdrojovém stromu?
No, pokud se jedná o rozhovor otázku, první věc, kterou bych vybreptnout (s nulovým skutečné myšlení), je toto: opakovat celý binární rekurzivně a a najít nejmenší prvek. Vezměte ho do binárního stromu. Nyní, opakujte postup, kde iteraci celý strom a najít nejmenší prvek, a přidejte ji jako rodič posledního elementu nalezeného (s předchozím prvkem stává levé dítě nového uzlu). podle potřeby, dokud původní strom je prázdný opakovat tolikrát, kolikrát. Na konci, jste odešel s nejhorším možným tříděného binárního stromu - propojeného seznamu. Ukazatel ukazuje na kořenový uzel, který je největší prvek.
To je hrozný algoritmus all-around - O (n ^ 2), doba provozu s nejhorším možným binárního stromu výstupu, ale je to slušné východisko, než přijít s něčím lepším a má tu výhodu, že budete schopni psát kód je asi 20 řádků na tabuli.
Nemusíte dát mnohem dál, ale v případě, že požadavek je to, co myslím, že je máte binární strom již vytvořili a sedí v paměti, ale není seřazena (tak, jak chcete, aby se třídit, tak jako tak).
Jsem za předpokladu, že uzly strom vypadat
struct tree_node {
struct tree_node * left;
struct tree_node * right;
data_t data;
};
Jsem také za předpokladu, že si můžete přečíst C
I když jsme mohli jen sedět a přemýšlel, proč byl tento strom byl kdy vytvořen, aniž by byla vytvořena v seřazeném pořadí, který nedělá nám k ničemu, takže budu to ignorovat a jen se zabývají jejich třídění.
Požadavek, aby byla použita žádná zvláštní prostor je lichý. Dočasně bude prostor navíc, i kdyby jen na stacku. Budu předpokládat, že to znamená, že volání malloc nebo něco podobného, a také to, že výsledný strom se musí používat více paměti než původní netříděného stromu.
První a nejjednodušší řešení je provést předobjednávku průchod netříděného stromu odstraňování každý uzel z toho stromu a dělá seřazené vložení do nového stromu. To je O (n + n log (n)), který je O (n log (n)).
Pokud to není to, co chtějí, a budete muset použít rotace a tak ..... to je hrůza!
Myslel jsem si, že byste mohli udělat tím, že dělá podivnou verzi haldy druhu, ale já běžel do problémů. Další věc, která se přijde na mysl, což by bylo strašně pomalý, bude dělat podivnou verzi bubble druhu na stromě.
Za tímto účelem každý uzel je ve srovnání a případně vyměnil s každým z jeho přímé děti (a tudíž i se svým rodičem) opakovaně, dokud procházet strom a nenacházíte potřebné swapy. Dělá vibrační druh (bubble sort, že jde zleva doprava a zprava doleva) verze této opravy bude fungovat nejlépe, a po počátečním průchodu nebudete muset procházet dolů podstromy, že nevypadal mimo pořadí s ohledem na to rodič ,
Jsem si jistý, že buď to algortimus vymyslel někdo jiný přede mnou a má cool jméno, které já prostě nevím, nebo že je zásadně chybné nějakým způsobem, že nevidím.
Přijít s run-time výpočty pro druhý návrh je docela složité. Zprvu jsem si myslel, že by to prostě bylo O (n ^ 2), stejně jako bublina a shaker druhů, ale nemohu uspokojit sebe, že vyhýbání podstrom průchod nemusí vyhrát natolik, aby to trochu lepší než O (n ^ 2). V podstatě bublina a vibrační druhy získat tuto optimalizaci taky, ale jen na koncích, kde celková sortedness vyskytuje brzy a můžete pokácet limity. S tímto stromem verzi dostanete oppurtunities aby případně nedošlo k kusy ve středu sady stejně. No, jak jsem řekl, je to zřejmě fatálně chybné.
Dělat nezbytného průchod binárního stromu a uložení výsledku. seřadit výsledek acending objednávkový formulář binární vyhledávací strom, vypočítává střední prvek z tříděného seznamu jako root (totéž lze provést pomocí binárního vyhledávání). tak dostaneme vyvážený strom binárního vyhledávání.
Ještě následující algoritmus k dosažení řešení.
1) najít v pořadí nástupce bez použití jakéhokoli prostoru.
Node InOrderSuccessor(Node node)
{
if (node.right() != null)
{
node = node.right()
while (node.left() != null)
node = node.left()
return node
}
else
{
parent = node.getParent();
while (parent != null && parent.right() == node)
{
node = parent
parent = node.getParent()
}
return parent
}
}
2) udělat, aby průchod bez použití prostoru.
a) Najděte prvního uzlu nezbytného průchod. Mělo by opustil většinu dítě stromu, pokud to má, nebo vlevo od prvního pravého potomka, pokud má nebo vpravo dítě samo. b) Použití výše algoritmus pro zjištění inoder nástupce prvního uzlu. c) Opakujte krok 2 pro všechny vrácené nástupce.
Používat více než 2 algoritmus a proveďte v pořadí průchod na binárního stromu bez použití více prostoru. Vytvoří binární vyhledávací strom, když dělal traversal. Ale složitost je O(N2)nejhorší případ.
heap sort stromu .. nlogn složitost ..
Proveďte postorder Traversal a od toho vytvoří binární vyhledávací strom.
struct Node * newroot = '\0';
struct Node* PostOrder(Struct Node* root)
{
if(root != '\0')
{
PostOrder(root->left);
PostOrder(root->right);
insertBST(root, &newroot);
}
}
insertBST(struct Node* node, struct Node** root)
{
struct Node * temp, *temp1;
if( root == '\0')
{
*root == node;
node->left == '\0';
node->right == '\0';
}
else
{
temp = *root;
while( temp != '\0')
{
temp1= temp;
if( temp->data > node->data)
temp = temp->left;
else
temp = temp->right;
}
if(temp1->data > node->data)
{
temp1->left = node;
}
else
{
temp1->right = node;
}
node->left = node->right = '\0';
}
}
Převést binární strom do dvojnásob propojeny Seznam Titulů lze provést inplace v O (n),
pak třídit je pomocí merge sort, nlogn
převést seznamu zpět do stromu - O (n)
Jednoduché nlogn řešení.
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
struct tree_node {
struct tree_node * left;
struct tree_node * right;
data_t data;
};
/* a bonsai-tree for testing */
struct tree_node nodes[10] =
{{ nodes+1, nodes+2, 1}
,{ nodes+3, nodes+4, 2}
,{ nodes+5, nodes+6, 3}
,{ nodes+7, nodes+8, 4}
,{ nodes+9, NULL, 5}
,{ NULL, NULL, 6}
,{ NULL, NULL, 7}
,{ NULL, NULL, 8}
,{ NULL, NULL, 9}
};
struct tree_node * harvest(struct tree_node **hnd)
{
struct tree_node *ret;
while (ret = *hnd) {
if (!ret->left && !ret->right) {
*hnd = NULL;
return ret;
}
if (!ret->left ) {
*hnd = ret->right;
ret->right = NULL;;
return ret;
}
if (!ret->right) {
*hnd = ret->left;
ret->left = NULL;;
return ret;
}
hnd = (rand() &1) ? &ret->left : &ret->right;
}
return NULL;
}
void insert(struct tree_node **hnd, struct tree_node *this)
{
struct tree_node *ret;
while ((ret= *hnd)) {
hnd = (this->data < ret->data ) ? &ret->left : &ret->right;
}
*hnd = this;
}
void show(struct tree_node *ptr, int indent)
{
if (!ptr) { printf("Null\n"); return; }
printf("Node(%d):\n", ptr->data);
printf("%*c=", indent, 'L'); show (ptr->left, indent+2);
printf("%*c=", indent, 'R'); show (ptr->right, indent+2);
}
int main(void)
{
struct tree_node *root, *this, *new=NULL;
for (root = &nodes[0]; this = harvest (&root); ) {
insert (&new, this);
}
show (new, 0);
return 0;
}
struct Node
{
int value;
Node* left;
Node* right;
};
void swap(int& l, int& r)
{
int t = l;
l = r;
r = t;
}
void ConvertToBST(Node* n, Node** max)
{
if (!n) return;
// leaf node
if (!n->left && !n->right)
{
*max = n;
return;
}
Node *lmax = NULL, *rmax = NULL;
ConvertToBST(n->left, &lmax);
ConvertToBST(n->right, &rmax);
bool swapped = false;
if (lmax && n->value < lmax->value)
{
swap(n->value, lmax->value);
swapped = true;
}
if (rmax && n->value > rmax->value)
{
swap(n->value, n->right->value);
swapped = true;
}
*max = n;
if (rmax && rmax->value > n->value) *max = rmax;
// If either the left subtree or the right subtree has changed, convert the tree to BST again
if (swapped) ConvertToBST(n, max);
}













