二叉树各种遍历功能的实现(c/c++)_实现二叉树各种遍历算法-程序员宅基地

技术标签: 算法  c++  c语言  数据结构  

目录

一、预备定义

1.自定义数据结构

2.关于栈和队列的自定义函数

栈:

队列:

二、根据完整先序序列,递归创建二叉树(二叉链表存储结构)

三、各种遍历

1.递归方式先序遍历

2.递归方式中序遍历

3.递归方式后序遍历

4.非递归方式前序遍历

5.非递归方式中序遍历

6.非递归方式后序遍历

7.层次遍历

8.递归销毁二叉树

四、功能菜单和主函数


一、预备定义

1.自定义数据结构

二叉树结点、循环顺序队列、数据栈结点、数据栈、指针栈结点,指针栈。

#define _CRT_SECURE_NO_WARNINGS  //去警告提示
#include <stdio.h>
#include <stdlib.h>

#define QUEUE_MAX_LENGTH 20  //最多存19个元素

// 二叉树结点的定义
typedef struct _BiNode
{
    char data;
    struct _BiNode* lchild;
    struct _BiNode* rchild;
}BiNode, * BiTree;        

// 固定长度的循序顺序队列结构体
typedef struct
{
    BiTree data[QUEUE_MAX_LENGTH];
    int front;  //指向队头元素的前一个元素
    int rear;  //指向队尾元素
} SeqQueue;


// 数据栈结点结构体  (非递归后序遍历时使用)
typedef struct DataNode
{
    char data;  // 数据域为char类型
    struct DataNode* next;
} DataStackNode;

// 数据栈结构体
typedef struct
{
    DataStackNode* top;  // 指向数据栈结点
} DataLinkedStack;


// 指针栈结点结构体
typedef struct PtrNode
{
    BiTree data;  // 数据域为BiTree类型
    struct PtrNode* next;
} PtrStackNode;

// 指针栈结构体
typedef struct
{
    PtrStackNode* top;  // 指向指针栈结点
} PtrLinkedStack;


2.关于栈和队列的自定义函数

初始化数据栈、进数据栈、出数据栈、判断数据栈是否为空。

初始化指针栈、进指针栈、出指针栈、判断指针栈是否为空、获取指针栈栈顶。

初始化队列、判断队列是否为空、判断队列是否为满、获取当前队列中有多少个元素、进队、出队、读取队头和队尾。

栈:

// 数据栈初始化为空栈
void initDataStack(DataLinkedStack& stack)
{
    stack.top = NULL;
}

/* 进栈一个元素 */
void pushDataStack(DataLinkedStack& stack, char e)
{
    DataStackNode* p;

    // 开辟空间,构造结点
    p = (DataStackNode*)malloc(sizeof(DataStackNode));
    p->data = e;
    p->next = NULL;

    // 入栈
    p->next = stack.top;
    stack.top = p;
}


/* 出栈一个元素 */
int popFromDataStack(DataLinkedStack& S, char& e)
{
    DataStackNode* p;  //出栈不需要为其开辟空间

    if (NULL != S.top)
    {
        p = S.top;
        S.top = p->next;

        e = p->data;
        free(p);

        return 1;        // 出栈成功
    }
    else
        return 0;        // 栈为空,出栈失败
}

/* 判断数据栈是否为空 */
int isEmptyDataStack(DataLinkedStack S)
{
    if (NULL == S.top)
        return 1;        // 栈为空,则返回1
    else
        return 0;        // 否则, 返回0
}


//

// 指针栈初始化为空栈
void initPtrStack(PtrLinkedStack& stack)
{
    stack.top = NULL;
}


/* 判断指针栈是否为空 */
int isEmptyPtrStack(PtrLinkedStack stack)
{
    if (NULL == stack.top)
        return 1;        // 栈为空,则返回1
    else
        return 0;        // 否则, 返回0
}

