Preface
Shouji opened the last few chapters of "Zhuji", so this article is more about Chapter 13, 14, and 15. The main content of this article is "AVL Tree", that is, the balance tree, which is one level lower than the red/black tree. The mess is really difficult to get rid of, and the situation is complicated; AVL's ideas are clear. "Programming Pearl, character Pearl" 910 Reading Notes-code optimization updated, made some notes about the "Sentinel. At the end of this article, I also added a "thorough understanding" of reference calls ".
Four Reading Notes: all here
AVL Tree
When I learned the data structure, I had an experiment course. The question is about the number of times an English word appears. At that time, we selected a hash table, map, and AVL Tree, which were done in order to "complete the lab instructor, please eat. The key value of the hash table is separated by the remainder distinct, and the simplest method of opening the hash table is used for conflict handling ". The ing (MAP) is not in-depth, but a simple application. The AVL Tree is quite sad.
AVL Tree Rotation
Tree rotation is divided into four types: Left Single rotation, right single rotation, left and right rotation, right left rotation. Specify that the height of the right subtree minus the height of the Left subtree to obtain the number of balances for this node (also known as the balance factor, balance factor, BF), using BF (node) the number of node balances. Take a look at these four situations:
When BF (node) = 2, that is, the tree height on the right is higher than that on the left. After the rotation, the left subtree BF + 1, The right subtree BF-1, the number of node balances to zero.
The Node Adjustment process is clear.
When BF (node) =-2, the right subtree is lower than the left subtree. You need to rotate the tree to the right of the node. After the selection, the left subtree BF-1, the right subtree + 1, node balancing tree to zero.
Carefully discovered that the Left and Right single spin are the same, but they are the opposite.
The following situations are complex, but they are extended from the above two situations. However, this change also makes a small difference in their balancing methods.In the following two cases, the child tree is inserted from the inside of the Child tree. As a result, the Child tree (BF (kid) is opposite to the BF of its father (BF (parent). First, the left and right sides are rotated to see the figure:
Solution: The kid node performs a simple left single spin, and the parent performs a simple right single spin. During the process, you need to pay attention to the BF adjustment of the node. We need to discuss the situation based on the situation (moving the worker across the past is not far from the success ).
- If you insert data from the left of the right subtree (grandkid) of the left kid,
Adjust BF (kid): Then BF (grandkid) <0, after the left single rotation of kid, the left Tree of grandkid is adjusted to the right subtree of kid, result BF (kid) = 0;
Adjust BF (parent): After the right single rotation is performed on the parent, the right subtree of grandkid is adjusted to the left subtree of the parent. Therefore, if BF (grandkid) <0, then BF (parent) = 1;
- If you insert data from the right subtree (grandkid) of the left kid,
Adjust BF (kid): Then BF (grandkid)> 0, after the left single rotation of kid, the left Tree of grandkid is adjusted to the right subtree of kid, result BF (kid) =-1;
Adjust BF (parent): After the right single rotation is performed on the parent, the right subtree of grandkid is adjusted to the left subtree of the parent. Therefore, if BF (grandkid) <0, then BF (parent) = 0;
- BF (grandkid) Adjustment: Finally, grandkid is adjusted to the root node of the new tree, BF (grandkid) = 0.
(Fill in a blank question) combined with the following figure, which belongs to the right left rotation:
If the left side of the left subtree (grandkid) of the right kid is inserted and the BF (kid) is adjusted to: BF (grandkid) 0, after the left single rotation of the kid, the left Tree of grandkid is adjusted to the right subtree of the kid, and the result is BF (kid) =; The BF (parent) Adjustment: After the right single rotation of the parent, the right subtree of grandkid is adjusted to the left subtree of parent. Therefore, if BF (grandkid) 0, BF (parent) =; If the left subtree of the right subtree (grandkid) and then adjust BF (kid): Then BF (grandkid) 0, after the left single rotation of kid, the left Tree of grandkid is adjusted to the right subtree of kid, result BF (kid) =; BF (parent) Adjustment: After the right single rotation of parent, the right subtree of grandkid is adjusted to the left subtree of parent, so if BF (grandkid) 0, then BF (parent) =;
BF (grandkid) Adjustment: Finally, grandkid is adjusted to the root node of the new tree, BF (grandkid) =.
Answer: <, 1, <, 0;>, 0,>,-1.
We can see that BF needs to be changed during the adjustment of the three nodes. The last rotation is the right-left rotation. There is no need for too much analysis. It is the same as above. It is a simple reversal. Disorder:
Construct a balance tree, that is, constantly locate a new node in the original tree and adjust it. In the process of "Searching", the BF of the node has changed (+ 1 or-1 ). To insert a node, use the stack to store the node that has passed through. After finding the Insertion Location, adjust it from the parent node at the insertion location. If the parent node is balanced, then retrieve the parent node from the stack and continue the adjustment.
In the above analysis, after rotation, the result of the node rotation will get the BF (node) = 0 result, so after rotation, our goal is to achieve-tree balance! Therefore, BF (node) = 0d will increase and accumulate on the top layer of the tree.
Therefore, you do not need to adjust to the root node of the tree every time. As long as the BF of the adjusted node is 0, it can end. The node or brother node above has BF = 0. This is also confusing when I first came into contact with AVL.
Finally, I will give the code of the insert node:
/*********************************** ** sample **********************************/void avl::insert(int data) { node * parent = 0,* p = root,* t = new node(data); stack<node *> s; while (p) { int ret = p->comp(*t); if(ret==0) {delete t; return;} parent = p;s.push(parent); if(ret<0) p = p->right; else p = p->left; }// while p = t; assert(p); if (!root) { root = p; return; }// if if(parent->comp(*t)>0) parent->left = p; else parent->right = p; while (!s.empty()) { parent = s.top(); s.pop(); if(p==parent->left) parent->bf--; else parent->bf++; int d; if(parent->bf==0) break; if(abs(parent->bf)==1) p=parent; else { d = parent->bf<0?-1:1; if(d<0 && p->bf<0) r(parent); else if(d>0 && p->bf>0) l(parent); else if(d>0 && p->bf<0) rl(parent); else lr(parent); break; }// if }// while if (s.empty()) root = parent; else { p = s.top(); if(p->comp(*parent)>0) p->left = parent; else p->right = parent; }// if }
In addition, I put the code that is rotated in the attachment (if it seems bloated). In addition, there is an experiment report "word Statistics" in the attachment. If you are interested, you can download it. At the time of the experiment, aVL's word statistics were quite powerful:
Reference and call
Note: Reference calls are not supported in ansi c, while C ++ provides the implementation of reference calls.
As mentioned in Article 1 of Objective C ++, pointers and references have application differences.The object referred to by the pointer can be changed at will, and its direction can be null, which is very flexible. However, the reference must represent an object and cannot be null. After it is assigned to an object, it always indicates that the object is destroyed.For example:
/*********************************** ** sample **********************************/ int b = 1; int &a = b;
A becomes a reference of B, and a cannot reference other data. In addition, whether the referenced variable occupies memory I heard that only the definition (http://topic.csdn.net/u/20100622/15/728477fe-92ab-4e83-8572-0923d37186f1.html ),I think the feasible method is that the program only adds a to the variable symbol table, and does not allocate any memory for.
In the process of passing parameters through a function, there are value passing, pointer passing (both belong to C), and reference passing (C ++ ). What the pointer can do, and the reference can also be done. But the reference is more secure (not to make it null), easier to operate, and has the advantages of "energy saving and emission reduction ". Let's take a look:
/*********************************** ** sample **********************************/function(TYPE * a) a = new TYPE **** main() TYPE * a = NULL; function(a); ***
After the function is returned, A is still the original null and has not changed. Because you want to, in the function stack, only the null value of pointer A is saved, even if a = new type can assign a new address for a, but this A is not a, after function rollback, this A will be destroyed, and Peter A is still null. Therefore, if you want to change the content of a pointer, you must use the pointer or pointer reference, and the pointer reference will be more convenient.
/*********************************** ** sample **********************************/function(TYPE *& a) a = new TYPE **** main() TYPE * a = NULL; function(a); ***
In this case, the value of pointer A is changed. There are many reference calls in the AVL Tree program. You should pay attention to them. Confused, this note should be written as early as the freshman year, ashamed and generous.
Summary of Pearl River
I still think of it as a casual book. This book is recommended for beginners of algorithms or data structures.
Attachment:
- Avltree program .rar
- Avlsingle-word statistical experiment .rar
After Thursday, limit l 26,201 2
Spoof http://daoluanxiaozi.cnblogs.com/