ToB企服应用市场:ToB评测及商务社交产业平台

标题: 数据结构- [打印本页]

作者: 欢乐狗    时间: 2024-9-1 13:14
标题: 数据结构-
代码库:dataStructure: 数据结构部门代码

数据结构

数据结构是计算机存储、构造数据的方式,以便高效地访问和修改数据。它主要包括数据的逻辑结构和物理存储结构。
逻辑结构


存储结构


算法


算法是解决特定问题的一系列步骤的聚集。

时间复杂度和空间复杂度



线性表

线性表是最基本的数据结构之一,具有次序性和线性关系。

线性表的进一步细节


代码:
1、动态数组线性表

  1. #include "dynamicArray.h"  
  2. DA * initList(){
  3.      DA* header = (DA *)malloc(sizeof(DA));
  4.      ERROE_CHECK(NULL,header,"malloc");
  5.     header->data = (type *)malloc(sizeof(type));
  6.     ERROE_CHECK(NULL,header->data,"malloc");
  7.     header->index = -1;
  8.     header->data_size = 1;
  9.     printf("11111\n");
  10.     return header;
  11. }
  12. void addList(DA * header,int val){
  13.     if (header->index+1 == header->data_size)
  14.     {
  15.        int new_size = header->data_size*2;
  16.         header->data = (type *)realloc(header->data,new_size*sizeof(type));
  17.         if (NULL == header->data)
  18.         {
  19.             perror("realloc");
  20.             exit(1);
  21.         }
  22.         header->data_size = new_size;
  23.       
  24.     }
  25.      header->data[++header->index] = val;
  26.    
  27. }
  28. void showList(DA *header){
  29.     for (size_t i = 0; i <= header->index; i++)
  30.     {
  31.         printf("%d ",header->data[i]);
  32.     }
  33.     puts("");
  34. }
  35. void delList(DA * header,int index){
  36.     if (header->index+1 <= header->data_size / 2)
  37.     {
  38.        int new_size = header->data_size / 2;
  39.         header->data = (type *)realloc(header->data,new_size*sizeof(type));
  40.         if (NULL == header->data)
  41.         {
  42.             perror("realloc");
  43.             exit(1);
  44.         }
  45.         header->data_size = new_size;   
  46.     }
  47.     if (index <= header->index)
  48.     {
  49.         for (size_t i = index; i < header->index; i++)
  50.         {
  51.             header->data[i] = header->data[i+1];
  52.         }
  53.         header->index--;
  54.     }
  55.    
  56. }
复制代码
 2、平凡数组线性表
  1. #include "seqList.h"
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <43func.h>
  5. LT *createList()
  6. {
  7.     LT *header = (LT *)malloc(sizeof(LT));
  8.     ERROE_CHECK(NULL, header, "malloc");
  9.     header->count = -1;
  10.     return header;
  11. }
  12. bool insertList(LT *header, type data)
  13. {
  14.     if (isFullList(header))
  15.     {
  16.         printf("Full\n");
  17.         exit(1);
  18.     }
  19.     if (header->count < LEN)
  20.     {
  21.         header->count++;
  22.         header->data[header->count] = data;
  23.         return true;
  24.     }
  25.     else
  26.     {
  27.         return false;
  28.     }
  29. }
  30. void showList(LT *header)
  31. {
  32.     if (isEmptyList(header))
  33.     {
  34.         puts("empty!");
  35.         exit(1);
  36.     }
  37.     for (size_t i = 0; i <= header->count; i++)
  38.     {
  39.         printf("%d ", header->data[i]);
  40.     }
  41.     puts("");
  42. }
  43. // full
  44. bool isFullList(LT *header)
  45. {
  46.     return (LEN - 1 == header->count) ? true : false;
  47. }
  48. // empty
  49. bool isEmptyList(LT *header)
  50. {
  51.     return (-1 == header->count) ? true : false;
  52. }
  53. // length
  54. int lengthList(LT *header)
  55. {
  56.     return header ? header->count + 1 : -1;
  57. }
  58. // select
  59. /// @brief  表头,要查找的值
  60. /// @return 索引,
  61. int selectListVal(LT *header, type val)
  62. {
  63.     if (isEmptyList(header))
  64.     {
  65.         puts("empty");
  66.         exit(1);
  67.     }
  68.     for (size_t i = 0; i <= header->count; i++)
  69.     {
  70.         if (val == header->data[i])
  71.         {
  72.             return i;
  73.         }
  74.     }
  75.     return -1;
  76. }
  77. /// @brief  header   valSrc valDest
  78. /// @return void
  79. void changeListVal(LT *header, type valSrc, type valDest)
  80. {
  81.     int ret = selectListVal(header, valSrc);
  82.     while (ret >= 0)
  83.     {
  84.         header->data[ret] = valDest;
  85.         ret = selectListVal(header, valSrc);
  86.     }
  87. }
  88. // del 按值删除,删第一个
  89. /// @brief  header   val
  90. /// @return void
  91. void delListVal(LT *header, type val)
  92. {
  93.     int index = selectListVal(header, val);
  94.     if (index >= 0)
  95.     {
  96.         for (size_t i = index; i < header->count; i++)
  97.         {
  98.             header->data[i] = header->data[i + 1];
  99.         }
  100.         header->count--;
  101.     }
  102. }
  103. // 清空free
  104. /// @brief  header   
  105. /// @return void
  106. void freeList(LT **header){
  107.     free(*header);
  108.     *header = NULL;
  109. }
  110. void init_header(LT *header){
  111.     header->count = -1;
  112. }