/* 进栈一个元素 */
void pushToPtrStack(PtrLinkedStack& stack, BiTree e)
{
    PtrStackNode* p;

    // 开辟空间,构造结点
    p = (PtrStackNode*)malloc(sizeof(PtrStackNode));
    p->data = e;
    p->next = NULL;

    // 入栈
    p->next = stack.top;
    stack.top = p;
}

/* 出栈一个元素 */
int popFromPtrStack(PtrLinkedStack& stack, BiTree& e)
{
    PtrStackNode* p;

    if (NULL != stack.top)
    {
        p = stack.top;
        stack.top = p->next;
        // 或stack.top = stack.top->next;

        e = p->data;
        free(p);

        return 1;        // 出栈成功
    }
    else
        return 0;        // 栈为空,出栈失败
}

/* 获取栈顶 */
int getTopOfPtrStack(PtrLinkedStack stack, BiTree& e)
{
    if (NULL != stack.top)
    {
        e = stack.top->data;
        return 1;        // 栈不为空,获取栈顶成功,则返回1
    }
    else
        return 0;        // 否则, 返回0
}

队列:

// 初始化为空队列
// 队头和队尾指向顺序队列数组中的最后一个元素
void initQueue(SeqQueue& queue)
{
    queue.front = queue.rear = QUEUE_MAX_LENGTH - 1;
}


// 判断队列是否为满
// 队尾指针下一个指向队头时队满
int queueIsFull(SeqQueue queue)
{
    if (queue.front == (queue.rear + 1) % QUEUE_MAX_LENGTH)
        return 1;
    else
        return 0;
}

// 判断队列是否为空
// 队头队尾指向同一元素时队列为空
int queueIsEmpty(SeqQueue queue)
{
    if (queue.front == queue.rear)
        return 1;
    else
        return 0;
}


/* 进队一个元素 */
int inQueue(SeqQueue& queue, BiTree e)
{
    if (1 == queueIsFull(queue))
        return 0;            // 队列已满,无法进队
    else
    {
        queue.rear = (queue.rear + 1) % QUEUE_MAX_LENGTH;
        queue.data[queue.rear] = e;

        return 1;            // 进队成功
    }
}


/* 出队一个元素 */
int outQueue(SeqQueue& queue, BiTree& e)
{
    if (1 == queueIsEmpty(queue))
        return 0;            // 队列已空,无法出队
    else
    {
        queue.front = (queue.front + 1) % QUEUE_MAX_LENGTH;  
        e = queue.data[queue.front];

        return 1;            // 出队成功(实际元素仍存在于数组中,逻辑上出队成功)
    }
}


// 获取当前队列中有多少个元素
int getElemNum(SeqQueue queue)
{
    return (queue.rear - queue.front + QUEUE_MAX_LENGTH) % QUEUE_MAX_LENGTH;
}

/* 读取队头和队尾元素的信息 */
int getFrontRear(SeqQueue queue, BiTree& ef, BiTree& er)
{
    if (1 == queueIsEmpty(queue))
        return 0;            // 队列已空,无队头和队尾
    else
    {
        ef = queue.data[queue.front + 1];
        er = queue.data[queue.rear];

        return 1;
    }
}

二、根据完整先序序列,递归创建二叉树(二叉链表存储结构)

BT.dat 文件内容(完整先序序列):ABD#G##E##C#FH###

递归算法(图文详解)_碎涛的博客-程序员宅基地_递归算法

个人易错点:每次递归“归来”时都要从开始递归的代码行,继续执行后续代码,直到进行下一次“归来”,而不是忽略后续代码的执行直接继续下一次“归来”。

