Структуры данных

MTUCI ICPC

Базовые структуры данных

  • Массив
  • Связный список
  • Куча
  • Стек

БАЗА

//Указатели
//Ссылки
memset
memcpy

Собственный динамический массив

template <typename T>
struct dynamic_array {
    T *t;
    int size = 0, capacity;
    
    dynamic_array(int capacity) : capacity(capacity) {
        t = new T[capacity];
    }

    void resize(int new_capacity) {
        T *new_t = new T[new_capacity];
        memcpy(new_t, t, sizeof(T) * size);
        delete[] t;
        t = new_t;
    }

    T get(int k) {
        return t[k];
    }

    T set(int k, T x) {
        t[k] = x;
    }

    void add(T x) {
        if (size == capacity)
            resize(2 * capacity);
        t[size++] = x;
    }

    void del() {
        // если хотим сэкономить память:
        if (4 * size < capacity)
            resize(capacity / 2);
        size--;
    }
};

Связные списки

#include <iostream>

using namespace std;

struct node
{
    int data;
    node *next;
};

class linked_list
{
private:
    node *head,*tail;
public:
    linked_list()
    {
        head = NULL;
        tail = NULL;
    }

    void add_node(int n)
    {
        node *tmp = new node;
        tmp->data = n;
        tmp->next = NULL;

        if(head == NULL)
        {
            head = tmp;
            tail = tmp;
        }
        else
        {
            tail->next = tmp;
            tail = tail->next;
        }
    }
};

int main()
{
    linked_list a;
    a.add_node(1);
    a.add_node(2);
    return 0;
}

Стек, очередь

struct ListNode {
    int data;
    ListNode *prev;
    ListNode *next;
};

class Deque {
public:
    ListNode* start, * last;
    Deque(){
        start = nullptr;
        last = nullptr;
    }

    void append(int data) {
        ListNode *cur = new ListNode;
        cur->data = data;
        if (start == nullptr){
            start = cur;
            last = cur;
        }
        else{
            last->next = cur;
            cur->prev=last;
            last = cur;
        }
    }
    void pop_back(){
        ListNode *newlast = last->prev;
        delete last;
        last = newlast;
        last->next = nullptr;
    }
    int back(){
        if (last!= nullptr){
        return last->data;
        }
    }
    int front(){
        return start->data;
    }
    void pop_front(){
        ListNode *newstart = start->next;
        delete start;
        start = newstart;
        last->prev = nullptr;
    }
};

Продвинутые структуры

  • Бинарное дерево
  • Суффиксное дерево
  • Дерево отрезков 
  • ...

Куча (пирамида, heap)

Куча в STL

int ints[] = {10,20,30,5,15};
vector<int> v(ints, ints + 5);

make_heap(v.begin(), v.end());
v.front(); // получить максимальный элемент (30)

pop_heap(v.begin(), v.end()); // удалить максимум из кучи
v.pop_back(); // уменьшить размер массива на единицу

v.push_back(99); // добавить элемент в конец массива
push_heap(v.begin(), v.end()); // вызовет sift_up от последнего элемента

sort_heap(v.begin(), v.end()); // сортировка кучей: в v будет записан отсортированный массив

-------------------------------------------------

priority_queue<int> q;

for (int x : {1,5,3,4,2,0})
    q.push(x);

q.top(); // вернуть максимальный элемент (5)
q.pop(); // удалить максимальный элемент

Реализация кучи

const int INF=1e9;

class Heap{
    vector<int> data;
    Heap(int size){data = vector<int>(size, -INF);};
    int max(){
        return data[0];
    }

//    [10, 16 ,9, 4, 5, 2, 1, 6, 8, 11]
// elem 3
// i 0


    void sift_down(int elem) {
        int i=0;
        while (2*i<data.size()){
            int left = 2*i;
            int right = 2*i+1;
            int less;
            if (data[right]>-INF && data[right]<data[left]){
                less = right;
            }
            else{
                less = left;
            }
            if(data[elem]<=data[less]){
                break;
            }
            swap(data[less], data[elem]);
            i = less;
        }
    }

    void sift_up(int elem){
        while (data[elem] > data[elem/2]){
            swap(data[elem], data[elem/2]);
            elem = elem/2;
        }
    }

};

Бинарное дерево поиска (BST)

Vanilla BST

struct Node{
    Node *l,*r,*parent;
    int value;
};