复制代码
3、单链表:
约定一:第一个节点不存值

在这种约定下,链表的第一个节点(通常称为哑节点或哨兵节点)不存储实际的数据值,而是仅用作链表的起始点,其next指针指向链表中第一个存储数据的节点。
头插法:

头插法意味着新节点将被插入到链表的头部(即哑节点的后面)。但由于哑节点不存储值,以是实际上新节点成为了链表中第一个存储数据的节点。
// 假设Node结构体已经界说,且链表有一个哑节点head
void insertAtHead(Node **head, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = value;
newNode->next = (*head)->next; // 将新节点的next指向原来的第一个数据节点
(*head)->next = newNode; // 更新哑节点的next为新节点
}
留意:这里head是一个指向头节点的指针的指针,因为我们须要修改头节点(哑节点)内部的next指针。
尾插法:

尾插法则须要遍历链表以找到末了一个存储数据的节点,并将新节点插入到厥后。
// 假设Node结构体已经界说,且链表有一个哑节点head
void insertAtTail(Node **head, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = value;
newNode->next = NULL;
Node *current = *head;
// 遍历链表找到末了一个节点
while (current->next != NULL) {
current = current->next;
}
// 将末了一个节点的next指向新节点
current->next = newNode;
}
约定二:第一个节点存值

在这种约定下,链表的第一个节点就存储了实际的数据值,而且没有哑节点。
头插法:

头插法意味着新节点将被插入到链表的头部,即成为新的第一个节点。
// 假设Node结构体已经界说,且head直接指向链表的第一个数据节点
void insertAtHead(Node **head, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = value;
newNode->next = *head; // 将新节点的next指向原来的头节点
*head = newNode; // 更新头指针为新节点
}
尾插法:

尾插法仍然须要遍历链表以找到末了一个节点,并将新节点插入到厥后。
// 假设Node结构体已经界说,且head直接指向链表的第一个数据节点
void insertAtTail(Node **head, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = value;
newNode->next = NULL;
if (*head == NULL) {
// 如果链表为空,则新节点即为头节点
*head = newNode;
} else {
Node *current = *head;
// 遍历链表找到末了一个节点
while (current->next != NULL) {
current = current->next;
}
// 将末了一个节点的next指向新节点
current->next = newNode;
}
}
单向链表:

单向链表的特点

  1. #include "singleLinkedList.h"
  2. ND *createList()
  3. {
  4.     ND *header = (ND *)malloc(sizeof(ND));
  5.     ERROR_CHECK(NULL, header, "malloc");
  6.     header->next = NULL;
  7.     return header;
  8. }
  9. void insertNodeTail(ND *header, type val)
  10. {
  11.     ND *p = header;
  12.     while (p->next)
  13.     {
  14.         p = p->next;
  15.     };
  16.     ND *new_node = (ND *)malloc(sizeof(ND));
  17.     ERROR_CHECK(NULL, new_node, "mallocTail");
  18.     new_node->data = val;
  19.     new_node->next = NULL;
  20.     p->next = new_node;
  21. }
  22. void insertNodeHead(ND *header, type val)
  23. {
  24.     ND *new_node = (ND *)malloc(sizeof(ND));
  25.     ERROR_CHECK(NULL, new_node, "mallocHeadnewHead");
  26.     new_node->data = val;
  27.     new_node->next = header->next;
  28.     header->next = new_node;
  29. }
  30. void showList(ND *header)
  31. {
  32.     if (NULL == header)
  33.     {
  34.         printf("List is NULL\n");
  35.         exit(1);
  36.     }
  37.     while (header = header->next)
  38.     {
  39.         printf("%d ", header->data);
  40.     }
  41.     puts("");
  42. }
  43. // void showList2(ND header){
  44. //      ND p = header;
  45. //     while (p.next != NULL)
  46. //     {
  47. //         p = *p.next;
  48. //         printf("%d ",p.data);
  49. //     }
  50. //     puts("");
  51. // }
  52. void delNode1(ND *header, int val)
  53. {
  54.     while (header->next)
  55.     {
  56.         if (header->next->data == val)
  57.             break;
  58.         header = header->next;
  59.     }
  60.     if (header->next)
  61.     {
  62.         ND *temp = header->next;
  63.         header->next = temp->next;
  64.         free(temp);
  65.     }
  66. }
  67. void delNode0(ND *header, int val)
  68. {
  69.     ND *pVal = header->next;
  70.     ND *pCur = NULL;
  71.     if (pVal->data == val)
  72.     {
  73.         header->next = pVal->next;
  74.         free(pVal);
  75.         return;
  76.     }
  77.     while ((pVal != NULL) && (pVal->data != val))
  78.     {
  79.         pCur = pVal;
  80.         pVal = pVal->next;
  81.     }
  82.     if (pVal == NULL)
  83.     {
  84.         puts("not found");
  85.     }
  86.     else
  87.     {
  88.         ND *temp = pCur->next;
  89.         pCur->next = pCur->next->next;
  90.         free(temp);
  91.     }
  92.     // return delNode(header,val);
  93. }
  94. int lengthList(ND *header)
  95. {
  96.     int ret = 0;
  97.     while (header = header->next)
  98.     {
  99.         ret++;
  100.     }
  101.     return ret;
  102. }
  103. int isEmptyList(ND *header)
  104. {
  105.     if (NULL == header)
  106.     {
  107.         puts("NULL list");
  108.         exit(1);
  109.     }
  110.     return header->next ? 0 : 1;
  111. }
  112. ND *slectNodeByVal(ND *header, int val)
  113. {
  114.     if (NULL == header)
  115.     {
  116.         puts("NULL list");
  117.         exit(1);
  118.     }
  119.     while (header = header->next)
  120.     {
  121.         if (header->data == val)
  122.         {
  123.             return header;
  124.         }
  125.     }
  126.     return NULL;
  127. }
  128. //init
  129. void initList(ND *header){
  130.     if (NULL == header)
  131.     {
  132.         puts("NULL list");
  133.         return;
  134.     }
  135.     while (header->next)
  136.     {
  137.         ND * temp = header->next;
  138.         header->next = temp->next;
  139.         free(temp);
  140.     }
  141.    
  142. }
  143. //freeList
  144. void freeList(ND **header){
  145.     initList(*header);
  146.     free(*header);
  147.     *header = NULL;
  148. }
