创建: 2018/04/13

完成: 2018/05/14

 

 ● 类似于链表,但每一个节点指向多个节点。

 ● 非线性数据结构(元素间的顺序不重要), 顺序重要的用链表, 堆, 队列等线性数据结构

树的术语
 根  根节点(没有父节点)
 边  从父节点到子节点的连线 
 叶  不含子节点的节点 
 兄弟  父节点相同的节点 
 祖先, 子孙  能连过去的 
 层次(level)

 该层所有节点的集合

 根为层次0

 深度

 根到该层的层数差

 高度

 从该节点到可到的最下层节点的层数差

 树的高度

 根节点到最深层次的层数差

 节点的大小  算上自己的所有子孙数
 歪树(skew tree)  除了叶(叶没有子节点)以外所有节点只有一个子节点
   
二叉树
 定义

 ● 节点最多只能包含2个子节点的树构造

 ● 可以看做根, 左二叉树, 右二叉树

   
   
   
   
   
二叉树的型
 严密二叉树  子节点数要么0要么2
 完全二叉树  子节点数全是2, 所有叶的高度相同 
 全二叉树  子节点数全是2, 所有叶的高度为h或h-1
   
二叉树的性质
 二叉树构造

 

struct BinaryTreeNode {
    int data;
    struct BinaryTreeNode *left;
    struct BinaryTreeNode *right;
}

 

 二叉树运算

 ● 基本运算

 - 插入元素

 - 删除元素

 - 搜索元素

 - 横断

 ● 辅助运算

 - 求木的大小(元素数量)

 - 求和最大的层次

 - 对两个求点求最近共同祖先

 二叉树应用

 ● 编译器

 ● 数据压缩算法使用的哈夫曼编码(Huffman coding)

 ● 对元素的组合进行搜索, 插入, 删除的二叉排序树(二叉探索树)  O(logn)(平均)

 ● 对元素的组合进行最大值(最小值)搜索, 删除的带优先度队列(PQ)

   
   
   
   
二叉树遍历
 前序遍历(DLR)

 非递归版需要堆, C语言没有堆标准库, 以后有空补上

//------------------------------------------------
//                  前序遍历 DLR
//------------------------------------------------
// 递归版
void preOrder(struct BinaryTreeNode *root) {
    if (root) {
        printf("处理%d\n中", root->data);
        preOrder(root->left);
        preOrder(root->right);
    }
}

 

 

 中序遍历(LDR)

 非递归版需要堆, C语言没有堆标准库, 以后有空补上

//------------------------------------------------
//                  中序遍历 LDR
//------------------------------------------------
// 递归版
void inOrder(struct BinaryTreeNode *root) {
    if (root) {
        inOrder(root->left);
        printf("处理%d\n中", root->data);
        inOrder(root->right);
    }
}

 

 后序遍历 (LRD)

 非递归版需要堆, C语言没有堆标准库, 以后有空补上

 

//------------------------------------------------
//                   后序遍历 LRD
//------------------------------------------------
// 递归版
void postOrder(struct BinaryTreeNode *root) {
    if (root) {
        postOrder(root->left);
        postOrder(root->right);
        printf("处理%d\n中", root->data);
    }
}

 

 层次遍历 

 Queue自己实现去吧

//------------------------------------------------
//                       层次遍历
//------------------------------------------------
// 层次遍历使用的queue
struct S6_Queue {
    int front, rear;
    int capacity;
    int *array;
};
struct S6_Queue *S6CreateQueue() {return NULL;}
int S6IsEmptyQueue(struct S6_Queue *queue) { return rand()%2;}
void S6EnQueue(struct BinaryTreeNode *data, struct S6_Queue *queue) {}
struct BinaryTreeNode *S6DeQueue() { return NULL; }
void S6DeleteQueue(struct S6_Queue *queue) {};
// 层次遍历
void levelOrder(struct BinaryTreeNode *root) {
    struct S6_Queue *queue = S6CreateQueue();
    struct BinaryTreeNode *temp;
    if (root == NULL) {
        return;
    }
    S6EnQueue(root, queue);
    while (!S6IsEmptyQueue(queue)) {
        temp = S6DeQueue(); // 处理当前node
        if (temp->left) {
            S6EnQueue(temp->left, queue);
        }
        if (temp->right) {
            S6EnQueue(temp->right, queue);
        }
    }
    S6DeleteQueue(queue);
}

 

   
   
一般树(N叉树)
 数据结构 

 

// N叉树数据结构
struct TreeNode {
    int data;
    struct TreeNode *firstChild; // 左侧子节点
    struct TreeNode *nextSibling; // 同层次右边一个节点
}

 

 

   
   
   
   
   
线索二叉树遍历
 结构

  左线索指向遍历顺序下前一个, 右线索指向遍历顺序下后一个

