Часть I : Списки
По типу связи
Односвязные
Двухсвязные
По типу организации
Линейные
Циклические
Задание: ptr / header
Структуры:
Стек First In – First Out
Insert
New->next=first
First=x
Read
If(null) false
Ret = first
First = first->next
Ret->next = 0
Очередь Last In – Last Out
Ins
If null
Head = new
Else tail->next = new
Tail = new
Read
If (empty) false
res = head
head = head->next
x->next=null
if(empty)
tail = null
Дек(double ended queue) mixed
Часть II : Таблицы
Просматриваемые ( insert to last; search from i to n; after delete move last to pos[deleted]; ф-ла для колва просматрив записей k = pN/2 + (1-p)N p –exist)
Упорядоченные ( sorted by key; binary search; search+insert; delete, move all down to their pos+1; k = log2N )
Вычисляемый вход
Произвольный доступ O(1):
table - array[n] (keys)
vector - array[m] (r(keys)), key = r(k);
search O(1) (array); c = n/m (coef_fill)
Перемешанные (хеш), h(k); k = (1-c/2)/(1-c)
collision h(k1)=h(k2)
сцепление: все эл-ты с r(key), k1!=k2 -> list
сложение (если есть, то ищем своб. ячейку ): последов. пересчет со смещ h’(k) = h(k+p) mod m, p = смещение, виды смещ: увелич. смещ: j = (j+1) % m, взаимно простые m и p числа: p = (j+p) % m
Часть III : Binary Search – Tree
Дерево – вершина, l/r поддеревья; node {key, node* left,right,parent}; Высота вершины – from 0(root) to current
Обходы O(n): прямой – корень, лево, право; концевой – лево, право, корень; центр. – лево, корень, право
Search(k,node){
if (x is null)
ret false;
if (k<x.key) {search(k,x->left)}
else{
if(k>x.key) {search(k,x->right)}
else { ret x.key}
}
}
Insert(parent,node)
{
If(parent =null) {parent = node;}
Else if (node->key < parent->key) {Insert(parent->left, node)}
Else {Insert(parent->right,node)}
}
Min(root) // for max left change to right
{
X = root;
While root.left {X = root.left;}
Return x;
}
Delete(root,k)
replace(node,val)
{
If (node->parent)
If (node == node->parent->left)
Node->parent->left = val
Else
Node->parent->right = val
If val
val->parent = node->parent;
}
Delete(parent,k)
{
If(k<root.parent) {Replace(parent->left,k)}
Else
If (k>parent.key) {Delete(parent->right,k)}
Else
If(parent->left && parent->right) // 2 childs
{
Suc = Min(parent);
Parent->key=suc->key;
Replace(suc,suc->right)
}
Else
If (parent->left || parent->right) //1 child
If(parent->left) {replace(parent,parent->left)}
Else {replace(parent,parent->right)}
Else // no children
Replace(parent,null)
}
Traversal(node){
if(!node) return;
traverse(node->left)
print node->key;
traverse(node->right)
}
All Ο(h) with max O(n)
Часть IV : rb – Деревья
Дерево – вершина, l/r поддеревья; node {key, color, node* left,right,parent}; Высота вершины – from 0(root) to current. Leave = null.
Каждый узел является красным или черным
Корень дерева является черным
Каждый лист дерева (EList) является черным
Если узел – красный, то оба его дочерних узла – черные
Для каждого узла все пути от него до листьев, являющихся потомками данного узла, содержат одно и то же количество черных узлов
bh(node) – black height of node; bh(tree) for tree
h>= 2 lg (n+1)
bh(node) >= h/2 O(h) = O(lg(n))
rotate_l(x): A is x, B is y. A->left= a, B->left=b,B->left=c
POST IMAGE FROM SLIDE 5.5 HERE
Rotate_l(x){ O(1)
y = x->right
x->right = y->left;
if(y->left != NULL) { y->left->parent = x}
y->parent=x->parent;
if(x->parent = NULL) {root =y}
else { if(x->parent->left =x) {x->parent->left = y} else {x->parent->right=y}
y->left = x;
x->parent = y;
INSERT,DELETE,SEARCH ????
Insertion
Вставка как в BST, новый узел – красный с 2 black leaves.
prev = EList – родительский узел
ptr = root – текущий узел
while (ptr ≠ EList) {
prev = ptr //par
if (x->key < ptr->key) – выбор поддерева
ptr = ptr->left – левое поддерево
else
ptr = ptr->right– правое поддерево
}
x->parent = prev – родительский узел
if prev = EList {root = x } //empty tree
else
if (x->key < prev->key) {prev->left = x}
else {prev->right = x}
x->left = EList
x->right = EList
x->color = RED
RB_Insert_Fixup(x)
RB_Insert_Fixup(x) !!! write scheme from 5.13
{
x = new
while (x->parent = RED) {
p1 = x->parent
pp = p1->parent
if (p1 = pp->left) { #1
p2 = pp->right // + left
if (p2->color = RED) { p1->color = BLACK; p2->color = BLACK {case 1}
pp->color = RED
x = pp
}
else if(x = p1->right) { case 2
x = p1; left_rotate(x); p1 = x->parent
}
Case 3:
p1->color = BLACK
pp->color = RED
Right_rotate(pp)
} #1
else { //(p1 = pp->right) +right
#1 left swap to right
}
} #while
root->color = BLACK
}
DELETE(x) //p –parent,y-deleting element{
if (x->left = NULL || x->right = NULL ) { y = x} //0 child
else { y = successor(x)} // 1 or more childs
if (y->left ≠ NULL) { p = y->left}
else { p = y->right}
p->parent = y->parent
if (y->parent = NULL) {root = p}
else if (y->parent->left = y) { y->parent->left = p}
else { y->parent->right = p}
if (y ≠ x) {
x->key = y->key // +copy data
}
if (y->color = BLACK) {RB_Delete_Fixup(p)}
}
RB_DELETE_Fixup(x){ // x – double black
p = x->parent – родительский узел
w = p->right (или p->left)
while (x ≠ root и x->color == BLACK) {
p = x->parent
if (x == p->left) //left subtree { # 1 – начало
w = p->right
if (w->color == RED) { case 1
поменять цвета у w и p:
w->color = BLACK
p->color = RED
Left_Rotate(p)
w = p->right
}
if (w->left->color == BLACK и w->right-color == BLACK) { – случай 2
забрать черную окраску у w:
w->color = RED
переместиться вверх по дереву:
x = p
}
else {
if (w->right->color == BLACK) { – случай 3
поменять цвета у w и w->left:
w->color = RED
w->left->color = BLACK
правый поворот вокруг w:
Right_Rotate(w)
w = p->right
}
– случай 4
поменять цвета:
w->color = p->color
p->color = BLACK
w->right->color = BLACK
левый поворот вокруг узла p
Left_Rotate(p)
x = root
}
} # 1 – конец
else {
повторить коды между #1 – начало и #1 – конец, заменив left на right, и наоборот
}
}
x->color = BLACK
}