class BST{
    Node *root;
    BST(){};
    void add(int value){
        if (root == nullptr){
            root=new Node;
            root->value=value;
            return;
        }
        Node* cur = root;
        while (true){
            if (cur->value<value){
                if (cur->r==nullptr){
                    Node* tmp = new Node;
                    tmp->value=value;
                    tmp->parent=cur;
                    cur->r=tmp;
                    return;
                }
                cur=cur->r;
            }
            else{
                if(cur->l==nullptr){
                    Node* tmp = new Node;
                    tmp->value=value;
                    tmp->parent=cur;
                    cur->l=tmp;
                    return;
                }
                cur=cur->l;
            }
        }
    }
    bool contains(int elem){
        Node* cur = root;
        while (true){
            if (cur->value==elem){
                return true;
            }
            if (cur->value<elem){
                if (cur->r==nullptr){
                    return false;
                }
                cur=cur->r;
            }
            else{
                if(cur->l==nullptr){
                    return false;
                }
                cur=cur->l;
            }
        }

    }
};

Курево. (treap) = tree + heap

Красно-черное дерево (КЧД, RBT)

Основные операции для балансировки:

  • Инверсия цветов
  • Левый поворот
  • Правый поворот

Код КЧД со вставкой

#include <iostream>

using namespace std;

enum color{
    RED,
    BLACK
};

color invert(color t){
    if (t==RED){
        return BLACK;
    }
    return RED;
}

struct Node{
    Node *l, *r, *parent;
    color c;
    int data;
    Node(){
        l= nullptr;
        r= nullptr;
        parent = nullptr;
        data=0;
        c=BLACK;
    }
};

Node a;

Node *NIL= new Node();

void invertColors(Node* vert){
    vert->parent->parent->c = invert(vert->parent->parent->c);
    vert->parent->parent->l->c = invert(vert->parent->parent->l->c);
    vert->parent->parent->r->c = invert(vert->parent->parent->r->c);
}

void rightRot(Node* ded){
    Node* dedl = ded->l; //otec
    ded->l = dedl->r; // правые дети отца становятся левыми деда
    dedl->r->parent = ded;
    dedl->parent = ded->parent;
    dedl->r = ded;
    ded->parent=dedl;
    dedl->c = ded->c;
    ded->c = RED;
    if(ded->parent->l==ded){
        ded->parent->l=dedl;
    }
    else{
        ded->parent->r=dedl;
    }
}


void leftRot(Node* ded){
    Node* dedr = ded->l; //otec
    ded->r = dedr->l; // правые дети отца становятся левыми деда
    dedr->l->parent = ded;
    dedr->parent = ded->parent;
    dedr->l = ded;
    ded->parent=dedr;
    dedr->c = ded->c;
    ded->c = RED;
    if(ded->parent->l==ded){
        ded->parent->l=dedr;
    }
    else{
        ded->parent->r=dedr;
    }
}

class RBTree{
    Node* root;
    RBTree(){
        root=NIL;
    }
//    ~RBTree(){
//        delete root;
//    }
    void fixInsert(Node* node){
        if (node == root){
            node->c = BLACK;
            return;
        }

        while (node->parent->c==RED) { // нарушается свойство 3
            if (node->parent->parent->l==node->parent) {
                if (node->parent->parent->r->c==RED){
                    invertColors(node);
                    node = node->parent->parent;
                 }
                else {
                    if (node->parent->r == node) {
                        leftRot(node->parent->parent);
                        node = node->parent;
                    }
                    else{
                    rightRot(node->parent->parent);
                        node = node->parent;

                    }
                }
            }
            else{ // "отец" — правый ребенок
                if (node->parent->parent->l->c==RED){
                    invertColors(node);
                    node = node->parent->parent;
                }
                else {
                    if (node->parent->r == node) {
                        leftRot(node->parent->parent);
                        node = node->parent;
                    }
                    else{
                        rightRot(node->parent->parent);
                        node = node->parent;
                    }
                }
            }
        }
        root->c = BLACK;
    }

    void insert(int data){
        Node* node = new Node();
        node->data=data;
        node->c=RED;
        if(root==NIL){
            root=node;
            root->c=BLACK;
            root->parent=NIL;
            return;
        }
        Node* par = NIL;
        Node* cur = root;
        while (cur!=NIL){
            par = cur;
            if (cur->data<data){
                cur = cur->r;
            }
            else{
                cur=cur->l;
            }
        }
        node->parent=par;
        if(par->data<data){
            par->r=node;
        }
        else{
            par->l=node;
        }
        fixInsert(node);
    }

};




int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}
Made with Slides.com