[Computer Basics] Überprüfung der Datenstruktur

Notieren Sie einige der Probleme, auf die Einzelpersonen bei der Überprüfung der Datenstruktur stoßen

Finden
Ausgeglichener Binärbaum
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <windows.h>

using namespace std;

#pragma region Struct
typedef struct TreeNode {
    int balance;
    int data;
    TreeNode *left;
    TreeNode *right;
    TreeNode *parent;
} * PNODE, NODE;

typedef struct Tree {
    TreeNode *root;
    int height;
} TREE;
#pragma endregion

#pragma region Stack
PNODE *STK = nullptr;
int _stop = 0;
void PUSH(PNODE node) {
    STK[_stop++] = node;
}
PNODE POP() {
    return STK[--_stop];
}
PNODE PEEK() {
    return STK[_stop - 1];
}
#pragma endregion

void setpoint(PNODE *node, int lr) {
    if (lr == 1) {
        (*node)->left->balance = -1;
        (*node)->right->balance = 0;
    } else if (lr == -1) {
        (*node)->left->balance = 0;
        (*node)->right->balance = 1;
    } else {
        (*node)->left->balance = 0;
        (*node)->right->balance = 0;
    }
}
//
void LRotate(PNODE *node) {
    PNODE temp = *node;
    (*node) = (*node)->right;
    temp->right = (*node)->left;
    (*node)->left = temp;
    if (temp->balance == 2) {
        temp->balance = 0;
        (*node)->balance = 0;
    }
}
//
void RRotate(PNODE *node) {
    PNODE temp = *node;
    (*node) = (*node)->left;
    temp->left = (*node)->right;
    (*node)->right = temp;
    if (temp->balance == -2) {
        temp->balance = 0;
        (*node)->balance = 0;
    }
}
///LR balance
void LBalance(PNODE *node) {
    PNODE temp = *node;
    PNODE temp2 = (*node)->left;
    int lr = temp2->right->balance;
    LRotate(&((*node)->left));
    RRotate(node);
    (*node)->balance = 0;
    setpoint(node, lr);
}

///RL balance
void RBalance(PNODE *node) {
    PNODE temp = *node;
    PNODE temp2 = (*node)->right;
    int lr = temp2->left->balance;
    RRotate(&((*node)->right));
    LRotate(node);
    (*node)->balance = 0;
    setpoint(node, lr);
}

PNODE InsertNode(int data, PNODE node) { // O(logn)
    if (node == nullptr)
        return nullptr;
    PNODE _r = node, _p = node, _o = node;
    ///true -L false -R
    bool last = true;

    //找节点
    while (_r != nullptr) {
        PUSH(_r);
        if (_r->data <= data) {
            if (_r->data == data) { //节点已存在
                _stop = 0;
                return _o;
            }
            if (_r->right != nullptr) {
                _r = _r->right;
            } else {
                _r->right = (PNODE)malloc(sizeof(NODE));
                _r = _r->right;
                _r->data = data;
                _r->balance = 0;
                _r->left = _r->right = nullptr;
                PUSH(_r);
                // last = false;
                break;
            }
        } else {
            if (_r->left != nullptr)
                _r = _r->left;
            else {
                _r->left = (PNODE)malloc(sizeof(NODE));
                _r = _r->left;
                _r->data = data;
                _r->balance = 0;
                _r->left = _r->right = nullptr;
                PUSH(_r);
                // last = true;
                break;
            }
        }
    }

    //更新平衡度 并记录不平衡根
    _o = _p = nullptr;
    for (int i = 1; i < _stop; i++) {
        if (STK[i - 1]->left == STK[i]) {
            STK[i - 1]->balance -= 1;
            if (STK[i - 1]->balance == -2) {
                _p = STK[i - 1];
                if (i - 2 >= 0) {
                    _o = STK[i - 2];
                }
            }
            if (i > 2 && _p != nullptr && STK[i - 2] == _p) {
                last = true;
            }
        } else {
            STK[i - 1]->balance += 1;
            if (STK[i - 1]->balance == 2) {
                if (i - 2 >= 0){
                    _o = STK[i - 2];
                }
                _p = STK[i - 1];
            }
            if (i > 2 && _p != nullptr && STK[i - 2] == _p) {
                last = false;
            }
        }
    }

    //平衡
    PNODE newr = STK[0];
    if (_p != nullptr) {
        if (_p->balance == 2) {
            if (_o == nullptr) {
                if (last) {
                    newr = _p->right->left; //RL
                    RBalance(&_p);
                } else {
                    newr = _p->right; //RR
                    LRotate(&_p);
                }
            } else {
                if (last) {
                    if (_p == _o->left)
                        RBalance(&_o->left);
                    else
                        RBalance(&_o->right);
                } else {
                    if (_p == _o->left)
                        LRotate(&_o->left);
                    else
                        LRotate(&_o->right);
                }
            }
        } else {
            if (_o == nullptr) { //_p 是树根
                if (!last) {
                    newr = _p->left->right; //LR
                    LBalance(&_p);
                } else {
                    newr = _p->left; //LL
                    RRotate(&_p);
                }
            } else {// _p 不是树根,则找到p的父节点
                if (!last) {
                    if (_p == _o->left)
                        LBalance(&_o->left);
                    else
                        LBalance(&_o->right);
                } else {
                    if (_p == _o->left)
                        RRotate(&_o->left);
                    else
                        RRotate(&_o->right);
                }
            }
        }
    }

    //修正之前节点平衡度
    if (_o != nullptr) {
        for (int i = 1;; i++) {
            if (STK[i] == STK[i - 1]->left) {
                STK[i - 1]->balance += 1;
            } else {
                STK[i - 1]->balance -= 1;
            }
            if (STK[i - 1] == _o)
                break;
        }
    }

    _stop = 0;
    return newr;
}

