首页 > 编程语言 > 详细

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

时间:2019-04-04 18:22:20      阅读:171      评论:0      收藏:0      [点我收藏+]

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

 

构造出来了:

技术分享图片

 

 

#法创建树:

技术分享图片

 

 

答:可以。

 

#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("\n");

    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("\n");

}

 

 

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("排序前:\n");

 

    //PrintArray(arr, MAX);

   

    long t_start = getSystemtime();

 

    BubbleSort(arr,MAX);

 

    long t_end = getSystemtime();

 

 

   

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

 

    //PrintArray(arr, MAX);

   

 

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

 

   

    printf("\n");

    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("\n");

}

 

 

 

// 选择排序

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\n",MAX,tbubble_end-tbubble_start);

 

 

 

 

    // 选择排序

    long tselect_start = getSystemtime();

    SelectSort(arr2, MAX);

    long tselec_end = getSystemtime();

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

 

 

    printf("\n");

    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("\n");

}

 

// 选择排序

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\n",MAX,tshell_end - tshell_start);

 

    //PrintArray(arr, MAX);

 

 

    long tinsert_start = getSystemtime();

    InsertSort(arr2, MAX);

    long tinsert_end = getSystemtime();

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

 

 

    printf("\n");

    system("pause");

    return 0;

}

 

 

 

/*

问题:

   

    1. include <time.h>

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

       rand() % MAX

 

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

   

   

*/

 

 技术分享图片

 

 

惊了

 

 

插入排序:

技术分享图片

 

希尔排序:

 

技术分享图片

技术分享图片

 

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

原文:https://www.cnblogs.com/eret9616/p/10656351.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!