BiNode* createBiTree(FILE* fp)
{
    char ch;
    BiNode* p;

    // 从文件中依次读取各个结点值(空树为#)
    ch = fgetc(fp);

    if ('#' != ch)
    {
        // 开辟空间,构造结点,最后递归创建左右子树
        p = (BiNode*)malloc(sizeof(BiNode));
        p->data = ch;

        // 递归创建ch结点的左子树
        p->lchild = createBiTree(fp);

        // 递归创建ch结点的右子树
        p->rchild = createBiTree(fp);

        return p;  //返回根节点地址
    }
    else
        return NULL;
}

三、各种遍历

1.递归方式先序遍历

void preOrder(BiTree root)
{
    if (root == NULL) {  // 特殊情况优先考虑
        return;
    }
    printf("%2c", root->data);
    preOrder(root->lchild);
    preOrder(root->rchild);
}

2.递归方式中序遍历

void inOrder(BiTree root)
{
    if (root == NULL) {
        return;
    }
    inOrder(root->lchild);
    printf("%2c", root->data);
    inOrder(root->rchild);

}

3.递归方式后序遍历

void postOrder(BiTree root)
{
    if (root == NULL) {
        return;
    }
    postOrder(root->lchild);
    postOrder(root->rchild);
    printf("%2c", root->data);
}

4.非递归方式前序遍历

利用栈。

先将根结点输出,然后将其右孩子进指针栈、左孩子进指针栈,先右后左进栈则先左后右出栈

当指针栈不为空时,出栈一个元素,对其进行先序遍历:先将根结点输出,然后将根结点的右、左孩子依次进栈。

void nonRecursionPreOrder(BiTree root)
{
    PtrLinkedStack ptrStack;
    BiTree subRoot = NULL;

    // 先将栈初始化为空
    initPtrStack(ptrStack);

    // 先序遍历时,根应最先访问,所以先将根结点输出
    printf("%2c", root->data);
 

    // 再将右子树和左子树根结点的地址,依次进指针栈ptrStack  
    //先右后左进栈,先左后右出栈
    if (NULL != root->rchild)
        pushToPtrStack(ptrStack, root->rchild);

    if (NULL != root->lchild)
        pushToPtrStack(ptrStack, root->lchild);

    // 当PLStack栈不为空时,说明还有子树没有遍历
    while (0 == isEmptyPtrStack(ptrStack))
    {
        // 出栈一个元素(某棵子树根结点的地址) (左)
        popFromPtrStack(ptrStack, subRoot);

        // 先将根结点的值输出
        printf("%2c", subRoot->data);
      

        // 再将右子树和左子树根结点的地址,依次进指针栈ptrStack
        if (NULL != subRoot->rchild)
            pushToPtrStack(ptrStack, subRoot->rchild);

        if (NULL != subRoot->lchild)
            pushToPtrStack(ptrStack, subRoot->lchild);
    }
}

5.非递归方式中序遍历

(1)根结点先进栈。

(2)当栈不为空时,出栈一个元素:

        若为叶子结点则直接输出;

        若不是叶子结点,判断其第几次出栈:看栈顶是否为自己的右孩子,若是则为第二次出栈,若不是则为第一次出栈。对于没有右孩子的结点,进栈时将根节点多进一次栈,此时若为第二次出栈则其右孩子为自己。

                第一次出栈,代表以自己为根的子树,将其分解为三部分,并按 “右根左”的顺序进栈。

                第二次出栈:代表自己,可直接输出。 