Tree *GenerateTree(int *dataarr, int size, PNODE root) {
    Tree *tree = (Tree *)malloc(sizeof(Tree));
    int maxleaf = pow(2, ((int)log2(size) + 1));
    STK = (PNODE *)malloc(maxleaf * sizeof(PNODE));
    PNODE _r = root;
    if (root == nullptr) {
        _r = (PNODE)malloc(sizeof(NODE));
        _r->balance = 0;
        _r->data = dataarr[0];
        _r->parent = _r->left = _r->right = nullptr;
    }
    for (size_t i = 1; i < size; i++) {
        _r = InsertNode(dataarr[i], _r);
    }

    tree->root = _r;
    return tree;
}

void FillNode(PNODE p, int left, int right) {
    p->left = (PNODE)malloc(sizeof(NODE));
    p->left->data = left;
    p->left->left = nullptr;
    p->left->right = nullptr;
    p->right = (PNODE)malloc(sizeof(NODE));
    p->right->data = right;
    p->right->left = nullptr;
    p->right->right = nullptr;
}

int main() {
    // FillNode(p->right, 5, 6);
    int array[] = {1, 20, 5, 18, 6, 17, 7, 16, 13, 12, 21, 22, 9};

    Tree *root = GenerateTree(array, 12, nullptr);
    // RRotate(&o->left);

    cout << "";
    // root;
    cout << "";
}

Beim Schreiben war ich zunächst etwas verwirrt über Zeigeroperationen und dachte, wenn beide Zeiger auf den Knoten des Baums zeigen, kann ein Zeiger so geändert werden, dass er den Baum widerspiegelt, auf den der Stammzeiger zeigt (nur andere Zeiger können ohne Rekursion verwendet werden). Um die aktuelle Position zu speichern, ist dieser Ansatz in der Tat falsch. Diese Änderung ist nur für den übergebenen Zeiger nützlich, und der Zeiger auf dem Baum zeigt immer noch auf den ursprünglichen Knoten, sodass der Baum völlig falsch ist.

                R                           R                        *p|          
          *p |/   \                    *p|/   \                        C      R
             A     B                     C      B                    /   \  /   \
            /               => 希望     /  \         =>  实际        E      A      B 
           C                          E     A
          /                                       
         E  

Daher muss der beim Drehen des Knotens übergebene Zeiger ein Zeiger auf den Baum und kein Hilfszeiger sein.

Sortieren
Vorwort

