分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
- 作者:邹祁峰
- 邮箱:Qifeng.zou.job@hotmail.com
- 博客:http://blog.youkuaiyun.com/qifengzou
- 日期:2013.12.13 17:00
- 转载请注明来自"祁峰"的优快云博客
1 引言
大家可以通过以下图形对时间变化的趋势有一个大概的印象:
图1 变化趋势对比图
由图的变化趋势可知,当N逐渐增大时,时间相差的倍数越来越大[如:当N=2^32时,y = N/2 = 2^31,而y = log2@N = 2^5, 其性能差异可想而知]。因此,为了提高对二叉排序树的操作性能,很有必要在构造二叉树排序树时,进行平衡化处理,将其调整为一棵平衡二叉树。
2 平衡过程
平衡二叉树[Balanced Binary Tree]又称为AVL树,是二叉排序树的一种形式,其特点是:树中每个结点的左、右子树的深度之差的绝对值不超过1,即:|Hl - Hr| <= 1。
结点的平衡因子[Balance factor]:该结点的左子树深度Hl减去该结点的右子树的深度Hr。平衡二叉树所有结点的平衡因子的值只能为-1,0,1。
在构建平衡二叉树的过程中,插入一个新结点后,可能会造成平衡二叉树失去平衡。失去平衡后进行调整的规律可归纳为以下4种情况:[注:以下操作是平衡处理的核心,请认真分析总结]
2.1 LL型


2.2 LR型



2.3 RR型


2.4 RL型



