Jump to content
СофтФорум - всё о компьютерах и не только

удаление из АВЛ-дерева


Recommended Posts

Имеется задание: написать программу которая бы удаляла заданный элемент из АВЛ-дерева.

Я написал такой код:

#include<iostream.h>#define TRUE 1#define FALSE 0struct node{ int Key;  int Count;  int bal;  node *Left;  node *Right;};class TREE { public: //private:int h;node *Tree; //public:TREE () { Tree=NULL; h=FALSE;}void Search (int, node **);void Vyvod (node **, int);node** GetTree() {return &Tree;}void del_tree(int, node **);void del_el(node **);void bal_left(node **);void bal_right(node **);};void main (){ TREE A; int el,i; int n;FILE  *infile;bool flag=0;//,g=0,l=0;//int nN;char c;//node *t1,*t2;infile=fopen("input.txt","rb");  //открытие файлаif (!infile) //проверка наличия файла{cout << "Error: open 'input.txt'.";	flag=1;   	//return -1;}if ((flag==0)&&(c=getc(infile)==EOF)) //проверка файла на пустоту			flag=1;fclose(infile);if (flag==0){infile=fopen("input.txt","rb"); while(!feof(infile)){	 fscanf(infile,"%d",&el);	 A.Search (el,A.GetTree());	} fclose(infile);}else{ printf("File clear!"); //return -1;} //cout<<"Количество вершин в дереве: "; //cin>>n; //cout<<"Информационные поля вершин дерева: \n"; //for (i=1; i<=n; i++)//{ cin>>el; A.Search (el,A.GetTree());}  cout<<"AVL-tree:\n"; A.Vyvod (A.GetTree(),0);  cout<<"\nInput deleted node: ";  cin>>el;  A.del_tree(el,&A.Tree);  cout<<"\nAVL-tree:\n";  A.Vyvod (A.GetTree(),0);  cin>>el;}void TREE::Search (int x, node **p)// x - ключ вершины, помещаемой в АВЛ-дерево.// *p - указатель на корень АВЛ-дерева.// h - флаг, сигнализирующий об увеличении высоты поддерева:// TRUE - высота поддерева увеличилась, // FALSE - высота поддерева не увеличилась.// При первом обращении к функции Search() h=FALSE.{ node *p1, *p2; h = FALSE; if (*p==NULL)  {  *p = new(node);  h = TRUE; (**p).Key = x;   (**p).Count = 1; (**p).Left = (**p).Right = NULL;  (**p).bal = 0; } else   if (x<=(**p).Key)   {	Search (x,&((**p).Left)); 	if (h==TRUE)	  switch ((**p).bal)	  {		case 1 :  (**p).bal = 0; h = FALSE; break;		case 0 : (**p).bal = -1; break;		case -1:				 p1 = (**p).Left;				 if ((*p1).bal==-1)				 {	(**p).Left = (*p1).Right;					  (*p1).Right = *p;					  (**p).bal = 0; *p = p1; }				 else {				   p2 = (*p1).Right;				   (*p1).Right = (*p2).Left;				   (*p2).Left = p1;				   (**p).Left = (*p2).Right;				   (*p2).Right = *p;				   if ((*p2).bal==-1) (**p).bal = 1;				   else (**p).bal = 0;				   if ((*p2).bal==1) (*p1).bal = -1;				   else (*p1).bal = 0;				   *p = p2;				 }				 (**p).bal = 0; h = FALSE;				 break;	  }  }  elseif (x>(**p).Key) {	Search (x,&((**p).Right)); 	 if (h==TRUE)	   switch ((**p).bal)	   {		  case -1:  (**p).bal = 0; h = FALSE; break;		  case  0: (**p).bal = 1; break;		  case  1:				p1 = (**p).Right;				if ((*p1).bal==1)				{	(**p).Right = (*p1).Left;					 (*p1).Left = *p; (**p).bal = 0; *p = p1;				}				else				{	 p2 = (*p1).Left; (*p1).Left = (*p2).Right;					  (*p2).Right = p1; (**p).Right = (*p2).Left;					  (*p2).Left = *p;					  if ((*p2).bal==1) (**p).bal = -1;					  else (**p).bal = 0;					  if ((*p2).bal==-1) (*p1).bal = 1;					  else (*p1).bal = 0;					  *p = p2;				} 				(**p).bal = 0; h = FALSE; break;	   }}}void TREE::Vyvod (node **w,int l)//Изображение дерева w на экране дисплея//		 (рекурсивный алгоритм).//*w - указатель на корень дерева.{ int i; if  (*w!=NULL) {Vyvod (&((**w).Right),l+1);for  (i=1; i<=l; i++) cout<<"   ";cout<<(**w).Key<<endl;Vyvod (&((**w).Left),l+1); }}void TREE::del_tree(int x,node **tr){node *v=new node;v->Left=NULL;v->Right=NULL;if (tr==NULL) cout<<"Tree is nothing!\n";else{ if (x<(*tr)->Key) {  del_tree(x,&(*tr)->Left);  //левый поворот  bal_right(tr); } elseif (x>(*tr)->Key){ del_tree(x,&(*tr)->Right); //правый поворот bal_left(tr);}else{ v=*tr; if (v->Right==NULL) {  tr=&v->Left;  h=TRUE; } else   if (v->Left==NULL)   {	tr=&v->Right;	h=TRUE;   }   else   {	del_el(&v->Left);	//левый паворот	bal_right(tr);   }}}}void TREE::del_el(node **tr){if ((*tr)->Right!=NULL){ del_el(&(*tr)->Right); //bal_left}else{ node *v=new node; v->Key=(*tr)->Key; v=*tr; tr=&(*tr)->Left; h=TRUE;}}void TREE::bal_right(node **p){node *p1, *p2;if (h==TRUE)	   switch ((**p).bal)	   {		  case -1:  (**p).bal = 0; h = FALSE; break;		  case  0: (**p).bal = 1; h = FALSE; break;		  case  1:				p1 = (**p).Right;				if (((*p1).bal==1)||(*p1).bal==0)				{	(**p).Right = (*p1).Left;					 (*p1).Left = *p;					 //(*p).bal = 0;					 if ((*p1).bal==0)					 {					  (*p)->bal=1;					  p1->bal=-1;					  h=FALSE;					 }					 else					 {					  (*p)->bal=0;					  p1->bal=0;					 }					 *p = p1;				}				else				{	 p2 = (*p1).Left; (*p1).Left = (*p2).Right;					  (*p2).Right = p1; (**p).Right = (*p2).Left;					  (*p2).Left = *p;					  if ((*p2).bal==1) (**p).bal = -1;					  else (**p).bal = 0;					  if ((*p2).bal==-1) (*p1).bal = 1;					  else (*p1).bal = 0;					  *p = p2;				}				//(*p).bal = 0; //h = FALSE;				break;	   } //Vyvod (&Tree,0);}void TREE::bal_left(node **p){node *p1, *p2;if (h==TRUE)	  switch ((**p).bal)	  {		case 1 :  (**p).bal = 0; h = FALSE; break;		case 0 : (**p).bal = -1; h = FALSE; break;		case -1:				 p1 = (**p).Left;				 if (((*p1).bal==-1)||(*p1).bal==0)				 {	(**p).Left = (*p1).Right;					  (*p1).Right = *p;					  //(*p).bal = 0;					  if ((*p1).bal==0)					 {					  (*p)->bal=-1;					  p1->bal=1;					  h=FALSE;					 }					 else					 {					  (*p)->bal=0;					  p1->bal=0;					 }					  *p = p1;				 }				 else {				   p2 = (*p1).Right;				   (*p1).Right = (*p2).Left;				   (*p2).Left = p1;				   (**p).Left = (*p2).Right;				   (*p2).Right = *p;				   if ((*p2).bal==-1) (**p).bal = 1;				   else (**p).bal = 0;				   if ((*p2).bal==1) (*p1).bal = -1;				   else (*p1).bal = 0;				   *p = p2;				 }				 //(*p).bal = 0; //h = FALSE;				 break;	  } //Vyvod (&Tree,0);}

