Advertisement
Guest User

Untitled

a guest
Nov 24th, 2018
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.03 KB | None | 0 0
  1. /*
  2.  Программу продготовил: Буренков Игорь (М8О-206Б-17)
  3.  
  4.  Вариант: АВЛ-дерево
  5.  
  6.  Коды ошибок:
  7.  
  8.  1** - процесс ввода
  9.  2** - процесс сотрировки
  10.  3** - процесс вывода
  11.  
  12.  *42 - Ошибка выделения памяти
  13.  *43 - Ошибка перевыделения памяти
  14.  *50 - Ошибка ввода
  15.  
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <limits.h> // Для контроля вылетов за границы
  20. #include <math.h>   // Для округления
  21. #include <string.h>
  22. #include <stdbool.h>
  23.  
  24.  
  25. ////////////////////////////////////////////////
  26. // НАСТРОЙКИ
  27. ////////////////////////////////////////////////
  28. unsigned short int StringLength = 256; // Длина строки
  29. unsigned short start_init = 4;        // Кол-во инициируемых элементов по умолчанию
  30. float step_init = 1.5;                // Кол-во эл-ов добавляемых в дин. массив за раз
  31.  
  32.  
  33.  // Структуры
  34. struct incmd {
  35.     char cmdindex;                      // Сама комманда
  36.     char *cmdword;                      // Текстовый параметр
  37.     unsigned long long int *cmdint;     // Числовой параметр
  38. };
  39.  
  40. struct avlleaf { // структура для представления узлов дерева
  41.     char key[256];                                // Ключ
  42.     unsigned long long int llupar;                // Числовой параметр
  43.     long long int height;                         // Высота
  44.     struct avlleaf* left;                        // Левый ребенок
  45.     struct avlleaf* right;                       // Правый ребенок
  46. };
  47.  
  48. // Основные Функции (сигнатуры)
  49. char InputFiller(struct incmd**); //Функция для заполнения массива
  50. char TreeShell(struct incmd**);   //Функция для выполнения комманд
  51.  
  52. ////////////////////////////////////////////
  53. //     ФУНКЦИИ РАБОТЫ С АВЛ - ДЕРЕВОМ     //
  54. ////////////////////////////////////////////
  55.  
  56. // Освобождение памяти
  57. void MakeEmpty(struct avlleaf* tree){
  58.  if(tree == NULL) return;
  59.  MakeEmpty(tree->left);
  60.  MakeEmpty(tree->right);
  61.  free(tree);
  62. }
  63.  
  64. // Вычисление высоты
  65. long long int Height(struct avlleaf* tree){
  66.  if (tree == NULL) {
  67.      return -1;
  68.  }else {
  69.      return tree->height;
  70.  }
  71. }
  72.  
  73. // Вычисление максимального элемента
  74. long long int MaxLL(long long int a, long long int b){
  75.  if (a > b) {
  76.      return a;
  77.  } else {
  78.      return b;
  79.  }
  80. }
  81.  
  82. // Small Right Rotation
  83. struct avlleaf* SRR(struct avlleaf* tree) {
  84.  struct avlleaf* tmp;
  85.  tmp = tree->left;
  86.  tree->left = tmp->right;
  87.  tmp->right = tree;
  88.  tree->height = MaxLL(Height(tree->left), Height(tree->right))+1;
  89.  tmp->height =  MaxLL(Height(tmp->left), tree->height)+1;
  90.  return tmp;
  91. }
  92.  
  93. // Small Left Rotation
  94. struct avlleaf* SLR(struct avlleaf* tree){
  95.  struct avlleaf* tmp;
  96.  tmp = tree->right;
  97.  tree->right = tmp->left;
  98.  tmp->left = tree;
  99.  tree->height = MaxLL(Height(tree->left), Height(tree->right))+1;
  100.  tmp->height =  MaxLL(Height(tree->right), tree->height)+1 ;
  101.  return tmp;
  102. }
  103.  
  104. // Full Left Rotation
  105. struct avlleaf* FLR(struct avlleaf* tree){
  106.  tree->right = SRR(tree->right);
  107.  return SLR(tree);
  108. }
  109.  
  110. // Full Metal Alchemist
  111. struct avlleaf* FRR(struct avlleaf* tree){
  112.  tree->left = SLR(tree->left);
  113.  return SRR(tree);
  114. }
  115.  
  116. // Добавление листа
  117. struct avlleaf* InsertLeaf(struct avlleaf* tree, char key[256], unsigned long long int llupar){
  118.   unsigned short int i;
  119.     if (tree == NULL) {
  120.        tree         = malloc(sizeof(struct avlleaf));
  121.        tree->llupar = llupar;
  122.        tree->height = 0;
  123.        tree->left   = NULL;
  124.        tree->right  = NULL;
  125.        for (i = 0; i < 256; i++) {
  126.         tree->key[i]   = key[i];
  127.        }
  128.     } else
  129.     if (strcmp(key, tree->key) < 0) {
  130.        tree->left = InsertLeaf(tree->left, key,  llupar);
  131.        if ((Height(tree->left)) - (Height(tree->right)) == 2){
  132.            if (strcmp(key, tree->left->key) < 0) tree = SRR(tree);
  133.            else tree = FRR(tree);
  134.        }
  135.     } else
  136.     if (strcmp(key, tree->key) > 0) {
  137.        tree->right = InsertLeaf(tree->right, key, llupar);
  138.        if ((Height(tree->right)) - (Height(tree->left)) == 2){
  139.            if (strcmp(key, tree->right->key) > 0) tree = SLR(tree);
  140.            else tree = FLR(tree);
  141.        }
  142.     }
  143.     tree->height = MaxLL(Height(tree->left), Height(tree->right))+1;
  144.     return tree;
  145. }
  146.  
  147. // Поиск минимального листа
  148. struct avlleaf* FindMinL(struct avlleaf* tree){
  149.  if(tree == NULL) return NULL;
  150.  else if(tree->left == NULL) return tree;
  151.  else return FindMinL(tree->left);
  152. }
  153.  
  154. // Поиск максимального листа
  155. struct avlleaf* FindMaxL(struct avlleaf* tree) {
  156.  if(tree == NULL) return NULL;
  157.  else if(tree->right == NULL) return tree;
  158.  else return FindMaxL(tree->right);
  159. }
  160.  
  161. // Удаление листа из дерева
  162. struct avlleaf* DeleteLeaf(struct avlleaf* tree, char key[256]){
  163.   struct avlleaf* temp;
  164.   unsigned short int i;
  165.  
  166.   // Нет совпадений
  167.   if (tree == NULL) return NULL;
  168.  
  169.   // Поиск элемента
  170.   if (strcmp(key, tree->key) < 0) tree->left = DeleteLeaf(tree->left, key);
  171.   else if (strcmp(key, tree->key) > 0) tree->right = DeleteLeaf(tree->right, key);
  172.  
  173.   // Иначе элемент найден - обрабатываем случаи
  174.   // Многодетный элемент
  175.   else if((tree->left != NULL) && (tree->right != NULL)){
  176.     temp = FindMinL(tree->right);
  177.     tree->llupar = temp->llupar;
  178.     for (i = 0; i < 256; i++) {
  179.         tree->key[i]   = temp->key[i];
  180.     }
  181.     tree->right = DeleteLeaf(tree->right, tree->key);
  182.   }
  183.   // Один ребенок (2й - нулловый)
  184.   else {
  185.     temp = tree;
  186.     if(tree->left == NULL)    tree = tree->right;
  187.     else if(tree->right == NULL) tree = tree->left;
  188.     free(temp);
  189.   }
  190.  
  191.   // Если tree стул нуловым - выходим (все ок)
  192.   if(tree == NULL) return tree;
  193.  
  194.   // Иначе...
  195.   tree->height = MaxLL(Height(tree->left), Height(tree->right))+1;
  196.  
  197.   // Проверка на нарушение баланса
  198.   // Если удалили левый узел
  199.   if(Height(tree->left) - Height(tree->right) == 2){
  200.             if(Height(tree->left->left) - Height(tree->left->right) == 1)
  201.                 return SLR(tree);
  202.             else
  203.                 return FLR(tree);
  204.   }
  205.   // Если удалили правый узел
  206.   else if(Height(tree->right) - Height(tree->left) == 2){
  207.             if(Height(tree->right->right) - Height(tree->right->left) == 1)
  208.                 return SRR(tree);
  209.             else
  210.                 return FRR(tree);
  211.   }
  212.  
  213.   // Итог
  214.   return tree;
  215. }
  216.  
  217. // Получить баланс
  218. int GetBalance(struct avlleaf* tree){
  219.         if (tree == NULL) return 0;
  220.         else return Height(tree->left) - Height(tree->right);
  221. }
  222.  
  223. // Печать дерева
  224. void PrintMe(struct avlleaf* tree, unsigned long long int lvl){
  225.   unsigned long long int i;
  226.   if(tree == NULL) return;
  227.   PrintMe(tree->left, lvl+1);
  228.   for (i = 0; i < lvl; i++) {
  229.     printf("\t");
  230.   }
  231.   printf("%s", tree->key ); printf("\n");
  232.   PrintMe(tree->right, lvl+1);
  233. }
  234.  
  235. ////////////////////////////////////////////
  236. //         Основной "движок"              //
  237. ////////////////////////////////////////////
  238. int main()
  239. {
  240.     // Создадим массив ввода
  241.     struct incmd *incmd_dynmass;  // Дин. массив структур
  242.     unsigned short int log_error; // Код ошибки [см. в начале]
  243.  
  244.     // Считываем ввод комманд
  245.     log_error = InputFiller(&incmd_dynmass);
  246.     if (log_error != 0){
  247.       return 100 + log_error;
  248.     }
  249.  
  250.     //Выполняем комманд
  251.     log_error = TreeShell(&incmd_dynmass);
  252.     if (log_error != 0){
  253.       return 100 + log_error;
  254.     }
  255.  
  256.     // ОТЛАДКА
  257.     system("pause");
  258.     return 0;
  259. }
  260.  
  261.  
  262. // Функция ввода комманд
  263. char InputFiller(struct incmd **incmd_dynmass) {
  264.  
  265.     // Переменные
  266.     unsigned long long int initcount = 0; // На сколько элементов выделен массив
  267.     char tmpchar;                         // Переменная для ввода первого параметра сообщения
  268.     unsigned short int ticker;                          // Для цикла for
  269.  
  270.    // Инициализация структуры
  271.     *incmd_dynmass = malloc(start_init * sizeof**incmd_dynmass);
  272.     // Обработка ошибки памяти
  273.     if (*incmd_dynmass == NULL) {
  274.        return 42;
  275.     }
  276.     (*incmd_dynmass)[0].cmdint = malloc(sizeof(unsigned long long int));
  277.     // Обработка ошибки памяти
  278.     if ((*incmd_dynmass)[0].cmdint == NULL) {
  279.        return 42;
  280.     }
  281.     (*incmd_dynmass)[0].cmdint[0] = 0; //Обнуляем количество элементов
  282.     initcount = start_init;
  283.  
  284.   // Непосредственное считывание данных
  285.    while ((scanf("%c", &tmpchar) >= 1)){
  286.      if (tmpchar == '*') break;
  287.      // Если кол-во свободных ячеек закончилось
  288.      if (initcount == ((*incmd_dynmass)[0].cmdint[0])+1) {
  289.        if (initcount*step_init <= ULLONG_MAX) {
  290.          initcount=floor(initcount*step_init);
  291.          *incmd_dynmass = realloc(*incmd_dynmass, initcount * sizeof **incmd_dynmass);
  292.          if (*incmd_dynmass == NULL) { // Ошибка перевыделения памяти
  293.            return 43;
  294.          }
  295.        }
  296.      }
  297.  
  298.      // Непосредственное добавление комманды
  299.      switch (tmpchar){
  300.       case '+':
  301.       // Добавление элемента (1-WORD-ULL)
  302.         ((*incmd_dynmass)[0].cmdint)[0]++; // Увеличиваем кол-во элементов
  303.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdindex = 1;  // Указываем операцию
  304.  
  305.         // Выделение памяти
  306.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword = malloc(StringLength*sizeof(char));
  307.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdint =  malloc(sizeof(unsigned long long int));
  308.         if (((*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword == NULL)||(*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdint == NULL) {
  309.            return 42;  // Ошибка памяти
  310.         }
  311.  
  312.         // Считывание 2го параметра (WORD)
  313.         if (scanf("%s", (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword) < 1) {
  314.           return 50;  // Ошибка ввода
  315.         }
  316.  
  317.         // Считывание 3го параметра (ULL)
  318.         if (scanf("%llu", &((*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdint[0])) < 1) {
  319.           return 50;  // Ошибка ввода
  320.         }
  321.  
  322.         break;
  323.  
  324.       case '-':
  325.       // Добавление элемента (2-WORD)
  326.         ((*incmd_dynmass)[0].cmdint)[0]++; // Увеличиваем кол-во элементов
  327.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdindex = 2;  // Указываем операцию
  328.  
  329.         // Выделение памяти
  330.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword = malloc(StringLength*sizeof(char));
  331.         if ((*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword == NULL) {
  332.            return 42;  // Ошибка памяти
  333.         }
  334.  
  335.         // Считывание 2го параметра (WORD)
  336.         if (scanf("%s", (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword) < 1) {
  337.           return 50;  // Ошибка ввода
  338.         }
  339.  
  340.         break;
  341.  
  342.       case '!':
  343.       // Добавление элементов (3-WORD) или (4-WORD)
  344.         ((*incmd_dynmass)[0].cmdint)[0]++; // Увеличиваем кол-во элементов
  345.  
  346.          // Выделение памяти
  347.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword = malloc(StringLength*sizeof(char));
  348.         if ((*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword == NULL) {
  349.            return 42;  // Ошибка памяти
  350.         }
  351.  
  352.         // Выбор операции
  353.         while ((tmpchar != 'S') && (tmpchar != 's')  && (tmpchar != 'L')  && (tmpchar != 'l')) scanf("%c", &tmpchar);
  354.         if ((tmpchar == 'S')||(tmpchar == 's')) {
  355.           (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdindex = 3;  // Указываем операцию
  356.         } else
  357.         if ((tmpchar == 'L')||(tmpchar == 'l')) {
  358.           (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdindex = 4;  // Указываем операцию
  359.         }
  360.         scanf("%s", (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword); // Сбрасываем до сл. параметра
  361.  
  362.         // Считывание 2го параметра (WORD)
  363.         if (scanf("%s", (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword) < 1) {
  364.           return 50;  // Ошибка ввода
  365.         }
  366.  
  367.         break;
  368.  
  369.       default:
  370.       // Добавление элементов (5-WORD)
  371.  
  372.         ((*incmd_dynmass)[0].cmdint)[0]++; // Увеличиваем кол-во элементов
  373.  
  374.         // Выделение памяти
  375.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword = malloc(StringLength*sizeof(char));
  376.         if ((*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword == NULL) {
  377.            return 42;  // Ошибка памяти
  378.         }
  379.  
  380.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdindex = 5;  // Указываем операцию
  381.         if (scanf("%s", (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword) < 1) {
  382.           return 50;  // Ошибка ввода
  383.         }
  384.  
  385.         // Восстановление первого элемента
  386.         for (ticker = 0; ticker < StringLength; ticker++) {
  387.           (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword[StringLength-ticker]=
  388.             (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword[StringLength-ticker-1];
  389.         }
  390.         (*incmd_dynmass)[((*incmd_dynmass)[0].cmdint)[0]].cmdword[0] = tmpchar;
  391.  
  392.        break;
  393.      }
  394.  
  395.      while (getchar() != '\n');
  396.  
  397.  
  398.    }
  399.  
  400.    // ОТЛАДКА
  401.    /*
  402.    for (initcount = 1; initcount <= ((*incmd_dynmass)[0].cmdint)[0]; initcount++){
  403.     printf("\n");
  404.     printf("%i", (*incmd_dynmass)[initcount].cmdindex);
  405.     printf("\n");
  406.    }
  407.  
  408.     for (initcount = 1; initcount <= ((*incmd_dynmass)[0].cmdint)[0]; initcount++){
  409.     printf("\n");
  410.     printf("%s", (*incmd_dynmass)[initcount].cmdword);
  411.     printf("\n");
  412.    }
  413.  
  414.    for (initcount = 1; initcount <= ((*incmd_dynmass)[0].cmdint)[0]; initcount++){
  415.     printf("\n");
  416.     if ((*incmd_dynmass)[initcount].cmdint != NULL) {
  417.      printf("%llu", (*incmd_dynmass)[initcount].cmdint[0]);
  418.     }
  419.     printf("\n");
  420.    }
  421.    */
  422.  
  423.  return 0;
  424. }
  425.  
  426.  
  427. char TreeShell(struct incmd **incmd_dynmass) {
  428.  
  429.  // Переменные
  430.  unsigned long long int tmp1_ull, tmp2_ull; // Временные переменные
  431.  char tmpkey[256];
  432.  struct avlleaf *tree = NULL;
  433.  
  434.  
  435.  //Цикл прхода по коммандам
  436.  for (tmp1_ull = 1; tmp1_ull <= ((*incmd_dynmass)[0].cmdint)[0]; tmp1_ull++) {
  437.    //Проходимся по коммандам
  438.     switch ((*incmd_dynmass)[tmp1_ull].cmdindex) {
  439.      case 1:
  440.  
  441.      // Ввод ключа
  442.       for (tmp2_ull = 0; tmp2_ull < StringLength; tmp2_ull++) {
  443.         tmpkey[tmp2_ull] = ((*incmd_dynmass)[tmp1_ull].cmdword[tmp2_ull]);
  444.       }
  445.  
  446.       // Создаем ключ
  447.       tree = InsertLeaf(tree, tmpkey, (*incmd_dynmass)[tmp1_ull].cmdint[0]);
  448.       printf("%s", tree->key);
  449.       printf("\n");
  450.     }
  451.  }
  452.  //PrintMe(tree, 0);
  453.  return 0;
  454. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement