---
# System prepended metadata

title: DSA

---

## Topo
```
#include <iostream>

using namespace std;

typedef struct leader* lref;
typedef struct trailer* tref;


struct leader{
    int key; // Key value
    int count; // Count leader before it, leader before it in topo
    lref next; // To next leader
    tref trailer; // Trailer will manage leader which stay behind current leader
};

struct trailer{
    lref id; // To leader which stay behind current leader

    tref next; // The next trailer of current leader
};

vector<lref> allNodes;

lref addList(lref& head, lref& tail, int w, int &z)
{
    lref h;

    h = head;

    tail->key = w;

    while(h->key != w) // Sequential Search to return q or p
    {
        h = h->next;
    }
    if(h == tail)
    { // need create new tail to be guard
        tail = new leader;

        h->next = tail;
        z++;
        h->count = 0;
        h->trailer = nullptr;
        //allNodes.push_back(h); // Easy  to delete node
    }
    
    return h;
}   


void update(lref& p, lref& q)
{
    tref t = new trailer;
    t->id = q;
    t->next = p->trailer;
    p->trailer = t;
    q->count++;
}

void topoSort(lref& head , lref& tail, int& z)
{
    lref p = head;
    lref q = p;
    head = nullptr; // head : list of node have count = 0

    while(p != tail)
    {
        q = p;
        p = p->next;
        --z;
        if(q->count == 0)
        {
            q->next = head;
            head = q;
        }
    }

    q = head;
    while(q)
    {
        cout << q->key << " ";
        tref t = q->trailer;
        q = q->next;
        while(t)
        {
            p = t->id;
            p->count--;
            if(p->count == 0)
            {
                p->next = q;
                q = p;
            }
            t = t->next;
        }
    }
}

void deleteTrailers(tref t) {
    while (t != NULL) {
        tref temp = t;
        t = t->next;
        delete temp;
    }
}

void deleteLeaders(lref head) {
    while (head != NULL) {
        lref temp = head;
        head = head->next;
        deleteTrailers(temp->trailer); // Giải phóng danh sách các trailer
        delete temp;
    }
}

int main()
{
    lref head, tail, p , q;
    int z, x, y;

    z = 0;
    head = new leader;
    tail = head;

    while(cin >> x >> y)
    {
        p = addList(head,tail, x , z);
        q = addList(head,tail, y , z);

        update(p, q);
    }
    lref head_tmp = head;

    topoSort(head, tail, z);
    if(z)
    {
        cout << "Error List!\n";
    }

    deleteLeaders(head_tmp);

}
```

## Radix Sort (Ứng dụng Hash)
+ Xác định số lớn nhất để xem lặp lại bao nhiêu lần
+ Mỗi lần lặp sẽ lặp sẽ tạo các leader theo thứ tự theo thứ tự tăng dần, leader sẽ chứa các trailer mà có kí số bằng đại diện đó 
+ Giống với sắp xếp Topo nhưng các leader được sắp tăng dần
+ Mỗi lần duyệt kí số sẽ nối trailer của leader trước nối trailer sau rồi xoá các leader(Coi ví dụ trong tập nhé mf)

