• 数据结构(4) 第四天 二叉树的创建、 #法创建树、霍夫曼树、排序的基本概念、冒泡排序、选择排序、插入排序、希尔排序


    01 昨天课程回顾

    02 二叉树非递归遍历思路

    用栈

    03 二叉树的非递归遍历代码实现

    非递归遍历二叉树

    思路: 讲二叉树结点包装成一个新的结构体,增加一个flag 初始化值为false

    第一次把根节点压入栈

    如果栈中元素非空,进行循环:

    {

    从栈中弹出首部元素

      如果该元素node为 null 跳过这次循环,

      否则 将该元素flag设置为true  // 当设置为true的时候 意味着这个节点在将来某个时刻会被访问

    找到该元素 左结点 右结点 分别进行包装

    对于先序遍历DLR

    入栈顺序应该相反, RLD

    将包装好的右结点 左节点 结点 分别入栈

    }

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

     

    #include "linkstack.h"

     

     

    #define MY_FALSE 0

    #define MY_TRUE 1

    // 二叉树结点

    typedef struct BINARYNODE {

        char ch;

        struct BINARYNODE * lchild;

        struct BINARYNODE * rchild;

    } BinaryNode;

    // 栈中元素结构体:结构体存放一个 二叉树 和一个 flag

    typedef struct BITREESTACKNODE {

        LinkNode node;

        BinaryNode * root;

        int flag;

    } BiTreeStackNode;

     

    // 创建栈中的结点

    BiTreeStackNode * CreateBiTreeStackNode(BinaryNode * node,int flag) {

     

        // 在堆上分配空间 创建newnode

        BiTreeStackNode * newnode = (BiTreeStackNode *)malloc(sizeof(BiTreeStackNode));

     

        // root值是node

        newnode->root = node;

     

        // flag是flag

        newnode->flag = flag;

     

        // 返回newnode

        return newnode;

    }

     

    // 非递归遍历

    void NonRecursion(BinaryNode * root)

    {

     

        // 1.创建栈

        LinkStack * stack = Init_LinkStack();

     

        // 2.把根节点扔到栈里

        Push_LinkStack(stack, (LinkNode *)CreateBiTreeStackNode(root, MY_FALSE));

     

        // 判断栈是否为空

        while (Size_LinkStack(stack) > 0) {

     

            // 先弹出栈顶元素

            BiTreeStackNode * node =  (BiTreeStackNode *)Top_LinkStack(stack);

     

            Pop_LinkStack(stack);

     

     

            // 判断弹出的结点是否为空

            if (node->root == NULL) {

                // 跳过当前循环

                continue;

            }

     

            // 如果node的 flag标志是true

            if (node->flag == MY_TRUE) {

                printf("%c",node->root->ch);

            }else

            {

                // 对于先序遍历,压入顺序应该倒过来:先压右 再压左 最后压根

                // 对于中序遍历  压入顺序应是      先压右 再压中 最后压左

                // 对于后序遍历  压入顺序应该是    先压中 再压右 最后压左

     

     

     

                node->flag = MY_TRUE;

     

     

                // 当前结点右结点入栈

                Push_LinkStack(stack, (LinkNode *)CreateBiTreeStackNode(node->root->rchild, MY_FALSE));

     

     

     

                // 当前结点入栈

                // 压根

                Push_LinkStack(stack, (LinkNode *)node);

     

     

     

                // 当前结点左结点入栈

                Push_LinkStack(stack, (LinkNode *)CreateBiTreeStackNode(node->root->lchild, MY_FALSE));

     

     

               

     

            }

        }

    }

    04 二叉树的创建

    结论: 通过中序遍历和先序遍历可以确定一棵树。

          通过中序遍历和后序遍历可以确定一棵树

         通过先序遍历和后序遍历确定不了一棵树

    通过先序遍历结果 确定了根是A

    通过中序确定了左子树是DE 右子树是CFB

    构造出来了:

    #法创建树: (序列化 二叉树)

    答:可以。

    https://blog.csdn.net/yusiguyuan/article/details/42687623

    先序和中序,后序和中序需要两个组合才可以唯一确定一颗二叉树。

    #法这一个就可以唯一确定一颗二叉树,因为包含了空节点的信息了。

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

     

     

     

    // 定义二叉树结构体

    typedef struct BINARYNODE

    {

        // 存放ch

        char ch;

        // 存放左子树

        struct BINARYNODE * lchild;

        // 存放右子树

        struct BINARYNODE * rchild;

    } BinaryNode;

     

     

    // 递归

    void Recursion(BinaryNode * root) {

       

        // 设置递归退出条件

        if (root == NULL) {

            return;

        }

       

        // DLR

        // 打印ch

        printf("%c", root->ch);

     

        // 递归左节点

        Recursion(root->lchild);

     

        // 递归右结点

        Recursion(root->rchild);

    }

     

     

    // 创建二叉树

    BinaryNode * CreateBinaryTree()

    {

        fflush(stdin);

     

        char ch;

        scanf("%c",&ch);

     

        BinaryNode * node;

     

        if (ch == '#') {

            node = NULL;

        }

        else {

            node = (BinaryNode *)malloc(sizeof(BinaryNode));

            node->ch = ch;

            node->lchild = CreateBinaryTree();

            node->rchild = CreateBinaryTree();

        }

     

        return node;

    }

     

     

    int main(void)

    {

        // 创建树

        BinaryNode * root =  CreateBinaryTree();

        // 打印树

        Recursion(root);

     

     

        printf(" ");

        system("pause");

        return 0;

    }

     

    // A B C D # # P  # #  # Q

    // ???????这段代码根本跑不通… … 但是还是记录下来了 可能是fflush(stdin)的问题

    // 资料: fflush(stdin) 清空输入缓冲区 只在老旧的vc编译器下有小 是一个非C官方标准的实现

    05 上午课程回顾

    二叉树的非递归遍历:

    06 排序基本概念

     

    补: 霍夫曼树

     

    07 冒泡排序

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

     

    // 1 time.h是个啥?

    #include <time.h>

    // 2.

    #include <sys/timeb.h>

     

    #define MAX 100000

     

     

     

     

    long getSystemtime() {

     

        struct timeb tb;

        ftime(&tb);

        return tb.time * 1000 + tb.millitm;

            // 1s = 1000 ms

    }

     

     

     

     

    // 交换函数

    void Swap(int * a,int *b)

    {

        int temp = *a;

        *a = *b;

        *b = temp;

    }

     

     

    // C语言中如何创建随机数

    // 冒泡排序法

    void BubbleSort(int arr[], int length) { 

        // len:4 arr[4]

        for (int i = 0; i < length; i++)

        {

            for (int j = i; j < length; j++)

            {

                // 每次把最大的放到后面

                if (arr[j]<arr[i])

                {

                    Swap(&arr[i],&arr[j]);

                }

            }

        }

    }

     

     

     

    // 打印函数

    void PrintArray(int arr[],int length) {

        for (int i = 0; i < length;i++) {

            printf("%d ", arr[i]);

        }

        printf(" ");

    }

     

     

    int main(void)

    {

        int arr[MAX];

     

     

        // 设定随机种子

        srand((unsigned int)time(NULL));

       

     

        for (int i = 0;i<MAX;i++)

        {

                    // 产生0 到MAX的随机数

            arr[i] = rand() % MAX;

        }

     

     

        // 排序前

        printf("排序前: ");

     

        //PrintArray(arr, MAX);

       

        long t_start = getSystemtime();

     

        BubbleSort(arr,MAX);

     

        long t_end = getSystemtime();

     

     

       

        printf("冒泡排序后: ");

     

        //PrintArray(arr, MAX);

       

     

        printf("冒泡排序%d个元素,所需时间:%ld毫秒 ", MAX, t_end - t_start);

     

       

        printf(" ");

        system("pause");

        return 0;

    }

     

     

     

    /*

    问题:

       

        1. include <time.h>

           srand((unsigned int)time(NULL));

           rand() % MAX

     

        2. #include <sys/timeb.h> // 精确到毫秒?

       

       

    */

    08 冒泡排序改进版

    … …注意这种写法里面比较的是i 和 i+1

    09 选择排序

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

     

    #include <time.h>

    #include <sys/timeb.h>

     

    #define MAX 10000

     

     

     

    long getSystemtime() {

     

        struct timeb tb;

        ftime(&tb);

        return tb.time * 1000 + tb.millitm;

            // 1s = 1000 ms

    }

     

     

    // 交换函数

    void Swap(int * a,int *b)

    {

        int temp = *a;

        *a = *b;

        *b = temp;

    }

     

     

    // 打印函数

    void PrintArray(int arr[],int length) {

        for (int i = 0; i < length;i++) {

            printf("%d ", arr[i]);

        }

        printf(" ");

    }

     

     

     

    // 选择排序

    void SelectSort(int arr[], int length)

    {

        // 选择排序减少了交换次数

        for (int i = 0;i<length;i++)

        {

            int min = i;

            for (int j = i + 1; j < length;j++ ){

                if (arr[j]<arr[min]) {

                    min = j;

                }

            }

            if (min != i) {

                Swap(&arr[min],&arr[i]);

            }

        }

    }

     

     

     

    // C语言中如何创建随机数

    // 冒泡排序法

    void BubbleSort(int arr[], int length) {

        int flag = 0; // 0 标识没有排序好

        // 代表外层循环

        for (int i = 0; i < length && flag == 0; i++)

        {

     

            flag = 1; // 认为已经排序好了

     

            for (int j = i; j < length - 1; j++)

            {

                // 内层循环如果走了一遍都没有发生交换

     

                // 每次把最大的放到后面

                if (arr[j] > arr[j + 1])

                {

                    flag = 0;

                    Swap(&arr[j + 1], &arr[j]);

                }

     

            }

        }

    }

     

     

    int main(void)

    {

        int arr[MAX];

        int arr2[MAX];

     

        srand((unsigned int)time(NULL));

     

        for (int i = 0; i < MAX;i++){

            int randNum = rand() % MAX;

            arr[i] = randNum;

            arr2[i] = randNum;

        }

     

     

        // 冒泡排序

        long tbubble_start = getSystemtime();

        BubbleSort(arr,MAX);

        long tbubble_end = getSystemtime();

        printf("冒泡排序%d个元素,所需时间:%ld ",MAX,tbubble_end-tbubble_start);

     

     

     

     

        // 选择排序

        long tselect_start = getSystemtime();

        SelectSort(arr2, MAX);

        long tselec_end = getSystemtime();

        printf("选择排序%d个元素,所需时间:%ld ", MAX, tselec_end - tselect_start);

     

     

        printf(" ");

        system("pause");

        return 0;

    }

    选择排序:

    // 选择排序

    function select(arr)

    {

      for (let i = 0;i<arr.length;i++)

      {

           let min = i

          for(let j = i+1 ;j<arr.length;j++)

          {

               if(arr[i] < arr[min])

               min = i

           }

          // 每次交换后 将最小的放在相应位置

          // 相比冒泡排序 减少了交换的次数

          if(min != i){

           swap(arr[i],arr[min])

          }

      }

    }

    10 插入排序

    1. 将无序序列插入到有序序列中

     

    (希尔排序就是对这两个情况的改进)

    // 插入排序

    void InsertSort(int arr[],int length) {

     

        int j;

     

        for (int i = 1;i<length;i++)

        {

            if (arr[i] < arr[i - 1]) {

               

                // 插入排序

                int temp = arr[i];

               

                                           

                for (j = i-1; j >= 0 && arr[j] > temp ; j-- )

                {

                    arr[j + 1] = arr[j];

                }

                // 循环退出时候j指向前一个元素.. 之前所有的都交换了

     

                // 最后把这个也给交换过去

                arr[j + 1] = temp;

            }

        }

    }

     

    11 插入排序代码实现

    12 插入排序代码思路梳理

    13 希尔排序思路

    在插入排序的基础上进行分组:

    14 希尔排序

    #define _CRT_SECURE_NO_WARNINGS

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

     

    #include <time.h>

    #include <sys/timeb.h>

     

    #define MAX 100000

     

    long getSystemtime() {

     

        struct timeb tb;

        ftime(&tb);

        return tb.time * 1000 + tb.millitm;

            // 1s = 1000 ms

    }

     

     

    // 交换函数

    void Swap(int * a,int *b)

    {

        int temp = *a;

        *a = *b;

        *b = temp;

    }

     

     

    // 打印函数

    void PrintArray(int arr[],int length) {

        for (int i = 0; i < length;i++) {

            printf("%d ", arr[i]);

        }

        printf(" ");

    }

     

    // 选择排序

    void SelectSort(int arr[], int length)

    {

        // 选择排序减少了交换次数

        for (int i = 0;i<length;i++)

        {

            int min = i;  // min此时为0

            for (int j = i + 1; j < length;j++ ){

                if (arr[j]<arr[min]) {

                    min = j;

                }

            }

            if (min != i) {

                Swap(&arr[min],&arr[i]);

            }

        }

    }

     

    // C语言中如何创建随机数

    // 冒泡排序法

    void BubbleSort(int arr[], int length) {

        int flag = 0; // 0 标识没有排序好

        // 代表外层循环

        for (int i = 0; i < length && flag == 0; i++)

        {

     

            flag = 1; // 认为已经排序好了

     

            for (int j = i; j < length - 1; j++)

            {

                // 内层循环如果走了一遍都没有发生交换

     

                // 每次把最大的放到后面

                if (arr[j] > arr[j + 1])

                {

                    flag = 0;

                    Swap(&arr[j + 1], &arr[j]);

                }

     

            }

        }

    }

     

    // 插入排序

    void InsertSort(int arr[],int length) {

     

        int j;

        for (int i = 1;i<length;i++)

        {

            if (arr[i] < arr[i - 1]) {

               

                // 插入排序

                int temp = arr[i];

               

                                           

                for (j = i-1; j >= 0 && arr[j] > temp ; j-- )

                {

                    arr[j + 1] = arr[j];

                }

                // 循环退出时候j指向前一个元素.. 之前所有的都交换了

     

                // 最后把这个也给交换过去

                arr[j + 1] = temp;

            }

        }

    }

     

     

    // 希尔排序

    void ShellSort(int arr[], int length)

    {

        int increasement = length;

        int i,j,k;

     

        do {

     

            // 确定分组的增量

            increasement = increasement / 3 + 1;

     

     

            for (int i = 0;i<increasement;i++)

            {

                // 分组排序

                for (j = i + increasement; j < length; j+=increasement) {

                   

                    if (arr[j] < arr[j-increasement] ) {

     

                        int temp = arr[j];

     

                        for (k = j - increasement; k >= 0 && temp < arr[k];k-=increasement ) {

                             arr[k + increasement] = arr[k];

                        }

     

                        arr[k + increasement] = temp;

     

                    }

     

                }

            }

     

     

        } while (increasement > 1);

     

    };

     

     

     

     

    // 希尔排序是对插入排序的升级

     

    // 分组 插入排序

    /*

     

       先分组 对每一组分别进行插入排序

       分别进行插入排序

     

    */

     

    // 1 元素序列基本有序的情况下

    // 2 元素个数比较小的时候

     

    /*

       

     

     

    */

     

     

    int main(void)

    {

        int arr[MAX];

        int arr2[MAX];

     

        srand((unsigned int)time(NULL));

     

        for (int i = 0; i < MAX;i++){

            int randNum = rand() % MAX;

            arr[i] = randNum;

            arr2[i] = randNum;

        }

     

     

        //PrintArray(arr, MAX);

     

        long tshell_start = getSystemtime();

        ShellSort(arr, MAX);

        long tshell_end = getSystemtime();

        printf("希尔排序%d个元素所需时间:%ld ",MAX,tshell_end - tshell_start);

     

        //PrintArray(arr, MAX);

     

     

        long tinsert_start = getSystemtime();

        InsertSort(arr2, MAX);

        long tinsert_end = getSystemtime();

        printf("插入排序%d个元素所需时间:%ld ", MAX, tinsert_end - tinsert_start);

     

     

        printf(" ");

        system("pause");

        return 0;

    }

     

     

     

    /*

    问题:

       

        1. include <time.h>

           srand((unsigned int)time(NULL));

           rand() % MAX

     

        2. #include <sys/timeb.h> // 精确到毫秒?

       

       

    */

     

    惊了

    插入排序:

    希尔排序:

  • 相关阅读:
    Java并发包线程池之ThreadPoolExecutor
    Java并发包之线程池概述
    Java同步数据结构之ConcurrentHashMap
    new 操作符
    javascript-类型转换
    javascript-引用类型
    JS-数组与伪数组
    SVG-JS操作
    SVG-变换
    SVG-标签
  • 原文地址:https://www.cnblogs.com/eret9616/p/10656351.html
Copyright © 2020-2023  润新知