复制代码
双向链表:

双向链表的特点
  1. #include "doubleLinkedList.h"
  2. ND *createList()
  3. {
  4.     ND *head = (ND *)malloc(sizeof(head));
  5.     ERROR_CHECK(NULL, head, "malloc");
  6.     head->Precursor_node = NULL;
  7.     head->successor_node = NULL;
  8.     return head;
  9. }
  10. void insertNodeHead(ND *head, int val)
  11. {
  12.     if (NULL == head)
  13.     {
  14.         puts("invalid head NULL");
  15.         exit(1);
  16.     }
  17.     ND *new_node = (ND *)malloc(sizeof(ND));
  18.     ERROR_CHECK(NULL, new_node, "malloc_new_node_head");
  19.     new_node->data = val;
  20.     new_node->Precursor_node = head;
  21.     new_node->successor_node = head->successor_node;
  22.     if (head->successor_node)
  23.     {
  24.         head->successor_node->Precursor_node = new_node;
  25.     }
  26.         head->successor_node = new_node;
  27.    
  28. }
  29. void insertNodeTail(ND *head, int val)
  30. {
  31.     if (NULL == head)
  32.     {
  33.         puts("invalid head NULL");
  34.         exit(1);
  35.     }
  36.     ND *new_node = (ND *)malloc(sizeof(ND));
  37.     ERROR_CHECK(NULL, new_node, "malloc_new_node_tail");
  38.     new_node->data = val;
  39.     while (head->successor_node)
  40.         head = head->successor_node;
  41.     new_node->successor_node = head->successor_node;
  42.     new_node->Precursor_node = head;
  43.     head->successor_node = new_node;
  44. }
  45. void showList(ND *head)
  46. {
  47.     if (NULL == head)
  48.     {
  49.         puts("invalid head NULL");
  50.         exit(1);
  51.     }
  52.     while (head = head->successor_node)
  53.     {
  54.         printf("%d ", head->data);
  55.     }
  56.     puts("");
  57. }
  58. ND *selectVal(ND *head, int val)
  59. {
  60.     if (NULL == head)
  61.     {
  62.         puts("invalid head NULL");
  63.         exit(1);
  64.     }
  65.     while (head = head->successor_node)
  66.     {
  67.         if (head->data == val)
  68.             return head;
  69.     }
  70.     return NULL;
  71. }
  72. void changeVal(ND *head, int srcVal, int destVal)
  73. {
  74.     if (NULL == head)
  75.     {
  76.         puts("invalid head NULL");
  77.         exit(1);
  78.     }
  79.     ND *temp;
  80.     while (temp = selectVal(head, srcVal)){
  81.         if (destVal == temp->data)
  82.         {
  83.             break;
  84.         }
  85.         temp->data = destVal;}
  86. }
  87. void delVal(ND *head, int val)
  88. {
  89.     if (NULL == head)
  90.     {
  91.         puts("invalid head NULL");
  92.         exit(1);
  93.     }
  94.     ND *temp1;
  95.     while (temp1 = selectVal(head, val))
  96.     {
  97.          temp1->Precursor_node->successor_node = temp1->successor_node;
  98.         if (temp1->successor_node != NULL)
  99.         {      
  100.             temp1->successor_node->Precursor_node = temp1->Precursor_node;
  101.         }
  102.       
  103.         free(temp1);
  104.     }
  105. }
  106. int listLen(ND *head)
  107. {
  108.     if (NULL == head)
  109.     {
  110.         puts("invalid head NULL");
  111.         exit(1);
  112.     }
  113.     int ret;
  114.     while (head = head->successor_node)
  115.     {
  116.         ret++;
  117.     }
  118.     return ret;
  119.     //递归求长度
  120.     // if (head->successor_node == NULL)
  121.     // {
  122.     //    return 0;
  123.     // }
  124.     // return 1 + listLen(head->successor_node);
  125. }
  126. int isEmpty(ND *head)
  127. {
  128.     if (NULL == head)
  129.     {
  130.         puts("invalid head NULL");
  131.         exit(1);
  132.     }
  133.     return NULL == head->successor_node ? 0 : 1;
  134. }
  135. void initList0(ND *head)
  136. {
  137.     ND *temp = head->successor_node;
  138.     head->successor_node = NULL;
  139.     while (temp)
  140.     {
  141.         ND *next = temp->successor_node;
  142.         free(temp);
  143.         temp = next;
  144.     }
  145. }
  146. void initList1(ND *head)
  147. {
  148.     while (head->successor_node)
  149.     {
  150.         ND *temp = head->successor_node;
  151.          temp->Precursor_node->successor_node = temp->successor_node;
  152.         if (temp->successor_node != NULL)
  153.         {
  154.             temp->successor_node->Precursor_node = temp->Precursor_node;
  155.         }
  156.         free(temp);
  157.     }
  158. }
  159. void freeList(ND **head)
  160. {
  161.     initList0(*head);
  162.     free(*head);
  163.     *head = NULL;
  164. }