```
#include <iostream>
#include <fstream>
#include <math.h>
#include "multi-link-list.h"
#include "radix-sort.h"

struct TRAILER //node quản lý các số dữ liệu thực sự
{
    int number;
    TRAILER* next;
};

struct TLIST //danh sách các trailer
{
    TRAILER* head;
};

struct LEADER //node quản lý các chữ số dùng để so sánh được sắp xếp thứ tự tăng dần của digit
{
    int digit;
    LEADER* next;
    TRAILER* trailerHead;
    TRAILER* trailerTail;
};

struct LLIST //danh sách các leader
{
    LEADER* head;
};
#include <iostream>
#include "multi-link-list.h"
TRAILER* createTrailer(int number)
{
    TRAILER* trailer = new TRAILER;
    if (!trailer)
    {
        std::cerr << "Cannot allocate memory\n";
        return nullptr;
    }
    trailer->next = nullptr;
    trailer->number = number;
    return trailer;
}

LEADER* createLeader(int digit)
{
    LEADER* leader = new LEADER;
    if (!leader)
    {
        std::cerr << "Cannot allocate memory\n";
        return nullptr;
    }
    leader->digit = digit;
    leader->next = nullptr;
    leader->trailerHead = nullptr;
    leader->trailerTail = nullptr;
    return leader;
}

void addHeadTrailer(TLIST& tlist, int number)
{
    TRAILER* newTrailer = createTrailer(number); 
    if (!newTrailer)
        return;

    if (tlist.head)
        newTrailer->next = tlist.head;
    tlist.head = newTrailer;
}

void delTrailer(TLIST& tlist)
{
    for (TRAILER* trailer = tlist.head; trailer; trailer = trailer->next)
        delete trailer;
    tlist.head = nullptr;
}

void delLeader(LLIST& llist)
{
    for (LEADER* leader = llist.head; leader; leader = leader->next)
        delete leader;
    llist.head = nullptr;
}

LEADER* getLeader(LLIST& llist, int digit)
{
    if (!llist.head) //leader list chưa có phần tử nào -> tạo phần tử đầu tiên
    {
        LEADER* newLeader = createLeader(digit);
        if (!newLeader)
            return nullptr;
        llist.head = newLeader;
        return llist.head;
    }

    //tìm leader với digit đã cho
    LEADER* fakeHead = createLeader(-1); //tạo một head giả trỏ đến head thật sự
    fakeHead->next = llist.head;
    LEADER* leader = fakeHead;
    while (leader->next && (leader->next)->digit < digit) //tìm phần tử cuối cùng 
                                                          //hoặc phần tử tiếp theo có digit lớn hơn hoặc bằng digit đã cho
            leader = leader->next;
    //nếu phần tử tiếp theo là nullptr hoặc có digit lớn hơn 
    //-> không tồn tại leader với digit đã cho
    //-> tạo leader mới
    if (!leader->next || (leader->next)->digit > digit)
    {
        LEADER* newLeader = createLeader(digit);
        newLeader->next = leader->next;
        if (leader == fakeHead)
            llist.head = newLeader;
        else
            leader->next = newLeader;
        return newLeader;
    }

    //trường hợp còn lại: phần tử tiếp theo có digit bằng với digit cho trước 
    //-> đã tồn tại leader với digit cho trước
    //-> trả về leader tiếp theo 
    return leader->next;
}

int main()
{
    TLIST tlist = {nullptr};
    std::ifstream f = openFile("input.txt");
    int k, n;
    f >> k >> n;
    for (int i = 0; i < n; i++) //tạo danh sách liên kết gồm các trailer
    {
        int number; 
        f >> number;
        addHeadTrailer(tlist, number);
    }
    radixSort(tlist, k);

    for (TRAILER* trailer = tlist.head; trailer; trailer=trailer->next)
        std::cout << trailer->number << " ";
    delTrailer(tlist);
    return 0;
}

std::ifstream openFile(const char path[])
{   
    std::ifstream f;
    f.open(path);
    if (!f) 
    {
        std::cerr << "Cannot open file!\n";
        exit(-1);
    }
    return f;
}

int getDigit(int number, int k, int i) //chia các chữ số thành các phần gồm k chữ số
                                       //lấy đoạn thứ i (i từ 0) từ phải qua trái
{
    return (number / (int)pow(10, k * i)) % (int)pow(10, k);
}

void radixSort(TLIST& tlist, int k)
{
    if (!tlist.head)
        return;

    int max = tlist.head->number;
    for (TRAILER* trailer = tlist.head; trailer; trailer = trailer->next) 
        if (max < trailer->number)
            max = trailer->number; //tìm số lớn nhất trong trailer list
    int times = ceil(ceil(log10(max)) / k); //tính toán số lần thực hiện vòng for 
                                            //sử dụng số lớn nhất để tính toán
                                            //công thức: số số chữ số chia số khoảng chia yêu cần (làm tròn lên)
    
    for (int i = 0; i < times; i++)
    {
        LLIST llist = {nullptr};
        TRAILER* trailer = tlist.head;
        do
        {
            int digit = getDigit(trailer->number, k, i);
            LEADER* leader = getLeader(llist, digit); //trả về leader giữ digit 
                                                      //nếu chưa tồn tại, tạo mới rồi trả về
            
            //addTail trailer để giữ tính stable của radix sort
            TRAILER* curTrailer = trailer; //lưu lại trailer hiện tại
            trailer = trailer->next;

            ////nếu leader đang xét chưa có trailer -> thêm vào và cập nhật trailerHead và trailerTail
            if (!leader->trailerHead)
            {
                leader->trailerHead = leader->trailerTail = curTrailer;
                curTrailer->next = nullptr;
                continue;
            }
            ////nếu leader đã có trailer
            curTrailer->next = nullptr;
            leader->trailerTail = (leader->trailerTail)->next = curTrailer;
        } while (trailer);

        //sau khi hoàn thành đưa các trailer vào đúng leader có digit theo thứ tự tăng dần
        //-> nối các trailer lại với nhau
        tlist.head = (llist.head)->trailerHead;
        for (LEADER* leader = llist.head; leader->next; leader = leader->next)
            (leader->trailerTail)->next = (leader->next)->trailerHead;
        delLeader(llist); //sau khi nối thì xóa hệ thống leader
    }
}
```
## Priority queue
### Heap
+ Insert, Extract -> siftUp
+ Remove -> siftDown
+ i = 0, j = 2*i + 1
```
#include <iostream>
using namespace std;

struct p_queue{
    int key;
    int priority; // do uu tien
};


void sift(p_queue* a, int l, int r)
{
    int i = l;
    int j = 2*i + 1;


    while(j < r)
    {
        if(j < r - 1)
        {
            if(a[j].priority > a[j+1].priority)
            {
                ++j;
            }
        }
        if(a[i].priority <= a[j].priority)
            break;

        swap(a[i], a[j]);
        i = j;
        j = i*2 + 1;
        
    }
}

void sift_up(p_queue* a, int index)
{
    int i = (index - 1)/2;
    int j = index;
    while(i)
    {
        if(a[j].priority < a[i].priority)
        {
            swap(a[j], a[i]);
        }
        else{
            break;
        }
        j = i;
        i = (j - 1) / 2;
    }
    
}

void Insert(p_queue*& a, int x, int priority, int& len)
{
    p_queue* b = new p_queue[len + 1];
    memcpy(b, a, len*sizeof(p_queue));
    b[len].key = x;
    b[len].priority = priority;

    delete[]a;

    a = b;

    int l = (len + 1) / 2 - 1;

    sift_up(b, len);
    ++len;

}

void Remove(p_queue*& a, int val, int& len)
{

    int index = 0;

    for(int i = 0 ; i < len; ++i)
    {
        if(a[i].key == val)
        {
            index = i;
            swap(a[index], a[len-1]);
            break;
        }
    }
    
    if(index == len)
        return;
    p_queue* b = new p_queue[len - 1];
    memcpy(b, a, (len - 1)*sizeof(p_queue));

    delete[] a;

    a = b;
    --len;

    sift(a, index, len);
}

int Extract(p_queue* a, int& len)
{
    if(len == 0)
    {
        return -1;
    }
    int val = a[0].key;

    swap(a[0], a[len-1]);
    --len;
    sift(a, 0, len);
    return val;
}


int main()
{
    p_queue *a = nullptr;
    int list[] = {1, 4, 5, 3, 2 ,7 ,6};
    int priority[] = {1, 2, 3, 4, 5 ,6 ,7};

    int n = 7;
    int l = n / 2 - 1;
    a = new p_queue[n];

    for(int i = 0 ; i < n ; ++i)
    {
        a[i].key = list[i];
        a[i].priority = priority[i];
    }

    while(l--)
    {
        sift(a,l,n);
    }

    for(int i = 0 ; i < n; ++i)
    {
        cout << a[i].key << "-" << a[i].priority << endl;
    }
    cout << "After insert \n";
    Insert(a, 10, 2, n);

    cout << n << endl;
    for(int i = 0 ; i < n; ++i)
    {
        cout << a[i].key << "-" << a[i].priority << endl;
    }

    cout << "After remove \n";
    Remove(a, 4, n);

    cout << n << endl;
    for(int i = 0 ; i < n; ++i)
    {
        cout << a[i].key << "-" << a[i].priority << endl;
    }

    cout << "Pop : " << Extract(a, n) << endl;
    for(int i = 0 ; i < n; ++i)
    {
        cout << a[i].key << "-" << a[i].priority << endl;
    }
}
```

