basic_robot/scripts/avl_tree~.lua

175 lines
4.9 KiB
Lua

-- 1. MEMORY MANAGEMENT using array with addresses
-- note: this is all done "automatic" in c with malloc
mem = {};
mem.size = 10; -- how many available addresses in memory for each of internally used arrays
mem.freestk = {}; -- stack of free addresses in memory
mem.stkidx = mem.size;
for i = 1,mem.size do mem.freestk[i]=mem.size-i+1 end -- so: freestk = {memsize, memsize-1,...., 2, 1 } and head is at last one
mem.allocate = function() -- pop free spot from stack
if mem.stkidx>0 then
mem.stkidx = mem.stkidx -1
return mem.freestk[mem.stkidx+1]
end
end
mem.free = function(addr) -- release spot and mark it as free
if mem.stkidx>=mem.size then -- cant release anymore, all is free
return
end
mem.stkidx = mem.stkidx +1;
mem.freestk[mem.stkidx ] = addr;
end
-- 2. BALANCED BINARY SEARCH TREES USING POINTERS created with above MEMORY MANAGEMENT
idx = mem.allocate();
tree = {};
tree.data = { root = 0, count = 0, -- current root, element count
left = {0}, parent = {0}, right = {0}, -- links
key = {0}, -- value
heightl = {0}, heightr = {0} -- needed for balancing
};
-- root: idx of root element, count: how many elements in tree
-- 6 arrays with data for node stored at address i in memory:
-- left[i] == left child, right[i] = right child, parent[i] = parent, key[i] = stored value, if value left[i]== 0 then no left child...
-- heightl[i] = height of left subtree, heightr[i] = height of right subtree
-- NOTE: initially a root node is added
tree.insert = function (value)
local data = tree.data;
local idx = data.root;
if data.count == 0 then data.key[idx] = key; data.count = 1 return true end -- just set root key and exit
local key;
local cidx; -- child idx
while (true) do -- insert into tree by walking deeper and doing comparisons
key = data.key[idx];
if value<key then
cidx = data.left[idx];
else
cidx = data.right[idx];
end
if cidx == 0 then -- we hit nonexistent child, lets insert here
cidx = mem.allocate();
if not cidx then return "out of space" end
data.count = data.count+1
data.key[cidx] = value;
data.parent[cidx]=idx;data.left[cidx]=0;data.right[cidx]=0;
data.heightl[cidx]=0;data.heightr[cidx]=0;
-- update all heights for parents and find possible violation of balance property
local vidx = 0; -- index where violation happens
local vdir = 0; -- type of violation: 1: in left tree , 2: in right tree
while (idx~=0) do
if data.left[idx] == cidx then
data.heightl[idx]=data.heightl[idx]+1
else
data.heightr[idx]=data.heightr[idx]+1;
end
if data.heightl[idx]>data.heightr[idx]+1 then
vidx = idx; vdir = 1
elseif data.heightr[idx]>data.heightl[idx]+1 then
vidx = idx; vdir = 2
end
cidx = idx; -- set new child
idx = data.parent[idx]; -- set new parent
end
if vidx~=0 then
say("violation vidx " .. vidx .. " direction " .. vdir)
-- TO DO: apply internal tree rotation to restore balance
if vdir == 1 then -- left violation
--[[ need to reconnect 3 nodes:
D <- vidx C
/ \ / \
C E => A D
/ \ / \
A B B E
CHANGES:
C: new parent is old parent of D, new children are A,D
B: new parent D,
D: new parent is C, new children are B,E
--]]
local Didx = vidx; local Dpar = data.parent[Didx];
local Cidx = data.left[Didx];
local Bidx = data.right[Cidx];
local Aidx = data.left[Cidx];
data.parent[Cidx] = Dpar;data.left[Cidx] = Aidx;data.right[Cidx] = Didx;
data.parent[Bidx] = Didx;
data.parent[Didx] = Cidx;data.left[Didx] = Bidx;
else -- right violation
--[[ need to reconnect 3 nodes:
B <-vidx C
/ \ / \
A C => B E
/ \ / \
D E A D
CHANGES:
B: new parent C, new children A,D
C: new parent is old parent of B, new children are B,E
D: new parent is B
--]]
local Bidx = vidx; local Bpar = data.parent[Bidx];
local Cidx = data.right[Bidx];
local Didx = data.left[Cidx];
data.parent[Bidx] = Cidx;data.right[Bidx] = data.left[Cidx]
data.parent[Cidx] = Bpar;data.left[Cidx] = Bidx;
data.parent[Didx] = Bidx;
end
end
else
-- we go deeper
idx = cidx;
end
end
tree.find = function(value)
local idx = data.root;
while (idx~=0) do
key = data.key[idx];
if key == value then return idx end
if value<key then
idx = data.left[idx];
else
idx = data.right[idx];
end
end
end
tree.next = function(idx)
local right = data.right[idx];
local nidx = 0;
if right~=0 then
--TO DO: smallest idx in right subtree
else
if data.parent[idx]==0 then
return 0
end
end
end
tree.remove = function(idx)
--TO DO :
-- 1.find next element
-- put it where idx was and move subtree..
end
end