一、二叉树部分
1. 基础概念
- 树结构:一种描述 "一对多" 关系的数据结构,由节点和边构成。
- 节点分类
- 根节点:树的起始节点,只有后继,没有前驱。
- 分支节点:既有前驱又有后继,一个树中分支节点最多有一个前驱,但可以有多个后继。
- 叶子节点:只有前驱,没有后继,是树的末端节点。
- 核心术语
- 度:节点的前驱或后继的个数。入度(指向该节点的边数)均为 1,出度(该节点指向其他节点的边数)为后继节点的个数。
- 层:根节点在第 1 层,每向下一层,层数 + 1。
- 高度:该节点到其最远叶子节点的距离。
- 深度:该节点到根节点的节点个数。
- 树的高度:等于树的最大层数,也等于根节点的深度。
2. 二叉树定义与特性
- 定义:每个节点最多有 2 个后继节点(左孩子、右孩子)的树形结构。
- 特殊二叉树
- 满二叉树:所有叶子节点都在同一层,且每个非叶子节点都有两个子节点。
- 完全二叉树:将二叉树所有节点按层序编号后,编号连续且与满二叉树的编号顺序完全对应。
- 关键特性
- 第 k 层最多有 2(k−1) 个节点。
- 前 k 层最多有 2k−1 个节点。
3. 二叉树的遍历
- 深度优先遍历(DFS)
- 前序遍历:根 → 左 → 右
- 中序遍历:左 → 根 → 右
- 后序遍历:左 → 右 → 根
- 广度优先遍历(BFS)
-
层序遍历 :按节点所在的层,从上到下、从左到右依次访问。
cpp#include "btree.h" #include <stdio.h> #include <stdlib.h> #include "linkqueue.h" #include "seqstack.h" TreeNode_t *CreateCompleteBTree(int StartNo, int EndNo) { TreeNode_t *pNewNode = NULL; if (StartNo > EndNo) { return NULL; } pNewNode = malloc(sizeof(TreeNode_t)); if (NULL == pNewNode) { perror("fail to malloc"); return NULL; } pNewNode->No = StartNo; pNewNode->pLeftChild = CreateCompleteBTree(2*StartNo, EndNo); pNewNode->pRightChild = CreateCompleteBTree(2*StartNo+1, EndNo); return pNewNode; } void PreOrderBTree(TreeNode_t *pTmpRoot) { printf("%d(%c) ", pTmpRoot->No, pTmpRoot->Data); if (pTmpRoot->pLeftChild != NULL) PreOrderBTree(pTmpRoot->pLeftChild); if (pTmpRoot->pRightChild != NULL) PreOrderBTree(pTmpRoot->pRightChild); return; } void InOrderBTree(TreeNode_t *pTmpRoot) { if (pTmpRoot->pLeftChild != NULL) InOrderBTree(pTmpRoot->pLeftChild); printf("%d(%c) ", pTmpRoot->No, pTmpRoot->Data); if (pTmpRoot->pRightChild != NULL) InOrderBTree(pTmpRoot->pRightChild); return; } void PostOrderBTree(TreeNode_t *pTmpRoot) { if (pTmpRoot->pLeftChild != NULL) PostOrderBTree(pTmpRoot->pLeftChild); if (pTmpRoot->pRightChild != NULL) PostOrderBTree(pTmpRoot->pRightChild); printf("%d(%c) ", pTmpRoot->No, pTmpRoot->Data); return; } int DestroyBTree(TreeNode_t **ppTmpRoot) { if ((*ppTmpRoot)->pLeftChild != NULL) DestroyBTree(&(*ppTmpRoot)->pLeftChild); if ((*ppTmpRoot)->pRightChild != NULL) DestroyBTree(&(*ppTmpRoot)->pRightChild); free(*ppTmpRoot); *ppTmpRoot = NULL; return 0; } int LayoutOderBTree(TreeNode_t *pTmpRoot) { Node_t *pTmpQueue = NULL; DataType pTmpNode = NULL; if (NULL == pTmpRoot) { return 0; } pTmpQueue = CreateEmptyLinkQueue(); EnterLinkQueue(pTmpQueue, pTmpRoot); while (!IsEmptyLinkQueue(pTmpQueue)) { pTmpNode = QuitLinkQueue(pTmpQueue); printf("%d(%c) ", pTmpNode->No, pTmpNode->Data); if (pTmpNode->pLeftChild != NULL) EnterLinkQueue(pTmpQueue, pTmpNode->pLeftChild); if (pTmpNode->pRightChild != NULL) EnterLinkQueue(pTmpQueue, pTmpNode->pRightChild); } DestroyLinkQueue(&pTmpQueue); return 0; } int GetBTreeHigh(TreeNode_t *pTmpRoot) { int LeftHigh = 0; int RightHigh = 0; if (NULL == pTmpRoot) { return 0; } LeftHigh = GetBTreeHigh(pTmpRoot->pLeftChild); RightHigh = GetBTreeHigh(pTmpRoot->pRightChild); return (LeftHigh > RightHigh ? LeftHigh : RightHigh) + 1; } TreeNode_t *CreateBTree(int No) { TreeNode_t *pNewNode = NULL; char ch = 0; scanf(" %c", &ch); if ('#' == ch) { return NULL; } else { pNewNode = malloc(sizeof(TreeNode_t)); if (NULL == pNewNode) { perror("fail to malloc"); return NULL; } pNewNode->No = No; pNewNode->Data = ch; pNewNode->pLeftChild = CreateBTree(2*No); pNewNode->pRightChild = CreateBTree(2*No+1); } return pNewNode; } void PreOrderBTreeByStack(TreeNode_t *pTmpRoot) { SeqStack_t *pTmpStack = NULL; TreeNode_t *pTmpNode = NULL; pTmpStack = CreateSeqStack(50); pTmpNode = pTmpRoot; while (1) { while (pTmpNode != NULL) { printf("%d(%c) ", pTmpNode->No, pTmpNode->Data); PushSeqStack(pTmpStack, pTmpNode); pTmpNode = pTmpNode->pLeftChild; } if (IsEmptySeqStack(pTmpStack)) { break; } pTmpNode = PopSeqStack(pTmpStack); pTmpNode = pTmpNode->pRightChild; } DestroySeqStack(&pTmpStack); return; } void InOrderBTreeByStack(TreeNode_t *pTmpRoot) { SeqStack_t *pTmpStack = NULL; TreeNode_t *pTmpNode = NULL; pTmpStack = CreateSeqStack(50); pTmpNode = pTmpRoot; while (1) { while (pTmpNode != NULL) { PushSeqStack(pTmpStack, pTmpNode); pTmpNode = pTmpNode->pLeftChild; } if (IsEmptySeqStack(pTmpStack)) { break; } pTmpNode = PopSeqStack(pTmpStack); printf("%d(%c) ", pTmpNode->No, pTmpNode->Data); pTmpNode = pTmpNode->pRightChild; } DestroySeqStack(&pTmpStack); return; } void PostOrderBTreeByStack(TreeNode_t *pTmpRoot) { SeqStack_t *pTmpStack = NULL; TreeNode_t *pTmpNode = NULL; pTmpStack = CreateSeqStack(50); pTmpNode = pTmpRoot; while (1) { while (pTmpNode != NULL) { pTmpNode->Flag = 1; PushSeqStack(pTmpStack, pTmpNode); pTmpNode = pTmpNode->pLeftChild; } if (IsEmptySeqStack(pTmpStack)) { break; } pTmpNode = PopSeqStack(pTmpStack); if (1 == pTmpNode->Flag) { pTmpNode->Flag = 0; PushSeqStack(pTmpStack, pTmpNode); pTmpNode = pTmpNode->pRightChild; } else if (0 == pTmpNode->Flag) { printf("%d(%c) ", pTmpNode->No, pTmpNode->Data); pTmpNode = NULL; } } DestroySeqStack(&pTmpStack); return; }
-
二、哈希表部分
1. 核心思想
哈希表是一种通过哈希函数将数据映射为存储地址(键值)的数据结构,目标是实现 O(1) 时间复杂度的增删改查操作。
2. 哈希冲突
-
定义:多个不同的原始数据,通过哈希函数计算后得到了相同的键值,这种情况称为哈希冲突(哈希冲突)。
-
解决方法(链地址法):当发生哈希冲突时,在同一个键值对应的存储位置上,用链表来存储多个冲突的数据。
cpp#include "hashtable.h" #include <stdio.h> #include <stdlib.h> static Node_t *pHashTable[10]; int InsertHashTable(int TmpData) { int Index = 0; Node_t *pNewNode = NULL; Node_t **ppTmpNode = NULL; Index = TmpData % 10; for (ppTmpNode = &pHashTable[Index]; *ppTmpNode != NULL && TmpData > (*ppTmpNode)->Data;ppTmpNode = &(*ppTmpNode)->pNext); pNewNode = malloc(sizeof(Node_t)); if(NULL == pNewNode) { perror("fail to malloc"); return -1; } pNewNode->Data = TmpData; pNewNode->pNext = *ppTmpNode; *ppTmpNode = pNewNode; return 0; } void ShowHashTable(void) { int i = 0; Node_t *pTmpNode = NULL; for(i = 0; i < 10; i++) { printf("%d:",i); pTmpNode = pHashTable[i]; while(pTmpNode != NULL) { printf("%d ",pTmpNode->Data); pTmpNode = pTmpNode->pNext; } printf("\n"); } return; } int FindHashTable(int TmpData) { int tmp = 0; Node_t *pTmpNode = NULL; tmp = TmpData % 10; pTmpNode = pHashTable[tmp]; while(NULL != pTmpNode) { if(pTmpNode->Data == TmpData) { return 1; } else if(pTmpNode->Data > TmpData) { return 0; } pTmpNode = pTmpNode->pNext; } return 0; } int DestoryHashTable(void) { int i = 0; Node_t *pTmpNode = NULL; Node_t *pFreeNode = NULL; for(i = 0; i < 10; i++) { pTmpNode = pFreeNode = pHashTable[i]; while(NULL != pTmpNode) { pTmpNode = pTmpNode->pNext; free(pFreeNode); pFreeNode = pTmpNode; } pHashTable[i] = NULL; } return 0; }