Fixed bug in tree balancing. Text rope is now fully self-balancing.

This commit is contained in:
Nathan Vegdahl 2014-12-19 00:23:08 -08:00
parent 4f987ffa16
commit ef64bd8f1c
2 changed files with 73 additions and 36 deletions

View File

@ -206,6 +206,23 @@ impl TextNode {
} }
} }
pub fn update_stats(&mut self) {
match self.data {
TextNodeData::Leaf(ref tb) => {
self.tree_height = 1;
let (cc, nlc) = char_and_newline_count(tb.as_str());
self.char_count = cc;
self.newline_count = nlc;
},
TextNodeData::Branch(ref left, ref right) => {
self.tree_height = max(left.tree_height, right.tree_height) + 1;
self.char_count = left.char_count + right.char_count;
self.newline_count = left.newline_count + right.newline_count;
}
}
}
pub fn rotate_left(&mut self) { pub fn rotate_left(&mut self) {
let mut temp = TextNode::new(); let mut temp = TextNode::new();
@ -213,16 +230,23 @@ impl TextNode {
mem::swap(&mut temp, &mut (**right)); mem::swap(&mut temp, &mut (**right));
if let TextNodeData::Branch(ref mut left, _) = temp.data { if let TextNodeData::Branch(ref mut left, _) = temp.data {
mem::swap(left, right); mem::swap(&mut (**left), &mut (**right));
} }
else {
panic!("rotate_left(): attempting to rotate node without branching right child.");
}
}
else {
panic!("rotate_left(): attempting to rotate leaf node.");
} }
if let TextNodeData::Branch(ref mut left, _) = temp.data { if let TextNodeData::Branch(ref mut left, _) = temp.data {
mem::swap(&mut (**left), self); mem::swap(&mut (**left), self);
left.update_height(); left.update_stats();
} }
self.update_height(); mem::swap(&mut temp, self);
self.update_stats();
} }
pub fn rotate_right(&mut self) { pub fn rotate_right(&mut self) {
@ -232,21 +256,28 @@ impl TextNode {
mem::swap(&mut temp, &mut (**left)); mem::swap(&mut temp, &mut (**left));
if let TextNodeData::Branch(_, ref mut right) = temp.data { if let TextNodeData::Branch(_, ref mut right) = temp.data {
mem::swap(right, left); mem::swap(&mut (**right), &mut (**left));
} }
else {
panic!("rotate_right(): attempting to rotate node without branching left child.");
}
}
else {
panic!("rotate_right(): attempting to rotate leaf node.");
} }
if let TextNodeData::Branch(_, ref mut right) = temp.data { if let TextNodeData::Branch(_, ref mut right) = temp.data {
mem::swap(&mut (**right), self); mem::swap(&mut (**right), self);
right.update_height(); right.update_stats();
} }
self.update_height(); mem::swap(&mut temp, self);
self.update_stats();
} }
pub fn rebalance(&mut self) { pub fn rebalance(&mut self) {
loop { loop {
let mut rot: int = 0; let mut rot: int;
if let TextNodeData::Branch(ref mut left, ref mut right) = self.data { if let TextNodeData::Branch(ref mut left, ref mut right) = self.data {
let height_diff = (left.tree_height as int) - (right.tree_height as int); let height_diff = (left.tree_height as int) - (right.tree_height as int);
@ -262,7 +293,7 @@ impl TextNode {
if child_rot { if child_rot {
if let TextNodeData::Branch(_, ref mut rc) = right.data { if let TextNodeData::Branch(_, ref mut rc) = right.data {
rc.rotate_right(); rc.rotate_left();
} }
} }
@ -297,7 +328,7 @@ impl TextNode {
if rot == 1 { if rot == 1 {
self.rotate_right(); self.rotate_right();
} }
else if rot == 1 { else if rot == -1 {
self.rotate_left(); self.rotate_left();
} }
} }

View File

@ -2,6 +2,7 @@ extern crate rustbox;
extern crate docopt; extern crate docopt;
extern crate serialize; extern crate serialize;
use std::char; use std::char;
use docopt::Docopt; use docopt::Docopt;
use buffer::TextBuffer; use buffer::TextBuffer;
@ -39,8 +40,11 @@ fn main() {
rustbox::init(); rustbox::init();
let enough_time_has_passed: bool = true;
loop { loop {
// Draw the text buffer to screen // Draw the text buffer to screen
if enough_time_has_passed {
rustbox::clear(); rustbox::clear();
{ {
let mut tb_iter = tb.root_iter(); let mut tb_iter = tb.root_iter();
@ -73,6 +77,7 @@ fn main() {
} }
} }
rustbox::present(); rustbox::present();
}
// Handle events // Handle events
match rustbox::poll_event() { match rustbox::poll_event() {
@ -98,9 +103,10 @@ fn main() {
height = h as uint; height = h as uint;
} }
_ => { } _ => {break;}
} }
} }
rustbox::shutdown(); rustbox::shutdown();
println!("{}", tb.root.tree_height); println!("{}", tb.root.tree_height);