复制代码
约瑟夫环
判断链表是否有环 (快慢指针)
栈;

栈的特点
用线性表都可以实现,但是用次序表更方便

  1. #include "stack.h"  
  2. ST * createStack(){
  3.     ST *stack   = (ST*)malloc(sizeof(ST));
  4.     ERROR_CHECK(NULL,stack,"malloc stack");
  5.     stack->data = (type*)malloc(sizeof(type));  
  6.     if (NULL == stack->data)
  7.     {
  8.         perror("malloc stack->data");
  9.         free (stack);
  10.         exit(1);
  11.     }
  12.     stack->data_size = 1;
  13.     stack->top = -1;
  14.     return stack;
  15. }
  16. void pushStack(ST *stack,type val){
  17.     if (NULL == stack)
  18.     {
  19.         puts("NULL stack");
  20.         exit(1);
  21.     }
  22.     if (stack->top == stack->data_size - 1 )
  23.     {
  24.         int new_size = stack->data_size * 2;
  25.         stack->data = (type*)realloc(stack->data,new_size * sizeof(type));
  26.         ERROR_CHECK(NULL,stack->data,"realloc push");
  27.         stack->data_size = new_size;
  28.     }
  29.    
  30.     stack->data[++stack->top] = val;
  31. }  
  32. type popStack(ST *stack){
  33.      if (NULL == stack)
  34.     {
  35.         puts("NULL stack");
  36.         exit(1);
  37.     }
  38.     if (isEmpty(stack))
  39.     {
  40.          if (stack->top <= stack->data_size/2 -1)
  41.     {
  42.         int new_size = stack->data_size /2;
  43.         stack->data = (type*)realloc(stack->data,new_size * sizeof(type));
  44.         ERROR_CHECK(NULL,stack->data,"realloc pop");
  45.         stack->data_size = new_size;
  46.     }
  47.     return stack->data[stack->top--];
  48.     }
  49.     puts("stack empty!");
  50. }
  51. void clearStack(ST *stack){
  52.     stack->top = -1;
  53.     stack->data_size = 1;
  54. }
  55. int isEmpty(ST* stack){
  56.         if (NULL == stack)
  57.     {
  58.         puts("NULL stack");
  59.         exit(1);
  60.     }
  61.     return stack->top == -1 ? 0 : 1;
  62. }
复制代码
队列:

队列的特点