struct ThreadedBinaryTreeNode {
    struct ThreadedBinaryTreeNode *left;
    int LTag;
    int data;
    int RTag;
    struct ThreadedBinaryTreeNode *right;
}

 

 分类

 

 前线索二叉树

 只保持前一个的信息

 

 后线索二叉树  只保持后一个的信息
 全线索二叉树, 也就是常说的线索二叉树  保持前后的信息

 

 二叉树与线索二叉树的区别

 

   二叉树  线索二叉树
 LTag == 0  NULL  
 LTag == 1  Left指向左侧子节点   相同,  Left指向左侧子节点
 RTag == 0  NULL  
 RTag == 1  Right指向右侧子节点  相同,  Right指向右侧子节点

 

 中序遍历

 dummy节点:   left | LTag | data | RTag | right

 空树  LTage = 0
 RTag  永远等于1, 指向自身
   
   
   

 

struct ThreadedBinaryTreeNode {
    struct ThreadedBinaryTreeNode *left;
    int LTag; // 0: 线索指针, 1: 子节点指针
    int data;
    int RTag;
    struct ThreadedBinaryTreeNode *right;
};
//------------------------------------------------
//                     中序遍历
//------------------------------------------------
// 搜索中序遍历的下一个节点
struct ThreadedBinaryTreeNode *inOrderSuccessor(struct ThreadedBinaryTreeNode *p) {
    struct ThreadedBinaryTreeNode *position;
    if (p->RTag == 0) { // 右子节点不存在, 返回上层节点
        return p->right;
    } else { // 右侧子节点存在
        position = p->right;
        while (position->LTag == 1) {
            position = position->left;
        }
        return position;
    }
}
// dummy节点: RTag恒为1, right指向自身
// 中序遍历
// 方法1
void inorderTraversal(struct ThreadedBinaryTreeNode *root) { // root是dummy节点
    struct ThreadedBinaryTreeNode *current = inOrderSuccessor(root);
    while (current != root) {
        current = inOrderSuccessor(current);
        printf("data: %d\n", current->data);
    }
}

// 方法2
void inorderTraversalV2(struct ThreadedBinaryTreeNode *root) {
    struct ThreadedBinaryTreeNode *current = root;
    while (1) {
        if (current == root) {
            return;
        }
        current = inOrderSuccessor(current);
        printf("data: %d\n", current->data);
    }
}

 

 

 向线索二叉树插入节点  
   
   
表达式树(expression tree)
 概述   叶节点是被运算值, 分支节点(非终端节点)是运算符
 

 

struct BinaryTreeNode *buildExpressionTree(char postfixExpression[], int size) {
    struct S9Stack *stack = S9CreateStack();
    for (int i = 0; i < size; i++) {
        if (!isOperater(postfixExpression[i])) {
            struct BinaryTreeNode *newNode = (struct BinaryTreeNode *)malloc(sizeof(struct BinaryTreeNode));
            if (!newNode) {
                printf("memory error\n");
                return NULL;
            }
            newNode->data = postfixExpression[i];
            newNode->left = newNode->right = NULL;
            S9Push(stack, newNode);
        } else {
            struct BinaryTreeNode *t2 = S9Pop(stack), *t1 = S9Pop(stack);
            struct BinaryTreeNode *newNode = (struct BinaryTreeNode *)malloc(sizeof(struct BinaryTreeNode));
            if (!newNode) {
                printf("memory error\n");
                return NULL;
            }
            newNode->left = t1;
            newNode->right = t2;
            newNode->data = postfixExpression[i];
            S9Push(stack, newNode);
        }
    }
    return stack;
}

 

 

   
   
   
   
XOR树
   
   
   
   
   
   
二叉搜索树
   BST(Binary Search Tree)
 性质  左子节点小比当前小, 右子节点比当前大
 节点声明 

 

//------------------------------------------------
//                 二叉搜索树节点声明
//------------------------------------------------
// 和普通二叉树没有区别
struct BinarySearchTreeNode {
    int data;
    struct BinarySearchTreeNode *left;
    struct BinarySearchTreeNode *right;
};

 

 运算 

 

 主要运算

 ● 搜索元素/最大元素/最小元素

 ● 插入元素

 ● 删除元素

 辅助元素

 ● 判断是否是二叉探索树

 ● 搜索第n小的元素

 ● 对元素排序

 

 注 

 ● 中序遍历相当于升序排序

 ● 一般处理顺序: 左->根->右

   一般只需要处理根节点

 ● 搜索更简单, 左小右大所以只需考虑半边

 搜索元素 

 

//------------------------------------------------
//                     搜索元素
//------------------------------------------------
// 方法1
struct BinarySearchTreeNode *find(struct BinarySearchTreeNode *root, int data) {
    if (root == NULL) {
        return NULL;
    }
    if (data < root->data) {
        return find(root->left, data);
    } else if (data > root->data) {
        return find(root->right, data);
    } else {
        return root;
    }
}

// 方法2
struct BinarySearchTreeNode *findV2(struct BinarySearchTreeNode *root, int data) {
    while (root) {
        if (data == root->data) {
            return root;
        } else if (data > root->data) {
            root = root->right;
        } else {
            root = root->left;
        }
    }
    return NULL;
}

// 个人方法
struct BinarySearchTreeNode *findV3(struct BinarySearchTreeNode *root, int data) {
    struct BinarySearchTreeNode *current = root;
    if (root == NULL) {
        return NULL;
    }
    while (1) {
        if (data == current->data) {
            return current;
        } else if (data > current->data) {
            current = current->right;
        } else {
            current = current->left;
        }
        if (current == NULL) {
            return NULL;
        }
    }
}

 

 搜索最小元素

 

//------------------------------------------------
//                     搜索最小元素
//------------------------------------------------
// 递归版
struct BinarySearchTreeNode *findMin(struct BinarySearchTreeNode *root) {
    if (root == NULL) {
        return NULL;
    }
    if (root->left) {
        return findMin(root->left);
    } else {
        return root;
    }
}
// 非递归版
struct BinarySearchTreeNode *findMinV2(struct BinarySearchTreeNode *root) {
    if (root == NULL) {
        return NULL;
    }
    while (root->left) {
        root = root->left;
    }
    return root;
}

struct BinarySearchTreeNode *findMinV3(struct BinarySearchTreeNode *root) {
    if (root == NULL) {
        return NULL;
    }
    while (1) {
        if (root->left) {
            root = root->left;
        } else {
            break;
        }
    }
    return root;
}

 

 

 搜素最大元素

 

//------------------------------------------------
//                     搜索最大元素
//------------------------------------------------
// 递归版
struct BinarySearchTreeNode *findMax(struct BinarySearchTreeNode *root) {
    if (root == NULL) {
        return NULL;
    }
    if (root->right == NULL) {
        return root;
    } else {
        return findMax(root->right);
    }
}
// 非递归版
struct BinarySearchTreeNode *findMaxV2(struct BinarySearchTreeNode *root) {
    if (root == NULL) {
        return NULL;
    }
    while (root->right) {
        root = root->right;
    }
    return root;
}

struct BinarySearchTreeNode *findMaxV3(struct BinarySearchTreeNode *root) {
    if (root == NULL) {
        return NULL;
    }
    while (1) {
        if (root->right) {
            root = root->right;
        } else {
            return root;
        }
    }
}

 

 插入元素

 

//------------------------------------------------
//                     插入元素
//------------------------------------------------
// 递归版
struct BinarySearchTreeNode *insert(struct BinarySearchTreeNode *root, int data) {
    if (root == NULL) { // 树不存在则新建树
        root = (struct BinarySearchTreeNode *)malloc(sizeof(struct BinarySearchTreeNode));
        if (root == NULL) { // 生成树失败
            return NULL;
        }
        root->data = data;
        root->left = root->right = NULL;
        return root;
    } else {
        if (data < root->data) {
            root->left = insert(root->left, data);
        } else if (data > root->data) {
            root->right = insert(root->right, data);
        }
    }
    return root;
}

// 非递归版
struct BinarySearchTreeNode *insertV2(struct BinarySearchTreeNode *root, int data) {
    if (root == NULL) {
        root = (struct BinarySearchTreeNode *)malloc(sizeof(struct BinarySearchTreeNode));
        if (root == NULL) {
            return NULL;
        }
        root->data = data;
        root->left = root->right = NULL;
        return root;
    } else {
        struct BinarySearchTreeNode *current = root;
        while (1) {
            if (data > current->data) {
                if (current->right) {
                    current = current->right;
                } else {
                    current->right = (struct BinarySearchTreeNode *)malloc(sizeof(struct BinarySearchTreeNode));
                    current->right->data = data;
                    current->right->left = current->right->right = NULL;
                    return root;
                }
            } else if (data < current->data) {
                if (current->left) {
                    current = current->left;
                } else {
                    current->left = (struct BinarySearchTreeNode *)malloc(sizeof(struct BinarySearchTreeNode));
                    current->left->data = data;
                    current->left->left = current->left->right = NULL;
                    return root;
                }
            }
        }
    }
}

 

 

 删除元素

 

//------------------------------------------------
//                    删除元素
//------------------------------------------------
// 递归版
struct BinarySearchTreeNode *delete(struct BinarySearchTreeNode *root, int data) {
    struct BinarySearchTreeNode *temp;
    if (root == NULL) {
        return NULL;
    }
    if (data < root->data) {
        root->left = delete(root->left, data);
    } else if (data > root->data) {
        root->right = delete(root->right, data);
    } else { // 找到了需要删除的元素
        if (root->left && root->right) { // 子节点有两个
            //可以把用左侧最大或右侧最小替代当前元素
            temp = findMax(root);
            root->data = temp -> data;
            root->left = delete(root->left, root->data);
        } else if (!root->left && !root->right) { // 子节点0个
            temp = root;
            free(temp);
        } else { // 子节点1个
            if (root->left == NULL) {
                root = root->right;
            } else if (root->right == NULL) {
                root = root->left;
            }
            temp = root;
            free(temp);
        }
    }
    return root;
}

 

 

   
AVL树
   
   
   
   
   
   
树的其他形式
   
   
   
   
   
   
posted @ 2018-04-13 22:09  懒虫哥哥  阅读(138)  评论(0)    收藏  举报