### List
```
#include <iostream>
using namespace std;

struct PQNode{
    PQNode* next; 
    int key;
    int priority;

    PQNode(int key, int priority) : key(key), priority(priority), next(nullptr) {}

};

bool isEmpty(PQNode* head) {
        return head == nullptr;
    }

// Method to insert an object into the queue
void Insert(PQNode*& head, int key, int priority) {
    PQNode* newNode = new PQNode(key, priority); // Create a new node
    // If the queue is empty or the new node has higher priority than the head
    if (isEmpty(head) || head->priority > priority) {
        newNode->next = head; // Insert the new node at the beginning
        head = newNode;
    } else {
        // Find the correct position to insert the new node
        PQNode* current = head;
        while (current->next != nullptr && current->next->priority <= priority) {
            current = current->next;
        }
        newNode->next = current->next;
        current->next = newNode;
    }
}

// Method to extract (remove) the highest priority object from the queue
PQNode* Extract(PQNode*& head) {
    if (isEmpty(head)) {
        return nullptr; // Return null if the queue is empty
    }
    PQNode* temp = head; // Store the head node
    head = head->next; // Move the head to the next node
    return temp; // Return the original head node
}

// Method to remove an object with a specific ID from the queue
bool Remove(PQNode*& head, int val) {
    if (isEmpty(head)) {
        return false; // Return false if the queue is empty
    }
    if (head->key == val) {
        // Remove the head node if it matches the ID
        PQNode* temp = head;
        head = head->next;
        delete temp;
        return true;
    }
    // Search for the node with the given ID
    PQNode* current = head;
    while (current->next != nullptr && current->next->key != val) {
        current = current->next;
    }
    if (current->next == nullptr) {
        return false; // Return false if the ID is not found
    }
    // Remove the found node
    PQNode* temp = current->next;
    current->next = temp->next;
    delete temp;
    return true;
}

// Method to change the priority of an object with a specific ID
bool changePriority(PQNode*& head,int val, int newPriority) {
    if (Remove(head, val)) {
        // If the object is successfully removed, re-insert it with the new priority
        Insert(head, val, newPriority);
        return true;
    }
    return false; // Return false if the object with the specified ID is not found
}

void printQueue(PQNode* a)
{
    PQNode* p = a;
    while(p)
    {
        cout << p->key << " - " << p->priority << endl;
        p = p->next;
    }

}

int main()
{
    PQNode *a;

    int list[] = {1, 4, 5, 3, 2 ,7 ,6};
    int priority[] = {1, 2, 3, 4, 5 ,6 ,7};

    int n = 7;

    for(int i = 0 ; i < n; ++i)
    {
        Insert(a, list[i], priority[i]);
    }
    printQueue(a);
    cout << "After insert 10 : " << endl;
    Insert(a, 10, 2);
    printQueue(a);
    Remove(a, 4);
    printQueue(a);
}
```