void nonRecursionInOrder(BiTree root)
{
    PtrLinkedStack ptrStack;        // 定义一个结点指针型栈
    BiTree outElem, topElem;    // 分别用来保存出栈元素和栈顶元素

    // 先将指针栈初始化为空
    initPtrStack(ptrStack);

    // 二叉树的根进栈
    if (NULL != root)
        pushToPtrStack(ptrStack, root);

    // 当PLStack栈不为空时,说明还有子树没有遍历
    while (0 == isEmptyPtrStack(ptrStack))
    {
        // 出栈一个元素(某棵子树根结点的地址)
        popFromPtrStack(ptrStack, outElem);

        // 如果出栈的是叶子结点,则直接输出;
        if (NULL == outElem->lchild && NULL == outElem->rchild)
            printf("%2c", outElem->data);
        else
        {
            // 如果出栈的结点不是叶子
            if (1 == getTopOfPtrStack(ptrStack, topElem))  //判断是否成功获取栈顶
            {
                // 出栈时栈顶为其右孩子则说明其第二次出栈,代表自己出栈,可直接输出(孩子在栈里说明自己已被拆分进栈过一次)
                if (outElem->rchild == topElem) {
                    printf("%2c", outElem->data);
                }
                else if (topElem == outElem) {     // 栈顶等于自己,说明出栈结点无右孩子,当前栈顶是多进栈的
                    printf("%2c", outElem->data);
                    popFromPtrStack(ptrStack, outElem);  //扔掉重复进栈的根,因为该结点是因为当前结点无右孩子而多进栈的
                }
                else
                {
                    if (NULL != outElem->rchild)
                        pushToPtrStack(ptrStack, outElem->rchild);        // 右子树的根进栈
                    else
                    {
                        //对于没有右孩子的,虚构一个等于自己的右孩子(进两次栈),这样当栈顶为自己则表示第二次出栈
                        pushToPtrStack(ptrStack, outElem);
                    }

                    pushToPtrStack(ptrStack, outElem);                // 二叉树的根进栈

                    if (NULL != outElem->lchild)
                        pushToPtrStack(ptrStack, outElem->lchild);        // 左子树的根进栈   
                }
            }
            // 若获取栈顶失败,出栈元素必须分解为三部分,并按“右根左”的顺序进栈。
            else 
            {
                if (NULL != outElem->rchild)
                    pushToPtrStack(ptrStack, outElem->rchild);        // 右子树的根进栈
                else
                {
                    //对于没有右孩子的,虚构一个等于自己的右孩子(进两次栈),若栈顶为自己则表示第二次出栈
                    pushToPtrStack(ptrStack, outElem);
                }

                pushToPtrStack(ptrStack, outElem);                // 二叉树的根进栈

                if (NULL != outElem->lchild)
                    pushToPtrStack(ptrStack, outElem->lchild);        // 左子树的根进栈   
            }

        }
            
            
    }
    
}


/*    下面这个函数,也可以进行非递归中序遍历,
    但是在遍历过程中,二叉链表将被破坏,所以一般不用这种方法!*/
    // 会破坏二叉链表存储结构的非递归方式中序遍历
void problematicNonRecursionInOrder(BiTree root)
{
    PtrLinkedStack ptrStack;    // 定义一个结点指针型栈
    BiTree leftChild;

    // 先将栈初始化为空
    initPtrStack(ptrStack);

    // 二叉树的根进栈
    if (NULL != root)
        pushToPtrStack(ptrStack, root);

    // 当PLStack栈不为空时,说明还有子树没有遍历
    while (0 == isEmptyPtrStack(ptrStack))
    {
        BiTree p = NULL;

        // 出栈一个元素(某棵子树根结点的地址)
        popFromPtrStack(ptrStack, p);

        // 如果该根结点的左右子树都不存在(即为孤立结点),则直接输出;
        // 否则,必须分解为三部分按“右根左”的顺序进栈。
        // 注意:根结点也作为一个单独的子树,所以其左右指针域应先设置为NULL。
        if (NULL == p->lchild && NULL == p->rchild)
        {
            printf("%2c", p->data);
        }
        else
        {
            leftChild = p->lchild;                    // 先保留左子树根的地址

            if (NULL != p->rchild)
                pushToPtrStack(ptrStack, p->rchild);    // 右子树的根进栈

            p->lchild = NULL;                 //清空左右孩子域,进去孤立结点
            p->rchild = NULL;
            pushToPtrStack(ptrStack, p);                // 二叉树的根进栈

            if (NULL != leftChild)
                pushToPtrStack(ptrStack, leftChild);    // 左子树的根进栈
        }
    }
}