Bei der Überprüfung der Sortierung stellte ich fest, dass das Verständnis einiger Methoden in der vorherigen Studie nicht ausreichte. Früher dachte ich, dass die Kettenstruktur für die Heap-Sortierung verwendet werden kann. Als ich sie überprüfte, wollte ich feststellen, dass die Suche mit umgekehrter Baumstruktur schwierig schien, und überprüfte sie schließlich. Die ursprüngliche Heap-Sortierung ist für die Kettenstruktur sehr unfreundlich und degeneriert zu (n ^ 2). Die meisten Sortierungen basieren auf der effektiven Methode, wenn auf die Sequenz zufällig zugegriffen werden kann. Der allgemeine (nlogn) Sortieralgorithmus lautet [ Schnellsortierung ], und diese [ Zusammenführung ] scheint in der Kettenstruktur implementiert zu sein, verwendet jedoch im Allgemeinen keine schnelle Sortierung für die verknüpfte Liste. Sie können sich das ansehen . Wenn der Datenspeicher in der verknüpften Liste ausreicht, wird er schneller zusammengeführt oder zuerst in das Array kopiert und dann schneller sortiert. [ Stackoverflow ] Einige Leute haben Vergleiche angestellt. Ich kann mich nicht erinnern, welcher Artikel, aber einer davon ist sehr wichtig. Der Punkt ist, dass bei großen Datenmengen auch die Cache-Trefferquote einen Einfluss hat, sodass Arrays gegenüber verknüpften Listen offensichtlichere Vorteile haben. Daher ist List <T> in einigen Hochsprachen ein Array, und seine Sortiermethode List.Sort () basiert im Allgemeinen auf der Kapazität des Arrays und der Qualität des Teilungspunkts (Einfügen <schnelle Sortierung <Heap-Sortierung gibt nur die Reihenfolge der Auswahl an). ).

Eine Art verknüpfte Liste zusammenführen

Das Folgende ist eine verknüpfte Zusammenführung von Listen, die in der Sprache C implementiert ist

  • Mittelpunktsuche
    PILNode Mid(PILNode h, PILNode t) {
          
          //快慢指针找
      PILNode p1 = h, p2 = h;
      for (; p2 != t && p2->next != t; p1 = p1->next, p2 = p2->next->next) ;
      return p1;
    }
    
  • Liste teilen
    /**
    * 将链表以头尾分割,尾传入null即分割头节点所指链表
    * 链表头也存储数据
    **/
    void LDivide(PILNode start, PILNode end) {
      if (start != nullptr) {
          // if (end == nullptr)
          //     cout << "   <  L : " << start->data << " -   H : " << "end" << ">  " << endl;
          // else
          //     cout << "   <  L : " << start->data << " -   H : " << end->data << ">  " << endl;
    
          PILNode p1, p2;
          p1 = start;
          p2 = Mid(start, end);
          if (p2->next != end) {
              LDivide(p2, end);
              LDivide(p1, p2);
          }
          if (p1 != p2)
              LMerage(p1, p2, end);
      }
    }
    
  • Verknüpfte Liste zusammenführen
    
     ///非递减合并 p1->p2-1 与 p2->p3 两个链表
     ///同样使用n个辅助空间
     ///sup需要外部 声明
     void LMerage(PILNode p1, PILNode p2, PILNode p3) {
          
          
           // cout << p1->data << "  " << p2->data << "  " << (p3 == nullptr ? -1 : p3->data) << endl;
    
      PILNode lh = p1;
      int s, k, k1; //用于记录p2位置 域数组长度
      for (int i = 0; lh != p3; lh = lh->next, i++) {
          
          
          //装填
          if (lh == p2)
             k1 = k = i;
          sup[i] = lh->data;
          s = i;
      }
     
     //以下为书上使用的合并方法
      lh = p1;
      size_t i = 0;
      for (; i < k1 && k <= s;) {
          
          
          int c = i;
          if (sup[i] > sup[k]) {
          
          
              c = k;
              k++;
          } else {
          
          
              i++;
          }
          lh->data = sup[c];
          lh = lh->next;
      }
    
      while (i < k1) {
          
          
          lh->data = sup[i];
          lh = lh->next;
          i++;
      }
    
      while (k <= s) {
          
          
          lh->data = sup[k];
          lh = lh->next;
          k++;
        }
      }
    
  • verwenden
     #include <iostream>
     #include <stdlib.h>
    
     using namespace std;
     int sup[20] = {
          
          0};
     int main() {
          
          
      // MerageSort(table, 10);
      PILNode head = (PILNode)malloc(sizeof(ILNode));
      PILNode node = head, p = nullptr;
      for (size_t i = 1; i < 20; i++) {
          
          
          if (p != nullptr)
              node = p;
          node->data = rand() % 100;
          node->next = (PILNode)malloc(sizeof(ILNode));
          p = node->next;
      }
      node->next = nullptr;
      //最后一个节点一定要指空,mingw里默认不是空指针
      cout << " Origin " <<  endl;
      node = head;
      for (; node != nullptr; node = node->next) {
          
          
          cout << node->data << "  ";
      }
      cout <<  endl;
    
      LDivide(head,nullptr);
    
      cout << " End " << endl;
      node = head;
      for (; node != nullptr; node = node->next) {
          
          
          cout << node->data << "  ";
      }
      cout <<  endl;
    
      return 0;
      }
    
    

Ich denke du magst

Origin blog.csdn.net/q886yes/article/details/109165548
Empfohlen
Rangfolge