## BST

+ Sử dụng dummyHead để gán hai node ý tưởng để khử đệ qui
```
#include <bits/stdc++.h>
using namespace std;


template<typename T>
class Stack {
private:
    struct StackNode {
        T data;
        StackNode* next;

        StackNode(T data) : data(data), next(nullptr) {}
    };

    StackNode* topNode;

public:
    Stack() : topNode(nullptr) {}

    ~Stack() {
        while (!isEmpty()) {
            pop();
        }
    }

    void push(T data) {
        StackNode* newNode = new StackNode(data);
        newNode->next = topNode;
        topNode = newNode;
    }

    void pop() {
        if (isEmpty()) {
            return;
        }
        StackNode* temp = topNode;
        topNode = topNode->next;
        delete temp;
    }

    T top() {
        if (!isEmpty()) {
            return topNode->data;
        }
        return nullptr; // Handle this appropriately in your code
    }

    bool isEmpty() {
        return topNode == nullptr;
    }
};


struct NODE{ // AVL
    int key;
    NODE* pLeft;
    NODE* pRight;
    int height;
};


struct BSTNODE{
    int key;
    BSTNODE* pLeft;
    BSTNODE* pRight;

};

BSTNODE* createNode(int data){
    BSTNODE* pNode = new BSTNODE;
    pNode->key = data;
    pNode->pLeft = NULL;
    pNode->pRight = NULL;

    return pNode;
}

NODE* createNodeAVL(int data){
    NODE* pNode = new NODE;
    pNode->key = data;
    pNode->height = 0;
    pNode->pLeft = nullptr;
    pNode->pRight = nullptr;

    return pNode;
}

void Insert(BSTNODE* &pRoot, int x){
    if (pRoot == NULL)
        pRoot = createNode(x);
    else if (x < pRoot->key)
        Insert(pRoot->pLeft, x);
    else if (x > pRoot->key)
        Insert(pRoot->pRight, x);
}

void Insert(BSTNODE*& dummyHead, BSTNODE*& root, int x)
{
    if(root == nullptr)
    {
        root = createNode(x);
        return;
    }
    BSTNODE* p1 = root; // p2 is parent of p1
    BSTNODE* p2 = dummyHead;
    while(p1 != nullptr)
    {
        if(p1->key == x)
            return;
        p2 = p1;
        if(p1->key > x)
        {
            p1 = p1->pLeft;
        }
        else{
            p1 = p1->pRight;
        }
    }
    p1 = createNode(x);

    if(p2->key > x)
    {
        p2->pLeft = p1; 
    }
    else
    {
        p2->pRight = p1;
    }
}

int Height(BSTNODE* pRoot){
    if (pRoot == NULL)
        return -1;

    return max(Height(pRoot->pLeft), Height(pRoot->pRight)) + 1;
}

void printTree(BSTNODE* r, int indent = 0) 
{
    if (r != nullptr) {
        if (r->pRight) {
            printTree(r->pRight, indent + 5);
        }
        if (indent > 0) {
            cout << setw(indent) << " ";
        }
        cout << "[" << r->key << "]" << endl;
        if (r->pLeft) {
            printTree(r->pLeft, indent + 5);
        }
    }
}

void printTree(NODE* r, int indent = 0) 
{
    if (r != nullptr) {
        if (r->pRight) {
            printTree(r->pRight, indent + 5);
        }
        if (indent > 0) {
            cout << setw(indent) << " ";
        }
        cout << "[" << r->key << "]" << endl;
        if (r->pLeft) {
            printTree(r->pLeft, indent + 5);
        }
    }
}
void createTree(BSTNODE*& dummy, BSTNODE*& root, int a[], int n)
{
    if(n <= 0)
        return;


    for(int i = 0 ; i < n; ++i)
    {
        Insert(dummy, root, a[i]);
    }
}

// 6. Level-order Traversal:
void LevelOrder(BSTNODE* pRoot){
    if (pRoot == NULL)
        return;

    queue<BSTNODE*> Q;
    Q.push(pRoot);
    while (!Q.empty()){
        BSTNODE* p = Q.front();
        Q.pop();

        cout << p->key << " ";
        if (p->pLeft != NULL)
            Q.push(p->pLeft);
        if (p->pRight != NULL)
            Q.push(p->pRight);
    }
}

// BSTNODE* Search(BSTNODE* pRoot, int x){
//     if (pRoot == NULL)
//         return NULL;

//     if (x == pRoot->key)
//         return pRoot;
//     else if (x < pRoot->key)
//         return Search(pRoot->pLeft, x);
//     else
//         return Search(pRoot->pRight, x);
// }

BSTNODE* Search(BSTNODE* root, int x)
{
    if(root == nullptr)
        return root;

    BSTNODE* p1 = root;
    while(p1 != nullptr)
    {
        if(p1->key == x)
            return p1;
        if(p1->key > x)
        {
            p1 = p1->pLeft;
        }
        else{
            p1 = p1->pRight;

        }
    }
    return nullptr;
}

BSTNODE* findRightMostNode(BSTNODE* pRoot){
    // pRoot must be not null
    if (pRoot->pRight == NULL)
        return pRoot;
    return findRightMostNode(pRoot->pRight);
}

void Del(BSTNODE*& root, int x)
{
    if(root == nullptr)
        return;
    
    if(root->key < x)
        Del(root->pRight, x);
    else if (root->key > x)
        Del(root->pLeft, x);
    else
    {
        if(root->pLeft == nullptr && root->pRight == nullptr) // no child
        {
            delete root;
            root = nullptr;
        }
        else if (root->pLeft == nullptr || root->pRight == nullptr)
        {
            if(root->pLeft == nullptr)
            {
                BSTNODE* tmp = root->pRight;
                delete root;
                root = tmp;
            }
            else
            {
                BSTNODE* tmp = root->pLeft;

                delete root;
                root = tmp;
            }
        }
        else
        {
            BSTNODE* rightMost = findRightMostNode(root->pLeft);
            root->key = rightMost->key;
            Del(root->pLeft, rightMost->key);
        }
    }
}

void DeleteNode(BSTNODE*& root, int x) { # Non-recursive
    BSTNODE* parent = nullptr;
    BSTNODE* current = root;

    // Tìm node cần xoá
    while (current != nullptr && current->key != x) {
        parent = current;
        if (x < current->key) {
            current = current->pLeft;
        } else {
            current = current->pRight;
        }
    }

    // Nếu không tìm thấy node cần xoá
    if (current == nullptr) {
        return;
    }

    // Nếu node có hai con
    if (current->pLeft != nullptr && current->pRight != nullptr) {
        BSTNODE* successor = current->pRight;
        BSTNODE* successorParent = current;

        // Tìm node kế cận (node có giá trị nhỏ nhất trong cây con phải của current)
        while (successor->pLeft != nullptr) {
            successorParent = successor;
            successor = successor->pLeft;
        }

        // Copy giá trị của successor vào current
        current->key = successor->key;

        // Di chuyển current và parent đến node kế cận để xoá
        current = successor;
        parent = successorParent;
    }

    // Node có một hoặc không có con
    BSTNODE* child = (current->pLeft != nullptr) ? current->pLeft : current->pRight;

    // Xác định node cần xoá là con trái hay con phải của parent
    if (parent == nullptr) {
        root = child;
    } else if (parent->pLeft == current) {
        parent->pLeft = child;
    } else {
        parent->pRight = child;
    }

    // Xoá node
    delete current;
}
```
## AVL
```jk
int getHeight(NODE* root)
{
    if(root == nullptr)
        return 0;
    return max(getHeight(root->pLeft), getHeight(root->pRight)) + 1;
}


void UpdateHeight(NODE*& p){
    if (p == nullptr) return;

    p->height = max(getHeight(p->pLeft), getHeight(p->pRight)) + 1;
}



NODE* LeftRotation(NODE* pRoot){
    NODE* child = pRoot->pRight;
    pRoot->pRight = child->pLeft;
    child->pLeft = pRoot;

    UpdateHeight(pRoot);
    UpdateHeight(child);

    return child;
}

NODE* RightRotation(NODE* pRoot){
    NODE* child = pRoot->pLeft;
    pRoot->pLeft = child->pRight;
    child->pRight = pRoot;

    UpdateHeight(pRoot);
    UpdateHeight(child);

    return child;
}

int BalanceFactor(NODE* p){
    if (p == NULL) return 0;
    return getHeight(p->pLeft) - getHeight(p->pRight);
}

void Balance(NODE*& pRoot){
    if (pRoot == NULL) 
        return;

    UpdateHeight(pRoot);
    int balanceFactor = BalanceFactor(pRoot);

    if (abs(balanceFactor) <= 1) 
        return;

    // Left Left
    if (balanceFactor > 1 && BalanceFactor(pRoot->pLeft) >= 0){
        pRoot = RightRotation(pRoot);
    }

    // Right Right
    else if (balanceFactor < -1 && BalanceFactor(pRoot->pRight) < 0){
        pRoot = LeftRotation(pRoot);
    }

    // Left Right
    else if (balanceFactor > 1 && BalanceFactor(pRoot->pLeft) < 0){
        pRoot->pLeft = LeftRotation(pRoot->pLeft);
        pRoot = RightRotation(pRoot);
    }

    // Right Left
    else if(balanceFactor < -1 && BalanceFactor(pRoot->pRight) >= 0){
        pRoot->pRight = RightRotation(pRoot->pRight);
        pRoot = LeftRotation(pRoot);
    }
}

void Insert(NODE* &pRoot, int x){
    if (pRoot == nullptr){
        pRoot = createNodeAVL(x);
        return;
    }

    if (x < pRoot->key){
        Insert(pRoot->pLeft, x);
        UpdateHeight(pRoot->pLeft);
    }
    else if (x > pRoot->key){
        Insert(pRoot->pRight, x);
        UpdateHeight(pRoot->pRight);
    }
    else
        return;
    
    Balance(pRoot);
}

void RemoveRightmost(NODE*& pRoot, NODE*& tmp){
    if (pRoot->pRight != NULL){
        RemoveRightmost(pRoot->pRight, tmp);
    }
    else{
        tmp->key = pRoot->key;
        tmp = pRoot;
        pRoot = pRoot->pLeft;
        delete tmp;
    }

    Balance(pRoot);
}

void Remove(NODE* &pRoot, int x){
    if (pRoot == NULL)
        return;
    
    if (x < pRoot->key)
        Remove(pRoot->pLeft, x);
    else if (x > pRoot->key)
        Remove(pRoot->pRight, x);
    else{
        // FOUND
        NODE* tmp = pRoot;
        if (pRoot->pLeft == NULL){
            pRoot = pRoot->pRight;
            delete tmp;
        }
        else if (pRoot->pRight == NULL){
            pRoot = pRoot->pLeft;
            delete tmp;
        }
        else
            RemoveRightmost(pRoot->pLeft, tmp);
    }

    Balance(pRoot);
}


void balanceTree(NODE*& node) {
    if (node == nullptr) {
        return;
    }

    // Balance the left subtree
    balanceTree(node->pLeft);

    // Balance the right subtree
    balanceTree(node->pRight);

    // Get the balance factor of this node to check whether
    // this node became unbalanced
    int balance = BalanceFactor(node);

    // If this node becomes unbalanced, then there are 4 cases

    // Left Left Case
    if (balance > 1 && BalanceFactor(node->pLeft) >= 0) {
        node = RightRotation(node);
    }

    // Left Right Case
    if (balance > 1 && BalanceFactor(node->pLeft) < 0) {
        node->pLeft = LeftRotation(node->pLeft);
        node = RightRotation(node);
    }

    // Right Right Case
    if (balance < -1 && BalanceFactor(node->pRight) <= 0) {
        node = LeftRotation(node);
    }

    // Right Left Case
    if (balance < -1 && BalanceFactor(node->pRight) > 0) {
        node->pRight = RightRotation(node->pRight);
        node = LeftRotation(node);
    }

    // Return the node pointer
}

void InsertNonRecursive(NODE*& root, int x) {
    Stack<NODE**> path;
    // Find the position to insert the new node
    NODE** p = &root;
    while (*p != nullptr) {

        path.push(p); // Store the path for later balancing
        if (x < (*p)->key) {
            p =&((*p)->pLeft);
        } else if (x > (*p)->key) {
            p =&((*p)->pRight);

        } else { // Element already exists
            return;
        }
    }

    // Create new node
    *p = createNodeAVL(x);

    // Traverse back up the tree and balance each node
    while (!path.isEmpty()) {
        p = path.top();
        path.pop();
        if(abs(BalanceFactor(*p)) > 1)
        {
            UpdateHeight(*p);
            Balance(*p);
            break; // Dung lai khi gap nut mat can bang
        }
    }
    UpdateHeight(root);
}


void RemoveNonRecursive(NODE*& root, int x) {
    Stack<NODE*> path;
    NODE* p = root;

    NODE* parent = nullptr;

    // Tìm node cần xoá
    while (p != nullptr && (p)->key != x) {
        path.push(p); // Store the path for later balancing

        parent = p;
        if (x < (p)->key) {
            p = ((p)->pLeft);
        } else if (x > p->key){
            p = ((p)->pRight);
        }
        else
            break;
    }

    // Nếu không tìm thấy node cần xoá
    if (p == nullptr) {
        return;
    }
    // Nếu node có hai con
    if (p->pLeft != nullptr && p->pRight != nullptr) {
        NODE* successor = p->pRight;
        NODE* successorParent = p;

        // Tìm node kế cận (node có giá trị nhỏ nhất trong cây con phải của current)
        while (successor->pLeft != nullptr) {
            path.push(successorParent);
            successorParent = successor;
            successor = successor->pLeft;
        }

        // Copy giá trị của successor vào current
        p->key = successor->key;

        // Di chuyển current và parent đến node kế cận để xoá
        p = successor;
        parent = successorParent;
    }

    // Node có một hoặc không có con
    NODE* child = (p->pLeft != nullptr) ? p->pLeft : p->pRight;

    // Xác định node cần xoá là con trái hay con phải của parent
    if (parent == nullptr) {
        root = child;
    } else if (parent->pLeft == p) {
        parent->pLeft = child;
    } else {
        parent->pRight = child;
    }

    // Xoá node
    delete p;

    // Traverse back up the tree and balance each node
    while (!path.isEmpty()) {
        p = path.top();
        path.pop();
        if(abs(BalanceFactor(p)) >= 1)
        {
            UpdateHeight(p);
            Balance(p);
        }

    }
}


int main()
{
    int a[] = {3,2,4,5,6,7,2,3,5};
    int n = sizeof(a)/sizeof(a[0]);
    BSTNODE* dummyHead = new BSTNODE;
    BSTNODE* root = nullptr;
    dummyHead->pRight = root;
    createTree(dummyHead, root, a, n);
    //LevelOrder(root);
    // printTree(root);
    // BSTNODE* node = Search(root, 7);
    // cout << node->key << endl;

    // DeleteNode(root, 3);
    // printTree(root);

    // DeleteNode(root, 2);
    // printTree(root);


    // AVL Tree

    NODE* AVL_root = nullptr;

    for(int i = 0; i < n ; ++i)
    {
        InsertNonRecursive(AVL_root, a[i]);
        //printTree(AVL_root, a[i]);
    }

    printTree(AVL_root);
    cout <<"-------------------------\n";
    InsertNonRecursive(AVL_root,8);
    printTree(AVL_root);
    cout <<"-------------------------\n";
    RemoveNonRecursive(AVL_root,5);
    printTree(AVL_root);

    cout <<"-------------------------\n";
    RemoveNonRecursive(AVL_root,4);
    printTree(AVL_root);

    cout <<"-------------------------\n";
    RemoveNonRecursive(AVL_root,6);
    printTree(AVL_root);

}
```