6.非递归方式后序遍历

设置指针栈和数据栈。数据栈数据域为char,指针栈数据域为BiTree。

进栈:

        数据栈:根→根右→根左

        指针栈:(栈底)根的左子树→根的右子树

                当指针栈不为空时,说明还有子树没有遍历:出栈,将其根进数据栈,将其左右子树依次进指针栈。

将数据栈元素出栈,即可得到后序遍历序列。

// Function5--非递归方式后序遍历
void nonRecursionPostOrder(BiTree root)
{
    DataLinkedStack dataStack;        // 定义一个输出数据栈
    PtrLinkedStack ptrStack;            // 定义一个结点指针型栈

    // 先将两个栈都初始化为空
    initDataStack(dataStack);
    initPtrStack(ptrStack);

    // 后序遍历时,根应最后访问,所以先将根结点的值进数据栈DLStack
    pushDataStack(dataStack, root->data);

    // 再将左子树和右子树根结点的地址,依次进指针栈PLStack  
    if (NULL != root->lchild)
        pushToPtrStack(ptrStack, root->lchild);

    if (NULL != root->rchild)
        pushToPtrStack(ptrStack, root->rchild);  

    // 当PLStack栈不为空时,说明还有子树没有遍历
    while (0 == isEmptyPtrStack(ptrStack))
    {
        BiTree pNode = NULL;

        // 出栈一个元素(某棵子树根结点的地址)
        popFromPtrStack(ptrStack, pNode);

        // 先将根结点的值进数据栈DLStack
        pushDataStack(dataStack, pNode->data);

        // 再将左子树和右子树根结点的地址,依次进指针栈PLStack
        if (NULL != pNode->lchild)
            pushToPtrStack(ptrStack, pNode->lchild);

        if (NULL != pNode->rchild)
            pushToPtrStack(ptrStack, pNode->rchild);
    }

    // 数据栈dataStack依次出栈,即可得到后序遍历序列
    while (0 == isEmptyDataStack(dataStack))
    {
        char value = ' ';

        // 出栈一个元素(某结点的值),并输出
        popFromDataStack(dataStack, value);
        printf("%2c", value);
    }
}

7.层次遍历

void hierarchicalOrder(BiTree root)
{
    BiTree pNode = NULL;
    SeqQueue queue;

    // 初始化为空队列
    initQueue(queue);

    // 树根结点的地址先进队
    inQueue(queue, root);

    // 只要队列不为空,则一直循环
    while (queueIsEmpty(queue) == 0) {
        outQueue(queue, pNode);
        printf("%2c", pNode->data);

        if (pNode->lchild != NULL)
            inQueue(queue, pNode->lchild);
        if (pNode->rchild != NULL)
            inQueue(queue, pNode->rchild);

    }


}

8.递归销毁二叉树

void destroy(BiTree root)
{
    if (NULL != root)
    {
        if (NULL != root->lchild)        // 左子树不为空,则递归销毁左子树
            destroy(root->lchild);

        if (NULL != root->rchild)        // 右子树不为空,则递归销毁右子树
            destroy(root->rchild);

        printf("%c node has been freed!\n", root->data);
        free(root);        // 最后直接释放根结点
    }
}

四、功能菜单和主函数

// 功能菜单
void menu()
{
    printf("\n\t************************Binary Linked List************************\n");
    printf("\t*    1--Read data from a file to create a binary tree            *\n");
    printf("\t*    2--PreOrder, InOrder and PostOrder traversal by recursion   *\n");
    printf("\t*    3--PreOrder traversal by non-recursion                      *\n");
    printf("\t*    4--InOrder traversal by non-recursion                       *\n");
    printf("\t*    5--PostOrder traversal by non-recursion                     *\n");
    printf("\t*    6--Hierarchical traversal (using queue)                     *\n");
    printf("\t*    7--Destroy the entire binary tree                           *\n");
    printf("\t*    8--Clear screen                                             *\n");
    printf("\t*    0--Exit program                                             *\n");
    printf("\t******************************************************************\n");
    printf("\tPlease select a menu item:");
}