3 操作接口
3.1 结构定义
/* 结点结构 */typedef struct _avl_node_t{ struct _avl_node_t *parent; /* 父结点 */ struct _avl_node_t *lchild; /* 左孩子 */ struct _avl_node_t *rchild; /* 右孩子 */ int key; /* 结点值: 如果想构造成通用的平衡二叉树,在此可使用void *类型 */ int bf; /* 平衡因子 */}avl_node_t;
/* 树结构 */typedef struct{ node_t *root; /* 根结点 */ /* 如果想构造成通用的平衡二叉树,可以在此增加一个比较函数指针,其类型为: typedef int (*cmp)(const void *s1, const void *s2) 1. 当s1 < s2时: 返回值小于0 2. 当s1 == s2时: 返回值等于0 3. 当s1 > s2时: 返回值大于0 */}avl_tree_t;
typedef enum{ AVL_SUCCESS /* 成功 */ , AVL_FAILED = ~0x7FFFFFFF /* 失败 */ , AVL_NODE_EXIST /* 结点存在 */ , AVL_ERR_STACK /* 栈异常 */}AVL_RET_e;
/* 平衡因子 */#define AVL_RH (-1) /* 右高 */#deifne AVL_EH (0) /* 等高 */#define AVL_LH (1) /* 左高 */#define AVL_MAX_DEPTH (512) /* AVL栈的最大深度 *//* BOOL类型 */typedef int bool;#define true (1)#define false (0)/* 设置node的左孩子结点 */#define avl_set_lchild(node, lc) \{ \ (node)->lchild = (lc); \ if (NULL != (lc)) { \ (lc)->parent = (node); \ } \}/* 设置node的右孩子结点 */#define avl_set_rchild(node, rc) \{ \ (node)->rchild = (rc); \ if (NULL != (rc)) { \ (rc)->parent = (node); \ } \}/* 替换父结点的孩子结点 */#define avl_instead_child(tree, parent, old, _new) \{ \ if (NULL == parent) { \ (tree)->root = (_new); \ if (NULL != (_new)) { \ (_new)->parent = NULL; \ } \ } \ else if (parent->lchild == old) { \ avl_set_lchild(parent, _new); \ } \ else if (parent->rchild == old) { \ avl_set_rchild(parent, _new); \ } \}
3.2 创建对象
增加创建平衡二叉树对象的接口可以有效的屏蔽平衡二叉树的成员变量的定义,使用者不必关心哪些参数需要设置或修改,只需知道参数接口便可正确使用。其代码实现如下:/****************************************************************************** **函数名称: avl_creat **功 能: 创建平衡二叉树对象(对外接口) **输入参数: ** tree: 平衡二叉树 **输出参数: NONE **返 回: AVL_SUCCESS:成功 AVL_FAILED:失败 **实现描述: **注意事项: **作 者: # Qifeng.zou # 2013.12.19 # ******************************************************************************/int avl_creat(avl_tree_t **tree){ *tree = (avl_tree_t *)calloc(1, sizeof(avl_tree_t)); if (NULL == *tree) { return AVL_FAILED; } (*tree)->root = NULL; return AVL_SUCCESS;}
3.3 插入结点
/****************************************************************************** **函数名称: avl_insert **功 能: 插入新结点(对外接口) **输入参数: ** tree: 平衡二叉树 ** node: 新结点 **输出参数: NONE **返 回: AVL_SUCCESS:成功 AVL_NODE_EXIST:已存在 AVL_FAILED:失败 **实现描述: ** 1. 当树的根结点为空时,则直接创建根结点,并赋值 ** 2. 当树的根结点不为空时,则调用_avl_insert()进行处理 **注意事项: **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/int avl_insert(avl_tree_t *tree, int key){ bool taller = false; avl_node_t *node = tree->root; /* 如果为空树,则创建第一个结点 */ if (NULL == node) { node = (node_t *)calloc(1, sizeof(node_t)); if (NULL == node) { return AVL_FAILED; } node->parent = NULL; node->rchild = NULL; node->lchild = NULL; node->bf = AVL_EH; node->key = key; tree->root = node; return AVL_SUCCESS; } return _avl_insert(tree, node, key, &taller); /* 调用插入结点的接口 */}
/****************************************************************************** **函数名称: _avl_insert **功 能: 插入新结点(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 需在该结点的子树上插入key ** key: 需被插入的key **输出参数: ** taller: 是否增高 **返 回: AVL_SUCCESS:成功 AVL_NODE_EXIST:已存在 AVL_FAILED:失败 **实现描述: ** 1. 当结点关键字等于key值时,结点已存在 ** 2. 当结点关键字小于key值时,插入右子树 ** 3. 当结点关键字大于key值时,插入左子树 **注意事项: **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/static int _avl_insert(avl_tree_t *tree, avl_node_t *node, int key, bool *taller){ if (key == node->key) { /* 结点已存在 */ *taller = false; return AVL_NODE_EXIST; } else if (key > node->key) { /* 插入右子树 */ return avl_insert_right(tree, node, key, taller); } /* 插入左子树 */ return avl_insert_left(tree, node, key, taller);}
/****************************************************************************** **函数名称: avl_insert_right **功 能: 在node的右子树中插入新结点(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 需在该结点的子树上插入key ** key: 需被插入的key **输出参数: ** taller: 是否增高 **返 回: AVL_SUCCESS:成功 AVL_NODE_EXIST:已存在 AVL_FAILED:失败 **实现描述: **注意事项: **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/static int avl_insert_right(avl_tree_t *tree, avl_node_t *node, int key, bool *taller){ int ret = -1; avl_node_t *add = NULL; if (NULL == node->rchild) { add = (node_t *)calloc(1, sizeof(node_t)); if (NULL == add) { *taller = false; return AVL_FAILED; } add->lchild = NULL; add->rchild = NULL; add->parent = node; add->key = key; add->bf = AVL_EH; node->rchild = add; *taller = true; /* node的高度增加了 */ } else { ret = _avl_insert(tree, node->rchild, key, taller); if ((AVL_SUCCESS != ret)) { return ret; } } if (false == *taller) { return AVL_SUCCESS; } /* 右增高: 进行平衡化处理 */ switch (node->bf) { case AVL_LH: /* 左高: 右子树增高 不会导致失衡 */ { node->bf = AVL_EH; *taller = false; return AVL_SUCCESS; } case AVL_EH: /* 等高: 右子树增高 不会导致失衡 */ { node->bf = AVL_RH; *taller = true; return AVL_SUCCESS; } case AVL_RH: /* 右高: 右子树增高 导致失衡 */ { avl_right_balance(tree, node); *taller = false; return AVL_SUCCESS; } } return AVL_FAILED;}
/****************************************************************************** **函数名称: avl_insert_left **功 能: 在node的左子树中插入新结点(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 需在该结点的子树上插入key ** key: 需被插入的key **输出参数: ** taller: 是否增高 **返 回: AVL_SUCCESS:成功 AVL_NODE_EXIST:已存在 AVL_FAILED:失败 **实现描述: **注意事项: **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/static int avl_insert_left(avl_tree_t *tree, avl_node_t *node, int key, bool *taller){ int ret = -1; avl_node_t *add = NULL; if (NULL == node->lchild) { add = (node_t *)calloc(1, sizeof(node_t)); if (NULL == add) { *taller = false; return AVL_FAILED; } add->lchild = NULL; add->rchild = NULL; add->parent = node; add->key = key; add->bf = AVL_EH; node->lchild = add; *taller = true; /* node的高度增加了 */ } else { ret = _avl_insert(tree, node->lchild, key, taller); if (AVL_SUCCESS != ret) { return ret; } } if (false == *taller) { return AVL_SUCCESS; } /* 左增高: 进行平衡化处理 */ switch(node->bf) { case AVL_RH: /* 右高: 左子树增高 不会导致失衡 */ { node->bf = AVL_EH; *taller = false; return AVL_SUCCESS; } case AVL_EH: /* 等高: 左子树增高 不会导致失衡 */ { node->bf = AVL_LH; *taller = true; return AVL_SUCCESS; } case AVL_LH: /* 左高: 左子树增高 导致失衡 */ { avl_left_balance(tree, node); *taller = false; return AVL_SUCCESS; } } return AVL_FAILED;}
/****************************************************************************** **函数名称: avl_rr_balance **功 能: RR型平衡化处理 - 向左旋转(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 右边失去平衡的结点 **输出参数: NONE **返 回: AVL_SUCCESS:成功 AVL_FAILED:失败 **实现描述: RR型 ** A C ** / \ / \ ** AL C -> A CR ** / \ / \ \ ** CL CR AL CL X ** \ ** X ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点C的平衡因子为-1时,可判断为RR型。 **注意事项: ** 1. 图(1)中A表示右边失衡的结点 图(2)表示平衡处理的结果 **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/static int avl_rr_balance(avl_tree_t *tree, avl_node_t *node){ avl_node_t *rchild = node->rchild, *parent = node->parent; avl_set_rchild(node, rchild->lchild); node->bf = AVL_EH; avl_set_lchild(rchild, node); rchild->bf = AVL_EH; avl_instead_child(tree, parent, node, rchild); return AVL_SUCCESS;}
/****************************************************************************** **函数名称: avl_rl_balance **功 能: RL型平衡化处理 - 先向右旋转 再向左旋转(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 右边失去平衡的结点 **输出参数: NONE **返 回: AVL_SUCCESS:成功 AVL_FAILED:失败 **实现描述: ** 场景1: RL型 ** A B ** / \ / \ ** AL C -> A C ** / \ / \ / \ ** B CR AL BL BR CR ** / \ ** BL BR ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点C的平衡因子为1时,可判断为RL型。 ** 虽然此时结点B的平衡因子的值可能为:-1, 0, 1. ** 但旋转处理的方式是一致的,只是旋转之后的平衡因子不一致. **注意事项: ** 1. 图(1)中A表示右边失衡的结点 图(2)表示平衡处理的结果 **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/int avl_rl_balance(avl_tree_t *tree, avl_node_t *node){ avl_node_t *rchild = node->rchild, *parent = node->parent, *rlchild = NULL; rlchild = rchild->lchild; switch(rlchild->bf) { case AVL_LH: { node->bf = AVL_EH; rchild->bf = AVL_RH; rlchild->bf = AVL_EH; break; } case AVL_EH: { node->bf = AVL_EH; rchild->bf = AVL_EH; rlchild->bf = AVL_EH; break; } case AVL_RH: { node->bf = AVL_LH; rchild->bf = AVL_EH; rlchild->bf = AVL_EH; break; } } avl_set_lchild(rchild, rlchild->rchild); avl_set_rchild(rlchild, rchild); avl_set_rchild(node, rlchild->lchild); avl_set_lchild(rlchild, node); avl_instead_child(tree, parent, node, rlchild); return AVL_SUCCESS;}
/****************************************************************************** **函数名称: avl_right_balance **功 能: 对右边失去平衡的结点进行平衡化处理(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 右边失去平衡的结点 **输出参数: NONE **返 回: AVL_SUCCESS:成功 AVL_FAILED:失败 **实现描述: ** 场景1: RR型 ** A C ** / \ / \ ** AL C -> A CR ** / \ / \ \ ** CL CR AL CL X ** \ ** X ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点C的平衡因子为-1时,可判断为RR型。 ** 场景2: RL型 ** A B ** / \ / \ ** AL C -> A C ** / \ / \ / \ ** B CR AL BL BR CR ** / \ ** BL BR ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点C的平衡因子为1时,可判断为RL型。 ** 虽然此时结点B的平衡因子的值可能为:-1, 0, 1. ** 但旋转处理的方式是一致的,只是旋转之后的平衡因子不一致. **注意事项: ** 1. 图(1)中A表示右边失衡的结点 图(2)表示平衡处理的结果 **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/static int avl_right_balance(avl_tree_t *tree, avl_node_t *node){ avl_node_t *rchild = node->rchild; switch(rchild->bf) { case AVL_RH: /* 场景1: RR型 - 向左旋转 */ { return avl_rr_balance(tree, node); } case AVL_LH: /* 场景2: RL型 - 先向右旋转 再向左旋转 */ { return avl_rl_balance(tree, node); } } return AVL_FAILED;}
/****************************************************************************** **函数名称: avl_ll_balance **功 能: LL型平衡化处理 - 向右旋转(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 左边失去平衡的结点 **输出参数: NONE **返 回: AVL_SUCCESS:成功 AVL_FAILED:失败 **实现描述: ** 场景1: LL型 ** A B ** / \ / \ ** B C -> BL A ** / \ / / \ ** BL BR X BR C ** / ** X ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点B的平衡因子为1时,可判断为LL型。 **注意事项: ** 1. 图(1)中A表示左边失衡的结点 图(2)表示平衡处理的结果 **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/int avl_ll_balance(avl_tree_t *tree, avl_node_t *node){ avl_node_t *lchild = node->lchild, *parent = node->parent; avl_set_lchild(node, lchild->rchild); node->bf = AVL_EH; avl_set_rchild(lchild, node); lchild->bf = AVL_EH; avl_instead_child(tree, parent, node, lchild); return AVL_SUCCESS;}
/****************************************************************************** **函数名称: avl_lr_balance **功 能: LR型平衡化处理 - 先左旋转 再向右旋转(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 左边失去平衡的结点 **输出参数: NONE **返 回: AVL_SUCCESS:成功 AVL_FAILED:失败 **实现描述: ** 场景1: LL型 ** A B ** / \ / \ ** B C -> BL A ** / \ / / \ ** BL BR X BR C ** / ** X ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点B的平衡因子为1时,可判断为LL型。 ** 场景2: LR型 ** A C ** / \ / \ ** B AR -> B A ** / \ / \ / \ ** BL C BL CL CR AR ** / \ ** CL CR ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点B的平衡因子为-1时,可判断为LR型。 ** 虽然此时结点C的平衡因子的值可能为:-1, 0, 1. ** 但旋转处理的方式是一致的,只是旋转之后的平衡因子不一致. **注意事项: ** 1. 图(1)中A表示左边失衡的结点 图(2)表示平衡处理的结果 **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/int avl_lr_balance(avl_tree_t *tree, avl_node_t *node){ avl_node_t *lchild = node->lchild, *parent = node->parent, *lrchild = NULL; lrchild = lchild->rchild; switch(lrchild->bf) { case AVL_LH: { node->bf = AVL_RH; lchild->bf = AVL_EH; lrchild->bf = AVL_EH; break; } case AVL_EH: { node->bf = AVL_EH; lchild->bf = AVL_EH; lrchild->bf = AVL_EH; break; } case AVL_RH: { node->bf = AVL_EH; lchild->bf = AVL_LH; lrchild->bf = AVL_EH; break; } } avl_set_rchild(lchild, lrchild->lchild); avl_set_lchild(lrchild, lchild); avl_set_lchild(node, lrchild->rchild); avl_set_rchild(lrchild, node); avl_instead_child(tree, parent, node, lrchild); return AVL_SUCCESS;}
/****************************************************************************** **函数名称: avl_left_balance **功 能: 对左边失去平衡的结点进行平衡化处理(内部接口) **输入参数: ** tree: 平衡二叉树 ** node: 左边失去平衡的结点 **输出参数: NONE **返 回: AVL_SUCCESS:成功 AVL_FAILED:失败 **实现描述: ** 场景1: LL型 ** A B ** / \ / \ ** B C -> BL A ** / \ / / \ ** BL BR X BR C ** / ** X ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点B的平衡因子为1时,可判断为LL型。 ** 场景2: LR型 ** A C ** / \ / \ ** B AR -> B A ** / \ / \ / \ ** BL C BL CL CR AR ** / \ ** CL CR ** (1) (2) ** 说明: 结点A是失衡结点,此时当结点B的平衡因子为-1时,可判断为LR型。 ** 虽然此时结点C的平衡因子的值可能为:-1, 0, 1. ** 但旋转处理的方式是一致的,只是旋转之后的平衡因子不一致. **注意事项: ** 1. 图(1)中A表示左边失衡的结点 图(2)表示平衡处理的结果 **作 者: # Qifeng.zou # 2013.12.13 # ******************************************************************************/int avl_left_balance(avl_tree_t *tree, avl_node_t *node){ avl_node_t *lchild = node->lchild; switch(lchild->bf) { case AVL_LH: /* 场景1: LL型 */ { return avl_ll_balance(tree, node); } case AVL_RH: /* 场景2: LR型 */ { return avl_lr_balance(tree, node); } } return AVL_FAILED;}
3.4 查找结点
- /******************************************************************************
- **函数名称: avl_search
- **功 能: 查找指定的结点
- **输入参数:
- ** tree: 平衡二叉树
- ** key: 需查找的关键字
- **输出参数: NONE
- **返 回: 结点地址
- **实现描述:
- **注意事项:
- **作 者: # Qifeng.zou # 2013.12.12 #
- ******************************************************************************/
- avl_node_t *avl_search(avl_tree_t *tree, int key)
- {
- avl_node_t *node = tree->root;
- while (NULL != node) {
- if (node->key == key) {
- return node;
- }
- else if (node->key < key) {
- node = node->lc;
- }
- else{
- node = node->rc;
- }
- }
- return NULL; /* Didn't find */
- }
3.5 销毁对象
/****************************************************************************** **函数名称: avl_destory **功 能: 销毁平衡二叉树(对外接口) **输入参数: ** tree: 平衡二叉树 **输出参数: NONE **返 回: VOID **实现描述: **注意事项: **作 者: # Qifeng.zou # 2013.12.15 # ******************************************************************************/int avl_destory(avl_tree_t **tree){ if (NULL != tree->root) { _avl_destory(tree->root); tree->root = NULL; } free(*tree), *tree=NULL; return 0;}
/****************************************************************************** **函数名称: _avl_destory **功 能: 销毁AVL树(内部接口) **输入参数: ** node: 需要被销毁的结点 **输出参数: NONE **返 回: VOID **实现描述: **注意事项: **作 者: # Qifeng.zou # 2013.12.15 # ******************************************************************************/void _avl_destory(avl_node_t *node){ if (NULL != node->lchild) { _val_destory(node->lchild); } if (NULL != node->rchild) { _val_destory(node->rchild); } free(node);}
3.6 调试程序
#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <memory.h>#define INPUT_MAX_LEN (256)int main(void){ int ret = 0; avl_tree_t *tree = NULL; avl_node_t *node = NULL; char input[INPUT_MAX_LEN] = {0}; ret = avl_creat(&tree); if (ret < 0) { avl_destory(&tree); return -1; } while (1) { memset(input, 0, sizeof(input)); scanf(" %s", input); if(!strcasecmp(input, "quit") || !strcasecmp(input, "exit") || !strcasecmp(input, "q")) { fprintf(stderr, "Quit!\n"); break; } node = val_search(&tree, atoi(input)); if (NULL != node) { fprintf(stderr, "parent:[%p] lchild:[%p] rchild:[%p] key:[%d] bf:[%d]\n", node->parent, node->lchild, node->rchild, node->key, node->bf); } ret = val_insert(&tree, atoi(input)); if (AVL_FAILED == ret) { fprintf(stderr, "Insert failed!\n"); continue; } else if (AVL_NODE_EXIST == ret) { fprintf(stderr, "Node exist!\n"); continue; } fprintf(stderr, "Insert success!\n"); avl_print(tree); } avl_destory(&tree); return 0;}
代码19 测试程序
随机输入10万条数据,其打印的平衡二叉树的结构如下图所示:
图12 测试结果
给我老师的人工智能教程打call!http://blog.youkuaiyun.com/jiangjunshow

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
- 全新的界面设计 ,将会带来全新的写作体验;
- 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
- 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
- 全新的 KaTeX数学公式 语法;
- 增加了支持甘特图的mermaid语法1 功能;
- 增加了 多屏幕编辑 Markdown文章功能;
- 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
- 增加了 检查列表 功能。
功能快捷键
撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
合理的创建标题,有助于目录的生成
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC
语法后生成一个完美的目录。
如何改变文本的样式
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
链接: link.
图片:
带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block var foo = 'bar';
生成一个适合你的列表
- 项目
- 项目
- 项目
- 项目
- 项目1
- 项目2
- 项目3
- 计划任务
- 完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' | ‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" | “Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash | – is en-dash, — is em-dash |
创建一个自定义列表
-
Markdown
- Text-to- HTML conversion tool Authors
- John
- Luke
如何创建一个注脚
一个具有注脚的文本。2
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
section 现有任务
已完成 :done, des1, 2014-01-06,2014-01-08
进行中 :active, des2, 2014-01-09, 3d
计划一 : des3, after des2, 5d
计划二 : des4, after des3, 5d
- 关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
注脚的解释 ↩︎