Построение дерева работает правильно, а вот с удалением возникли проблемы. Повороты вроде выполняются верно, но когда выводишь измененное дерево то оно выводится или вообще без изменений, либо правильно повернутое но удаляемый элемент при этом остается.

Link to comment
Share on other sites

За не имением советов пришлось разбираться самому, оказалось напутал с передачей параметров в методы.

Выкладываю полностью рабочий код реализующий удаление из АВЛ-дерева элементов с ключами из заданного диапазона, может кому пригодится:

#include<iostream.h>#define TRUE 1#define FALSE 0struct node{ int Key;  int Count;  int bal;  node *Left;  node *Right;};class TREE { public: //private:int h;node *Tree; //public:TREE () { Tree=NULL; h=FALSE;}void Search (int, node **);void Vyvod (node **, int);node** GetTree() {return &Tree;}void del_tree(int, node **);void del_el(node **, node **);void bal_left(node **);void bal_right(node **);};void main (){ TREE A; int el,el1,i; int n;FILE  *infile;bool flag=0;char c;infile=fopen("input.txt","rb");  //открытие файлаif (!infile) //проверка наличия файла{cout << "Error: open 'input.txt'.";	flag=1;}if ((flag==0)&&(c=getc(infile)==EOF)) //проверка файла на пустоту			flag=1;fclose(infile);if (flag==0){infile=fopen("input.txt","rb"); while(!feof(infile)){	 fscanf(infile,"%d",&el);	 A.Search (el,A.GetTree());	} fclose(infile);}else{ printf("File clear!");} //Вывод дерева cout<<"AVL-tree:\n"; A.Vyvod (A.GetTree(),0); cout<<"\nInput breach of deleted node: "; //ввод интервала удаляемых элементов cin>>el; cin>>el1; while (el<=el1) {  A.del_tree(el,&A.Tree);  el++; }  cout<<"\nAVL-tree:\n";  A.Vyvod (A.GetTree(),0);  cin>>el;}void TREE::Search (int x, node **p)//вставка элемента{ node *p1, *p2; h = FALSE; if (*p==NULL)  {  *p = new(node);  h = TRUE; (**p).Key = x;  (**p).Count = 1; (**p).Left = (**p).Right = NULL;  (**p).bal = 0; } else  if (x<=(**p).Key)  {	Search (x,&((**p).Left));	if (h==TRUE)	  switch ((**p).bal)	  {		case 1 :  (**p).bal = 0; h = FALSE; break;		case 0 : (**p).bal = -1; break;		case -1:			 // LL-поворот				 p1 = (**p).Left;				 if ((*p1).bal==-1)				 {	(**p).Left = (*p1).Right;					  (*p1).Right = *p;					  (**p).bal = 0; *p = p1; }				 else {	 // LR-поворот				   p2 = (*p1).Right;				   (*p1).Right = (*p2).Left;				   (*p2).Left = p1;				   (**p).Left = (*p2).Right;				   (*p2).Right = *p;				   if ((*p2).bal==-1) (**p).bal = 1;				   else (**p).bal = 0;				   if ((*p2).bal==1) (*p1).bal = -1;				   else (*p1).bal = 0;				   *p = p2;				 }				 (**p).bal = 0; h = FALSE;				 break;	  }  }  elseif (x>(**p).Key){	Search (x,&((**p).Right));	 if (h==TRUE)	   switch ((**p).bal)	   {		  case -1:  (**p).bal = 0; h = FALSE; break;		  case  0: (**p).bal = 1; break;		  case  1:			// RR-поворот				p1 = (**p).Right;				if ((*p1).bal==1)				{	(**p).Right = (*p1).Left;					 (*p1).Left = *p; (**p).bal = 0; *p = p1;				}				else		// RL-поворот				{	 p2 = (*p1).Left; (*p1).Left = (*p2).Right;					  (*p2).Right = p1; (**p).Right = (*p2).Left;					  (*p2).Left = *p;					  if ((*p2).bal==1) (**p).bal = -1;					  else (**p).bal = 0;					  if ((*p2).bal==-1) (*p1).bal = 1;					  else (*p1).bal = 0;					  *p = p2;				} 				(**p).bal = 0; h = FALSE; break;	   }}}void TREE::Vyvod (node **w,int l)//Вывод дерева на экран{ int i; if  (*w!=NULL) {Vyvod (&((**w).Right),l+1);for  (i=1; i<=l; i++) cout<<"   ";cout<<(**w).Key<<endl;Vyvod (&((**w).Left),l+1); }}void TREE::del_tree(int x,node **tr)//удаление элемента{node *v=new node;v->Left=NULL;v->Right=NULL;if (tr==NULL) cout<<"Tree is nothing!\n";else{ if (x<(*tr)->Key) {  del_tree(x,&(*tr)->Left);  //левый поворот  bal_right(tr); } elseif (x>(*tr)->Key){ del_tree(x,&(*tr)->Right); //правый поворот bal_left(tr);}else{ v=*tr; if (v->Right==NULL) {  *tr=v->Left;  h=TRUE; } else   if (v->Left==NULL)   {	*tr=v->Right;	h=TRUE;   }   else   {	del_el(&v->Left,&v);	//левый паворот	bal_right(tr);   }}}}void TREE::del_el(node **tr,node **v)//обработка случая когда удаляемый элемент имеет двух потомков{if ((*tr)->Right!=NULL){ del_el(&(*tr)->Right,v); bal_left(tr);}else{ (*v)->Key=(*tr)->Key; v=tr; *tr=(*tr)->Left; h=TRUE;}}void TREE::bal_right(node **p)//восстановление баланса при удалении из левого поддерева{node *p1, *p2;if (h==TRUE)	   switch ((**p).bal)	   {		  case -1:  (**p).bal = 0; h = FALSE; break;		  case  0: (**p).bal = 1; h = FALSE; break;		  case  1:				p1 = (**p).Right;				if (((*p1).bal==1)||(*p1).bal==0)				{	(**p).Right = (*p1).Left;					 (*p1).Left = *p;					 //(*p).bal = 0;					 if ((*p1).bal==0)					 {					  (*p)->bal=1;					  p1->bal=-1;					  h=FALSE;					 }					 else					 {					  (*p)->bal=0;					  p1->bal=0;					 }					 *p = p1;				}				else				{	 p2 = (*p1).Left; (*p1).Left = (*p2).Right;					  (*p2).Right = p1; (**p).Right = (*p2).Left;					  (*p2).Left = *p;					  if ((*p2).bal==1) (**p).bal = -1;					  else (**p).bal = 0;					  if ((*p2).bal==-1) (*p1).bal = 1;					  else (*p1).bal = 0;					  *p = p2;				}				break;	   }}void TREE::bal_left(node **p)//восстановление баланса при удалении из правого поддерева{node *p1, *p2;if (h==TRUE)	  switch ((**p).bal)	  {		case 1 :  (**p).bal = 0; h = FALSE; break;		case 0 : (**p).bal = -1; h = FALSE; break;		case -1:				 p1 = (**p).Left;				 if (((*p1).bal==-1)||(*p1).bal==0)				 {	(**p).Left = (*p1).Right;					  (*p1).Right = *p;					  //(*p).bal = 0;					  if ((*p1).bal==0)					 {					  (*p)->bal=-1;					  p1->bal=1;					  h=FALSE;					 }					 else					 {					  (*p)->bal=0;					  p1->bal=0;					 }					  *p = p1;				 }				 else {				   p2 = (*p1).Right;				   (*p1).Right = (*p2).Left;				   (*p2).Left = p1;				   (**p).Left = (*p2).Right;				   (*p2).Right = *p;				   if ((*p2).bal==-1) (**p).bal = 1;				   else (**p).bal = 0;				   if ((*p2).bal==1) (*p1).bal = -1;				   else (*p1).bal = 0;				   *p = p2;				 }				 break;	  } }
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...