首尾相连(取余,约定末了一个不存值)
  1. #include "queue.h"
  2. QL *createQueueList()
  3. {
  4.     QL *queue = (QL *)malloc(sizeof(QL));
  5.     ERROR_CHECK(NULL, queue, "malloc create");
  6.     queue->front = queue->rear = 0;
  7. }
  8. int isEmpty(QL *queue)
  9. {
  10.     if (NULL == queue)
  11.     {
  12.         puts("NULL queue");
  13.         exit(1);
  14.     }
  15.     return queue->rear == queue->front ? 1 : 0;
  16. }
  17. int isFull(QL *queue)
  18. {
  19.     if (NULL == queue)
  20.     {
  21.         puts("NULL queue");
  22.         exit(1);
  23.     }
  24.     return queue->rear == queue->front -1  ? 1 : 0;
  25. }
  26. void enQueue(QL *queue, type val)
  27. {
  28.     if (isFull(queue))
  29.     {
  30.         puts("full queue");
  31.         exit(1);
  32.     }
  33.     queue->data[queue->rear] = val;
  34.     queue->rear = (queue->rear + 1) % LEN;
  35. }
  36. type deQueue(QL *queue)
  37. {
  38.     if (isEmpty(queue))
  39.     {
  40.         puts("empty queue");
  41.         exit(1);
  42.     }
  43.     type temp = queue->data[queue->front];
  44.     queue->front = (queue->front + 1) % LEN;
  45.     return temp;
  46. }
  47. void showQueue(QL *queue)
  48. {
  49.     for (size_t i = 0; i < LEN; i++)
  50.     {
  51.         printf("%c ", queue->data[i]);
  52.     }
  53.     puts("");
  54. }
  55. void clearQueue(QL *queue)
  56. {
  57.     queue->front = queue->rear = 0;
  58. }
  59. void freeQueue(QL **queue)
  60. {
  61.     free(*queue);
  62.     *queue = NULL;
  63. }
复制代码
链表实现队列:
    
  1. #include "queueLink.h"
  2. QUEUE *createQueueLink()
  3. {
  4.     QUEUE *qlink = (QUEUE *)malloc(sizeof(QUEUE));
  5.     ERROR_CHECK(NULL, qlink, "malloc");
  6.     qlink->front = NULL;
  7.     qlink->rear = NULL;
  8.     return qlink;
  9. }
  10. void enQueue(QUEUE *qlink, type val)
  11. {
  12.     if (NULL == qlink)
  13.     {
  14.         puts("NULL param");
  15.         exit(1);
  16.     }
  17.     QL *new_node = (QL *)malloc(sizeof(QL));
  18.     ERROR_CHECK(NULL, new_node, "malloc new_node");
  19.     new_node->data = val;
  20.     new_node->next = NULL;
  21.     if (qlink->rear == NULL)
  22.     {
  23.         qlink->front = new_node;
  24.     }
  25.     else
  26.     {
  27.         qlink->rear->next = new_node;
  28.     }
  29.     qlink->rear = new_node;
  30. }
  31. type deQueue(QUEUE *qlink)
  32. {
  33.     if (NULL == qlink)
  34.     {
  35.         puts("NULL param");
  36.         exit(1);
  37.     }
  38.     if (isEmpty(qlink))
  39.     {
  40.         puts("empty");
  41.         exit(1);
  42.     }
  43.     QL *temp = qlink->front;
  44.     qlink->front = temp->next;
  45.     int ret = temp->data;
  46.     free(temp);
  47.     if (qlink->front == NULL)
  48.     {
  49.         qlink->rear = NULL;
  50.     }
  51.     temp = NULL;
  52.     return ret;
  53. }
  54. int isEmpty(QUEUE *qlink)
  55. {
  56.     if (NULL == qlink)
  57.     {
  58.         puts("NULL param");
  59.         exit(1);
  60.     }
  61.     return qlink->rear == NULL ? 1 : 0;
  62. }
  63. void freeQueue(QUEUE **qlink)
  64. {
  65.     if (NULL == qlink)
  66.     {
  67.         puts("NULL param");
  68.         exit(1);
  69.     }
  70.     init(*qlink);
  71.     free(*qlink);
  72.     *qlink = NULL;
  73. }
  74. void init(QUEUE *qlink)
  75. {
  76.     if (NULL == qlink)
  77.     {
  78.         puts("NULL param");
  79.         exit(1);
  80.     }
  81.     while (qlink->front)
  82.     {
  83.         QL *temp = qlink->front;
  84.         qlink->front = qlink->front->next;
  85.         free(temp);
  86.     }
  87.     qlink->rear = NULL;
  88. }
复制代码
树:



     二叉树 

 

 



遍历:


从左往右连,按次序,
1绿色连起来是先序
2蓝色是中序;
3红色是后序;

 通过中序+(先序或后序)来确定二叉树:


            
 


 

1. 前序遍历(Pre-order Traversal)


 

2. 中序遍历(In-order Traversal)


 

3. 后序遍历(Post-order Traversal)



