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) {
let mut temp = TextNode::new();
@ -213,16 +230,23 @@ impl TextNode {
mem::swap(&mut temp, &mut (**right));
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 {
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) {
@ -232,21 +256,28 @@ impl TextNode {
mem::swap(&mut temp, &mut (**left));
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 {
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) {
loop {
let mut rot: int = 0;
let mut rot: int;
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);
@ -262,7 +293,7 @@ impl TextNode {
if child_rot {
if let TextNodeData::Branch(_, ref mut rc) = right.data {
rc.rotate_right();
rc.rotate_left();
}
}
@ -297,7 +328,7 @@ impl TextNode {
if rot == 1 {
self.rotate_right();
}
else if rot == 1 {
else if rot == -1 {
self.rotate_left();
}
}

View File

@ -2,6 +2,7 @@ extern crate rustbox;
extern crate docopt;
extern crate serialize;
use std::char;
use docopt::Docopt;
use buffer::TextBuffer;
@ -39,40 +40,44 @@ fn main() {
rustbox::init();
let enough_time_has_passed: bool = true;
loop {
// Draw the text buffer to screen
rustbox::clear();
{
let mut tb_iter = tb.root_iter();
let mut line: uint = 0;
let mut column: uint = 0;
if enough_time_has_passed {
rustbox::clear();
{
let mut tb_iter = tb.root_iter();
let mut line: uint = 0;
let mut column: uint = 0;
loop {
if let Option::Some(c) = tb_iter.next() {
if c == '\n' {
loop {
if let Option::Some(c) = tb_iter.next() {
if c == '\n' {
line += 1;
column = 0;
continue;
}
rustbox::print(column, line, Style::Normal, Color::White, Color::Black, c.to_string());
column += 1;
}
else {
break;
}
if line > height {
break;
}
if column > width {
tb_iter.next_line();
line += 1;
column = 0;
continue;
}
rustbox::print(column, line, Style::Normal, Color::White, Color::Black, c.to_string());
column += 1;
}
else {
break;
}
if line > height {
break;
}
if column > width {
tb_iter.next_line();
line += 1;
column = 0;
}
}
rustbox::present();
}
rustbox::present();
// Handle events
match rustbox::poll_event() {
@ -98,9 +103,10 @@ fn main() {
height = h as uint;
}
_ => { }
_ => {break;}
}
}
rustbox::shutdown();
println!("{}", tb.root.tree_height);