Перейти к содержанию
СофтФорум - всё о компьютерах и не только

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


Рекомендуемые сообщения

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

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

#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);}

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

#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;	  } }
Ссылка на комментарий
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...