4. 层序遍历(Level-order Traversal)



  1. typedef struct QueueNode
  2. {
  3.     TREE *treeNode;
  4.     struct QueueNode *next;
  5. } QueueNode;
  6. typedef struct
  7. {
  8.     QueueNode *front;
  9.     QueueNode *rear;
  10. } Queue;
  11. void enqueue(Queue *q, TREE *node)
  12. {
  13.     QueueNode *newNode = (QueueNode *)malloc(sizeof(QueueNode));
  14.     newNode->treeNode = node;
  15.     newNode->next = NULL;
  16.     if (q->rear)
  17.     {
  18.         q->rear->next = newNode;
  19.     }
  20.     q->rear = newNode;
  21.     if (!q->front)
  22.     {
  23.         q->front = newNode;
  24.     }
  25. }
  26. TREE *dequeue(Queue *q)
  27. {
  28.     if (!q->front)
  29.         return NULL;
  30.     QueueNode *temp = q->front;
  31.     TREE *node = temp->treeNode;
  32.     q->front = q->front->next;
  33.     if (!q->front)
  34.     {
  35.         q->rear = NULL;
  36.     }
  37.     free(temp);
  38.     return node;
  39. }
  40. void level_showQueue(TREE *root)
  41. {
  42.     if (NULL == root)
  43.     {
  44.         return;
  45.     }
  46.     Queue q = {NULL, NULL};
  47.     enqueue(&q, root);
  48.     while (q.front)
  49.     {
  50.         TREE *node = dequeue(&q);
  51.         OUT(node->data);
  52.         if (node->lchild)
  53.         {
  54.             enqueue(&q, node->lchild);
  55.         }
  56.         if (node->rchild)
  57.         {
  58.             enqueue(&q, node->rchild);
  59.         }
  60.     }
  61. }
  62. void level_showArry(TREE *root)
  63. {
  64.     if (NULL == root)
  65.     {
  66.         return;
  67.     }
  68.     TREE *queue[MAX_QUEUE_SIZE];
  69.     int front = 0, rear = 0;
  70.     queue[rear++] = root; // 入队根节点
  71.     while (front < rear)
  72.     {
  73.         TREE *node = queue[front++]; // 出队
  74.         OUT(node->data);
  75.         if (node->lchild)
  76.         {
  77.             if (rear < MAX_QUEUE_SIZE)
  78.             {
  79.                 queue[rear++] = node->lchild; // 入队左子节点
  80.             }
  81.         }
  82.         if (node->rchild)
  83.         {
  84.             if (rear < MAX_QUEUE_SIZE)
  85.             {
  86.                 queue[rear++] = node->rchild; // 入队右子节点
  87.             }
  88.         }
  89.     }
  90. }
复制代码
 哈夫曼树:

        哈夫曼编码:
   哈夫曼树(Huffman Tree),又称最优二叉树,是一种用于数据压缩的广泛使用的数据结构。它由美国数学家David A. Huffman在1952年提出,主要用于数据压缩中的变长编码表(Huffman Coding)。哈夫曼树是一种特别的二叉树结构,此中权重越大的节点离根节点越近,而权重越小的节点则离根节点越远。
  哈夫曼树的特点:

    哈夫曼编码(Huffman Coding):

  哈夫曼编码是一种使用可变长度编码表对源符号(如文件中的一个字符)进行编码的方法,编码的长度依赖于符号出现的概率。详细步骤如下:
    哈夫曼编码的优点:

  
  

图:


 



   在图论中,图是由极点(或称为节点)和连接这些极点的边组成的结构。
  有向图

  有向图(Directed Graph)是图中的边具有方向性的图。在有向图中,每条边都从一个极点指向另一个极点,表示一种单向关系。例如,在社交网络中,用户A关注用户B,但用户B不一定关注用户A,这种关系就可以用有向图来表示。
  无向图

  无向图(Undirected Graph)是图中的边没有方向性的图。在无向图中,如果两个极点之间存在边,则它们是相互连接的,表示一种双向关系。例如,在朋友关系中,如果A是B的朋友,那么B也是A的朋友,这种关系可以用无向图来表示。
  极点的度(有向和无向)

  
  路径

  路径(Path)是图中一系列极点和连接这些极点的边,使得从第一个极点开始,沿着边可以到达末了一个极点,且每条边只被使用一次(除非路径答应环)。
  连通性

  
  图的基本运算

  图的基本运算包括但不限于:
  
  极点

  极点(Vertex)是图的基本组成元素之一,用于表示图中的实体或对象。
  图的存储

  图的存储方式主要有两种:
    有向图的毗邻矩阵

  对于有向图,毗邻矩阵的大小由极点个数决定。假设图中有n个极点,则毗邻矩阵是一个n×n的矩阵。矩阵中的元素(i, j)表示极点i到极点j是否存在边(或边的权重)。如果存在边,则值为1(或边的权重);如果不存在边,则值为0。
  

     

A
B
C
D
E
A
0
0
1
1
0
B
0
0
0
0
0
C
0
1
0
0
0
D
0
1
0
0
1
E
0
0
0
0
0
   
   无向图
   
   

   
   
   
   毗邻表:

      

