AVL樹學習

AVL樹爲什會出現?

我們之前有學習使用二叉查找樹,但是二叉查找樹在使用的時候也會出現一些問題,當恰好所有的數據都是按照大小順序插入的話,就有可能將我們的二叉樹編程鏈表,就導致樹結構退化爲鏈表結構。

什麼是不平衡

其實不平衡就是一個節點下面的左子樹和右子樹的高度相差太多,沒有雨露均沾,導致出現了不平衡的現象。

如何解決不平衡?

其實我們從局部看,不平衡的情況其實就歸爲四種。

  1. 左—左類型
    左-左類型其實對於這種情況,三個節點都連在左邊,可以使用右旋的方式來調整,以5爲終點將其向右旋轉,然後9向下成爲5的右節點。如果5這個節點有右節點的話,可以按照這樣的方式移動
    右旋的動圖
  2. 右-右類型
    這個也不用多說,都是類似的使用左旋的方式,我們首先先寫出右旋和左旋的代碼。
    class Node {
    public:
    	Node * left;
    	Node * right;
    	int height; //需要記錄一下高度
    };
    
    class AVLTree {
    public:
    	AVLTree(){};
    	~AVLTree(){};
    	/***
    	R_Rotate穿進來的是那個有問題的節點
    	***/
    	Node* R_Rotate(Node * pa) { 
    		Node *leftNode = pa -> left; // 講leftNode拿出來
    		pa -> right = leftNode -> right;
    		leftNode -> right = pa;
    		
    		//重新計算節點的高度
    		pa->height = getHeight(pa->left) > getHeight(pa->right) ? getHeight(pa->left) : getHeight(pa->right) ;
    		pa->height ++;
    		leftNode->height =  getHeight(leftNode->left) > getHeight(leftNode->right) ? getHeight(leftNode->left) : getHeight(leftNode->right) ;
    		leftNode->height ++;
    		return leftNode;
    	}
    	Node * L_Rotate(Node * pa) {
    		Node * R = pa->right;
    		pa -> right = R -> left;
    		R -> left = pa;
    		//重新計算節點的高度
    		pa->height = getHeight(pa->left) > getHeight(pa->right) ? getHeight(pa->left) : getHeight(pa->right) ;
    		pa->height ++;
    		R->height =  getHeight(R->left) > getHeight(R->right) ? getHeight(R->left) : getHeight(R->right) ;
    		R->height ++;
    		return R;
    		
    	}
    		
    	int getHeight(Node * node) {
    		if(node) return node->height;
    		return -1;
    	}
    	
    	Node* L_R_Rotate(Node * pa) {
    		pa->right = L_Rotate(pa -> right);
    		pa = R_Rotate(pa);
    		return pa;
    	}
    	
    	Node* R_L_Rotate(Node* pa) {
    		pa->left = R_Rotate(pa->left);
    		pa = L_Rotate(pa);
    		return pa;
    	}
    	//insert這裏需要使用遞歸,因爲我們需要從上到下進行調整
    	Node * Insert(Node * newNode,Node * T) {
    		
    		if(!T) {
    			T = newNode; 
    		} else if(newNode->val > T->val) {
    			
    			T -> right = Insert(newNode , T -> right); //往右子樹上面插入
    			if(height(T->right) - height(T->left) == 2) {
    				// right right
    				if(T ->right->val < newNode -> val) {
    					T = L_Rotate(T);
    				} else //right left{
    					T = L_R_Rotate(T);	
    				}
    			}
    		} else if(newNode->val < T -> val) {
    			T -> left = Insert(newNode, T->left);
    			if(height(T->left) - height(T->right) == 2) {
    				// left left
    				if(T->left->val > newNode->val) {
    					T = R_Rotate(T);
    				} else // left right {
    					T = R_L_Rotate(T);
    				}
    			}
    		}
    		
    		T->height = getHeight(T->left) > getHeight(T->right) ? getHeight(T->left) : getHeight(T->right) ;
    		return T;
    	}
    	private:
    		Node * head;
    	
    };
    
發佈了56 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章