## Đỏ đen

```
#include <iostream>
using namespace std;

struct RBNode{
    int key;
    bool color; //Black = 0
    RBNode* parent;
    RBNode* left;
    RBNode* right;
};

RBNode* nil;

RBNode* getNode(int key, int color, RBNode* nil)
{
    RBNode* p = new RBNode;
    p->key = key;
    p->color = color;
    p->left = p->right = p->parent = nil;
    return p;
}

void leftRotate(RBNode*& root, RBNode* x)
{
    RBNode* y = x->right;
    x->right = y->left;
    if (y->left != nil)
    {
        y->left->parent = x;
    }
    y->parent = x->parent;
    if(x->parent == nil)
    {
        root = y;
    }
    else
    {
        if(x->parent->left == x)
        {
            x->parent->left = y;
        }
        else 
            x->parent->right = y;
    }
    y->left = x;
    x->parent = y;
}

void rightRotate(RBNode*& root, RBNode* x)
{
    RBNode* y = x->left;
    x->left = y->right;
    if (y->right != nil)
    {
        y->right->parent = x;
    }
    y->parent = x->parent;
    if(x->parent == nil)
    {
        root = y;
    }
    else
    {
        if(x->parent->left == x)
        {
            x->parent->left = y;
        }
        else 
            x->parent->right = y;
    }
    y->right = x;
    x->parent = y;
}

void insertLeftAdjust(RBNode* &pRoot, RBNode* ref) { // parent in left side
    RBNode* p = ref->parent->parent->right;

    if (p->color == true) { //case 1
        ref->parent->color = false;

        p->color = false;

        ref->parent->parent->color = true;

        ref = ref->parent->parent;
    } else {
        //Case 2 or case 3
        if (ref == ref->parent->right) {
            ref = ref->parent;

            leftRotate(pRoot, ref);
        }
        //case 3 
        ref->parent->color = false;

        ref->parent->parent->color = true;

        rightRotate(pRoot, ref->parent->parent);
    }
}

void insertRightAdjust(RBNode* &pRoot, RBNode* ref) {
    RBNode* p = ref->parent->parent->left;

    if (p->color == true) {
        ref->parent->color = false;

        p->color = false;

        ref->parent->parent->color = true;

        ref = ref->parent->parent;
    } else {
        if (ref == ref->parent->left) {
            ref = ref->parent;

            rightRotate(pRoot, ref);
        }

        ref->parent->color = false;

        ref->parent->parent->color = true;

        leftRotate(pRoot, ref->parent->parent);
    }
}

void inserFixedUp(RBNode*  &pRoot, RBNode* ref) {
    while (ref->parent->color == true) {
        if (ref->parent == ref->parent->parent->left) {
            insertLeftAdjust(pRoot, ref);
        } else {
            insertRightAdjust(pRoot, ref);
        }
    }

    pRoot->color = false;
}

void BST_Insert(RBNode*& root, RBNode* x)
{
    RBNode* y = nil;
    RBNode* z = root;
    while(z != nil)
    {
        y = z;
        if(x->key < z->key)
            z = z->left;
        else if(x->key > z->key)
            z = z->right;
        else
            return;
    }
    x->parent = y;
    if(y == nil)
        root = x;
    else
    {
        if(x->key < y->key)
            y->left = x;
        else 
            y->right = x;
    }
}

void insert(RBNode*& root, int key)
{
    RBNode* x = getNode(key, true, nil);
    BST_Insert(root, x);
    inserFixedUp(root, x);
}

RBNode* createTree(int a[], int n) {
    RBNode* pRoot = nil;

    for (int i = 0; i < n; i++) {
        insert(pRoot, a[i]);
    }

    return pRoot;
}

RBNode* lookUp(RBNode* pRoot, int key) {
    RBNode* ans = pRoot;

    while (ans != nil) {
        if (ans->key == key) {
            return ans;
        }

        if (ans->key > key) {
            ans = ans->left;
        } else {
            ans = ans->right;
        }
    }

    return nil;
}

int blackHeight(RBNode* pRoot) {
    if (pRoot == nil) {
        return 1;
    }

    int leftBlackHeight = blackHeight(pRoot->left);
    int rightBlackHeight = blackHeight(pRoot->right);

    if (leftBlackHeight != rightBlackHeight) {
        return 0;
    }

    if (pRoot->color == false) {
        leftBlackHeight++;
    }

    return leftBlackHeight;
}


void removeLeftAdjust(RBNode* pRoot, RBNode* ref) {
    RBNode* p = ref->parent->right;

    if (p->color == true) {
        p->color = false;

        ref->parent->color = true;

        leftRotate(pRoot, ref->parent);

        p = ref->parent->right;
    }

    if (p->right->color == false && p->left->color == false) {
        p->color = true;

        ref = ref->parent;
    } else {
        if (p->right->color == false) {
            p->left->color = false;
            p->color = true;
            
            rightRotate(pRoot, p);
            p = ref->parent->right;
        }

        p->color = ref->parent->color;

        ref->parent->color = false;

        p->right->color = false;

        leftRotate(pRoot, ref->parent);

        ref = pRoot;
    }
}

void removeRightAdjust(RBNode* pRoot, RBNode* ref) {
    RBNode* p = ref->parent->left;

    if (p->color == true) {
        p->color = false;

        ref->parent->color = true;

        rightRotate(pRoot, ref->parent);

        p = ref->parent->left;
    }

    if (p->left->color == false && p->right->color == false) {
        p->color = true;

        ref = ref->parent;
    } else {
        if (p->left->color == false) {
            p->right->color = false;
            p->color = true;

            leftRotate(pRoot, p);
            p = ref->parent->left;
        }

        p->color = ref->parent->color;

        ref->parent->color = false;

        p->left->color = false;

        rightRotate(pRoot, ref->parent);

        ref = pRoot;
    }
}

void removeFixedUp(RBNode* pRoot, RBNode* ref) {
    while ((ref->color == false) && (ref != pRoot)) {
        if (ref == ref->parent->left) {
            removeLeftAdjust(pRoot, ref);
        } else {
            removeRightAdjust(pRoot, ref);
        }
    }

    ref->color = false;
}

RBNode* minimum(RBNode* pRoot, RBNode* ref) {
    while (ref->left != nil) {
        ref = ref->left;
    }

    return ref;
}

RBNode* maximum(RBNode* pRoot, RBNode* ref) {
    while (ref->right != nil) {
        ref = ref->right;
    }

    return ref;
}

RBNode* treeSuccessor(RBNode* pRoot, RBNode* ref) {
    if (ref->right != nil) {
        return minimum(pRoot, ref->right);
    }

    RBNode* y = ref->parent;

    while (y != nil && ref == y->right) {
        ref = y;
        y = y->parent;
    }

    return y;
}

//return 0 if key does not appear in tree, therefore cannot remove
//return 1 if successfully remove
int remove(RBNode* pRoot, int key) {
    RBNode* pFind = lookUp(pRoot, key);

    if (pFind == nil) {
        return 0;
    }

    RBNode* y;
    if (pFind->left == nil || pFind->right == nil) {
        y = pFind;
    } else {
        y = treeSuccessor(pRoot, pFind);
    }
    
    RBNode* x;
    if (y->left != nil) {
        x = y->left;
    } else {
        x = y->right;
    }

    if (x != nil) {
        x->parent = y->parent;
    }

    if (y->parent == nil) {
        pRoot = x;
    } else if (y == y->parent->left) {
        y->parent->left = x;
    } else {
        y->parent->right = x;
    }

    if (y != pFind) {
        pFind->key = y->key;
    }

    if (y->color == false) {
        removeFixedUp(pRoot, x);
    }

    delete y;
}


int main(){
    nil = new RBNode;
    nil->color = false;
    nil->left = nil->right = nil->parent = nil;
    RBNode* root = nil;

}
```