A
->C->D->NULL
B
->NULL
C
->B->NULL
D
->B->E
E
->NULL
   
   
    图的遍历

    是图论中的一个基本问题,它指的是从图中的某一极点出发,沿着边访问图中的每一个极点,且每个极点仅被访问一次。图的遍历算法主要有两种:深度优先搜索(DFS, Depth-First Search)和广度优先搜索(BFS, Breadth-First Search)。这两种算法既可以用于无向图,也可以用于有向图。
    深度优先搜索(DFS)

    深度优先搜索是一种用于遍历或搜索树或图的算法。该算法沿着树的深度遍历树的节点,尽可能深地搜索树的分支。当节点v的地点边都已被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这个过程不停进行到已发现从源节点可达的全部节点为止。
    DFS算法的基本步骤
        随机一个极点,随机一条路径,碰到NULL再回到上一个极点,如果有路径就走,没有继续回退到上一个极点,如果找不完,就换个极点继续):
   

    广度优先搜索(BFS)

    广度优先搜索是一种对图进行遍历的算法。它从根节点开始,沿着树的宽度遍历树的节点。如果全部节点均被访问,则算法中止。
    BFS算法的基本步骤
       
    随机一个极点,展开路径,继续展开路径的路径
   

    留意事项

   
   
    Dijkstra算法概述

    Dijkstra算法从一个源点开始,渐渐找到该源点到其他全部极点的最短路径。算法使用了一个优先队列(通常是最小堆)来存储待处理的极点,以及一个间隔数组来记载从源点到图中每个极点的当前最短估计间隔。
    使用Dijkstra算法求解固定两点间最短路径

       

   
      
算法(查找、排序):

   算法(  Algorithm  )是一个有穷规则(或语句、指令)的有序聚集。     算法的特性     (  1  )   有穷性   ——   算法执行的步骤(或规则)是有限的;     (  2  )   确定性   ——   每个计算步骤无二义性;     (  3  )   可行性   ——   每个计算步骤可以或许在有限的时间内完成;     (  4  )   输入   ——   算法有零个或多个外部输入;     (  5  )   输出   ——   算法有一个或多个输出。     时间复杂度的概念先容 :     问题的规模 :输入数据量的大小,用  n  来表示。     算法的时间复杂度 :算法消耗时间,它是问题规模的函数   T  (  n  )  。   //log n < n <nlog n< n2     算法的空间复杂度 :须要的额外空间量   查找:

   1. 次序查找(Sequential Search)

  次序查找是最基本的查找技能。它的工作原理是遍历整个列表,逐个检查每个元素,直到找到所需的元素或搜索完备个列表。次序查找的时间复杂度是O(n),此中n是列表中元素的数目。这种方法不须要列表是有序的,但它在处理大数据集时可能非常慢。
  2. 二分查找(Binary Search)

  二分查找是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中央元素开始,如果中央元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中央元素,则在数组大于或小于中央元素的那一半中查找,而且跟开始一样从中央元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法的时间复杂度是O(log n),此中n是数组中的元素数目。
  1. int searchVal(int *data, int val, int low, int high) {  
  2.     if (low > high) {  
  3.         return -1; // 如果没有找到,返回-1  
  4.     }  
  5.   
  6.     int mid = low + (high - low) / 2; // 防止溢出  
  7.   
  8.     if (data[mid] == val) {  
  9.         return mid; // 如果中间元素就是目标值,直接返回  
  10.     }  
  11.   
  12.     // 判断哪边是有序的  
  13.     if (data[low] <= data[mid]) { // 左边有序  
  14.         if (val >= data[low] && val < data[mid]) {  
  15.             // 如果目标值在左半边有序区间内,则继续在左半边查找  
  16.             return searchVal(data, val, low, mid - 1);  
  17.         } else {  
  18.             // 否则,在右半边查找  
  19.             return searchVal(data, val, mid + 1, high);  
  20.         }  
  21.     } else { // 右边有序  
  22.         if (val > data[mid] && val <= data[high]) {  
  23.             // 如果目标值在右半边有序区间内,则继续在右半边查找  
  24.             return searchVal(data, val, mid + 1, high);  
  25.         } else {  
  26.             // 否则,在左半边查找  
  27.             return searchVal(data, val, low, mid - 1);  
  28.         }  
  29.     }  
  30. }
复制代码
3. 哈希查找(Hashing)

  哈希查找是一种通过计算索引位置来快速访问数据项的技能。它通过哈希函数将键(key)映射到表中一个位置来访问记载,以加速查找的速度。抱负情况下,哈希函数应该淘汰辩论,即不同的键映射到同一个索引位置的情况。然而,哈希辩论是不可制止的,因此须要一种策略来解决辩论,比如链地址法(即使用链表解决辩论)、开放定址法(即探求下一个空闲位置)等。
  

  二叉搜索树(Binary Search Tree, BST)

  二叉搜索树是一种特别的二叉树结构,它满足以下性质:
  
  二叉搜索树的中序遍历(左-根-右)会按照键的升序访问全部节点。在最坏的情况下(树退化为链表),二叉搜索树的操纵(如查找、插入、删除)的时间复杂度会退化到O(n)。但在平均情况下,这些操纵的时间复杂度接近O(log n)。
  

  AVL树

  AVL树是一种自平衡的二叉搜索树。在AVL树中,任何节点的两个子树的高度最大差异为1,这种高度的平衡保证了AVL树的搜索、插入和删除操纵都能保持较高的服从,即在最坏情况下这些操纵的时间复杂度也能维持在O(log n)。当AVL树发生不平衡时,它会通过旋转操纵来重新到达平衡。这些旋转操纵包括单旋转(左旋转和右旋转)和双旋转(左右旋转和右左旋转)。
  

  