int main()
{
    int choice;
    char c;
    BiTree root = NULL;        
    FILE* fpFrom;

    system("chcp 65001");  // 设置window控制台(CMD或命令行窗口)为UTF-8格式

    while (1)
    {
        menu();
        scanf("%d", &choice);

        switch (choice)
        {
        case 1:
            if (NULL != root)
            {
                printf("The current binary tree is not empty, please destroy it before rebuild!\n");
            }
            else
            {
                // 因为createBiTree()函数递归时要不断从文件中读取字符,所以先打开文件
                // 如果在createBiTree()函数中每读一个字符,就打开并关闭文件一次,则效率太低
                fpFrom = fopen("BT.dat", "r");
                if (NULL == fpFrom)
                {
                    printf("File containing complete PreOrdered sequence cannot be opened, binary tree creation failed!\n");
                    break;
                }

                root = createBiTree(fpFrom);

                fclose(fpFrom);
                printf("Binary tree created successfully!\n");
            }
            break;

        case 2:
            if (NULL != root)
            {
                printf("The PreOrdered sequence is as follows:");
                preOrder(root);

                printf("\nThe InOrdered sequence is as follows:");
                inOrder(root);

                printf("\nThe PostOrdered sequence is as follows:");
                postOrder(root);

                printf("\n");
            }
            else
                printf("The current binary tree is empty, please create the binary tree first!\n");
            break;

        case 3:
            if (NULL != root)
            {
                printf("The non-recursive PreOrdered sequence is as follows:\n");
                nonRecursionPreOrder(root);
                printf("\n");
            }
            else
                printf("The current binary tree is empty, please create the binary tree first!\n");
            break;

        case 4:
            if (NULL != root)
            {
                printf("The non-recursive InOrdered sequence is as follows:\n");
                nonRecursionInOrder(root);
                printf("\n");
            }
            else
                printf("The current binary tree is empty, please create the binary tree first!\n");
            break;

        case 5:
            if (NULL != root)
            {
                printf("The non-recursive PostOrder sequence is as follows:\n");
                nonRecursionPostOrder(root);
                printf("\n");
            }
            else
                printf("The current binary tree is empty, please create the binary tree first!\n");
            break;

        case 6:
            if (NULL != root)
            {
                printf("The hierarchical ordered sequence is as follows:\n");
                hierarchicalOrder(root);
                printf("\n");
            }
            else
                printf("The current binary tree is empty, please create the binary tree first!\n");
            break;

        case 7:
            if (NULL != root)
            {
                destroy(root);
                root = NULL;
                printf("The binary tree destroyed successfully!\n");
            }
            else
                printf("The current binary tree is empty, no need to destroy!\n");
            break;

        case 8:
            system("cls");
            break;

        case 0:
            // 关闭保存结果的文件后,再退出程序
            exit(0);
            break;

        default:
            // If the user enters an alphabetic menu item instead of an integer, 
            // the buffer needs to be emptied
            while ((c = getchar()) != '\n' && c != EOF);
            printf("The menu item you entered does not exist, please select it again!\n");
        }
    }
    return 0;
}

五、代码实现

测试数据:ABD#G##E##C#FH###

(放在文件"BT.dat"中)

 (二进制文件要与源程序.cpp放在一个文件夹下)

我实现了一下是没问题的。

说明:本文代码是我的数据结构作业,是老师写的,因为理解不透彻所以自己写了注释和分析,发现要自己写还是有点困难qwq,好歹自己理了一下思路,希望对你们有帮助.OvO.

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_62800173/article/details/127820112

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文