## Graph

```
Prim(G, root) {
    for (each vertex v in V) {
        v.dist = INF;
        v.parent = NIL;
    }
    root.dist = 0; VT = ∅;
    createQueue(Q, V);
    while (!isEmpty(Q)){
        v* = extractQueue(Q);
        add v* to VT;
        for (each v in Q that is adjacent to v*)
        if (G[v*][v] < v.dist) {
            v.dist = G[v*][v];
            v.parent = v*;
            updateQueue(Q, v);
        }
    }
}
```
```
void Prim(Graph g, int root)
{
    int len = g.getV();
    prim* lst = new prim[len];
    for(int i = 0 ; i < len ; ++i)
    {
        lst[i].priority = i + 1;
        lst[i].dist = INFINITY;
        lst[i].parent = nullptr;
    }
    lst[root].dist = 0;
    p_queue* Q = nullptr;
    createQueue(Q, lst, len);

    while(Q->len > 0)
    {
        prim v_star = Extract(Q,Q->len);

        // DUyet ma tran trong so de lay ra cac dinh ke cua v_star roi thuc hien nhu ma gia
    }
}

```


```
Dijkstra(G(V, E), source) {
    for (each vertex v ! V) {
    v.dist = ";
    v.parent = NIL;
    }
    source.dist = 0; VT = #;
    createQueue(Q, V);
    while (!isEmpty(Q)) {
        v* = extractQueue(Q);
        add v* to VT;
        for (each v ! Q that is adjacent to v*)
            if (v*.dist + G[v*][v] < v.dist) {
            v.parent = v*;
            v.dist = v*.dist + G[v*][v];
            updateQueue(Q, v);
            }
    }
}
```