排序

   1. 冒泡排序(Bubble Sort)

  冒泡排序是一种简朴的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果它们的次序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再须要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小(或越大)的元素会经由交换慢慢“浮”到数列的顶端。
  1.     for (size_t i = 0; i < len - 1; i++)
  2.     {
  3.         for (size_t j = i + 1; j < len; j++)
  4.         {
  5.             if (data[i] > data[j])
  6.             {
  7.                 int temp = data[i];
  8.                 data[i] = data[j];
  9.                 data[j] = temp;
  10.             }
  11.         }
  12.     }
复制代码
  1. void bubbleSort(int *data, int len)
  2. {
  3.     for (size_t i = 0; i < len - 1; i++)
  4.     {
  5.         for (size_t j = 0; j < len - i - 1; j++)
  6.         {
  7.             if (data[j] > data[j + 1])
  8.             {
  9.                 int temp = data[j];
  10.                 data[j] = data[j + 1];
  11.                 data[j + 1] = temp;
  12.             }
  13.         }
  14.     }
  15. }
复制代码
2. 选择排序(Selection Sort)

  选择排序是一种简朴直观的排序算法。它的工作原理是:起首在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续探求最小(大)元素,然后放到已排序序列的末端。以此类推,直到全部元素均排序完毕。
  1. void chooseSort(int *data,int len){
  2.     for (size_t i = 0; i < len -1; i++)
  3.     {
  4.         int minIndex = i;
  5.         for (size_t j = i+1; j < len; j++)
  6.         {
  7.             if ( data[minIndex] > data[j])
  8.             {
  9.                 minIndex= j;
  10.             }
  11.             
  12.         }
  13.         int temp = data[minIndex];
  14.         data[minIndex]  = data[i];
  15.         data[i] = temp;      
  16.     }
  17.    
  18. }
复制代码
3. 插入排序(Insertion Sort)

  插入排序的算法思想是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。在实际应用中,通常使用in-place排序(即只需用到O(1)的额外空间的排序)。
  插入排序可以和折半查找联合淘汰插入的时间复杂度;
  1. void insertSort2(int *data,int len){
  2.     int i ,j,key;
  3.     for (size_t i = 1; i < len; i++)
  4.     {
  5.         key = data[i];
  6.         j = i -1;
  7.         while (j>=0 && data[j] >key)
  8.         {
  9.             data[j+1] = data[j];
  10.             j--;
  11.         }
  12.         data[j+1] = key;
  13.         
  14.     }
  15.    
  16. }
复制代码
4. 快速排序(Quick Sort)

  快速排序使用分治法(Divide and Conquer)策略来把一个序列分为两个子序列。步骤为:
  
  1. void quickSort(int arr[], int low, int high)
  2. {
  3.     if (low < high)
  4.     {
  5.         // pi 是分区后基准值的正确位置
  6.         int pi = partition(arr, low, high);
  7.         // 分别对基准值左右两边的子数组进行快速排序
  8.         quickSort(arr, low, pi - 1);
  9.         quickSort(arr, pi + 1, high);
  10.     }
  11. }
  12. int partition(int arr[], int low, int high)
  13. {
  14.     int pivot = arr[high];
  15.     while (low < high)
  16.     {
  17.         while (arr[low] <= pivot && low <high)
  18.         {
  19.             low++;
  20.         }
  21.         if (low <high)
  22.         {
  23.             arr[high--] = arr[low];
  24.         }
  25.         while (arr[high] >= pivot && low <high)
  26.         {
  27.             high--;
  28.         }
  29.           if (low <high)
  30.         {
  31.             arr[low++] = arr[high];
  32.         }  
  33.     }
  34.     arr[low] = pivot;
  35.     return low;
  36. }
复制代码
快速排序的平均时间复杂度为O(n log n),但在最坏情况下(如输入数组已经有序)时间复杂度会退化到O(n^2)。通过随机选择基准值可以淘汰最坏情况的发生。
       in_place    //   原地排序        界说:   "In-place"    意味着算法在排序过程中不须要额外的存储空间,除了可能须要少量的辅助变量        外,全部的排序操纵都在原始的数据结构上进行。        优点:节省内存空间,特别适合处理大规模数据集。        缺点:由于直接在原始数据上操纵,可能会对数据造成破坏,须要谨慎处理。        有些   "in-place"   排序算法可能不是稳定的排序算法(即相等的元素之间的相对次序可能改变)。        out_place    //   非原地排序        界说:   "Out-of-place"    意味着算法在排序过程中须要额外的存储空间来生存数据的临时状态。   优点:通常更容易实现,且有些算法可以保持稳定性。        缺点:须要额外的存储空间,这在处理大规模数据集时可能会成为一个问题       。      

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4