zoukankan      html  css  js  c++  java
  • 排序算法 & 迷宫的深度, 广度优先

    内容提要

    1. 我掌握的排序算法的时间复杂度

    2. 我掌握的6种排序算法(插入, 冒泡, 选择, 归并, 快速, 希尔)

    3. 迷宫的搜索方法(深度优先 + 广度优先)


    各种排序的时间复杂度

    名称 稳定 否 平均时间复杂度
    插入排序 稳定 n2
    冒泡排序 稳定 n2
    选择排序 n2
    归并排序 稳定 nlog2n
    希尔排序 n2
    快速排序 nlog2n

    各种排序算法

    1. 插入排序

    类似打扑克, 来一个数, 从这个数的前一个数开始, 一直到第一个数, 比这个数小的, 比如位置是 a, 那么 a 之前的都比这个数小, 所以, 要移动 a 以后到这个数以前的数, 向后移动一位, 然后将这个数插入到 a+1 的位置上

    #include<stdio.h>

    int a[10] = {
        10, 2, 5, 1, 3, 4, 6, 7, 9, 8
    };

    void insert_sort()
    {
        int j = 1;     /* 插入location */
        int i ;
        int key = -1;
        for (j=1; j<10; j++) {
            i = j - 1;
            key = a[j];
            /* 移动元素 */
            while (i>=0 & a[i] > key) {
                a[i+1] = a[i];
                i--;
            }
            a[i+1] = key;
        }
    }

    int main(void)
    {
        int i = 0;
        printf("-------- now the data --------: ");
        for (i=0; i<10; i++) {
            printf("%d, ", a[i]);
        }
        insert_sort();
        printf(" -------- after insert sort --------: ");
        for (i=0; i<10; i++) {
            printf("%d, ", a[i]);
        }
    }

    2. 冒泡排序

    第一个循环就是控制循环次数, 没有别的意义, 在每次循环内部, 两两比较, 这样, 最大的数, 第一次循环就冒出去了, 以此类推, 逐渐冒出去第2大, 第3大的数.

    #include <stdio.h>

    #define LEN 10

    int a[LEN] = {10, 5, 6, 7, 8, 1, 4, 2, 9, 3};

    void maopao_sort(void)
    {
        int count = 0;
        int circle = LEN;
        int i = 0;
        int j = 1;
        int temp;
        for (count=0; count<LEN; count++) {    // 总循环次数 
            circle--;
            for (i=0; i<circle; i++) {
                if (a[i+1] < a[i]) {
                    temp = a[i+1];
                    a[i+1] = a[i];
                    a[i] = temp;
                }
            }
        }   
    }

    int main(void)
    {
        int i = 0;
        maopao_sort();
        for (i=0; i<LEN; i++) {
            printf("%d,", a[i]);
        }
        return 0;
    }

    3. 选择排序

    第一个循环是控制循环次数, 每次找出这个循环中最小的数,放在第一个位置, 然后再从第2个数开始找, 找出第二次循环中最小的数,放在第2个的位置上, 以此类推

    #include<stdio.h>

    #define LEN 10

    int a[LEN] = {
        10, 2, 5, 3, 4, 1, 7, 6, 8, 9
    };

    void selectSort()
    {
        int temp;
        int i;
        int j;
        for (i=0; i<LEN; i++) {
            for (j=i+1; j<LEN; j++) {
                if (a[j] < a[i]) {
                    temp = a[i];
                    a[i] = a[j];
                    a[j] = temp;
                }
            }
        }
    }


    int main(void)
    {
        int i;
        selectSort();
        for (i=0; i<LEN; i++) {
            printf("%d,", a[i]);
        }   
        return 0;
    }

    4. 归并排序(个人最喜欢的排序)

    递归思想, 首先, 将所有的数分为两部分, 这两部分排好序后,再整合(归并) merge, 整合时, 因为左右两边都是已经排好序的, 所以, 排序起来容易很多.

    #include<stdio.h>

    #define LEN 10

    int a[LEN] = {
        10, 7, 4, 2, 3, 1, 8, 9, 5, 6
    };

    void merge(int start, int mid, int end)
    {
        int n1 = mid - start + 1;
        int n2 = end - mid;
        int left[n1];
        int right[n2];
        int i, j, k;
        // init left and right
        for (i=0; i<n1; i++) {
            left[i] = a[start+i];
        }   
        for (j=0; j<n2; j++) {
            right[j] = a[mid+1+j];
        }
        i = j = 0;
        k = start;
        // merge
        while (i < n1 && j < n2) {
            if (left[i] <= right[j]) {
                a[k++] = left[i++];
            } else {
                a[k++] = right[j++];
            }
        }
        while (i < n1) {
            a[k++] = left[i++];
        }
        while (j < n2) {
            a[k++] = right[j++];
        }
               
    }


    void sort(int start, int end)
    {
        int mid;
        if (start < end) {
            mid = (end + start) / 2;
            sort(start, mid);
            sort(mid+1, end);
            merge(start, mid, end);
        }   
    }

    int main(void)
    {
        int i;
        sort(0, LEN-1);
        for(i=0; i<LEN; i++) {
            printf("%d,", a[i]);
        }   
       
        return 0;
    }

    5. 希尔排序

    插入排序的升级版, 算法: 首先定义一个步长, 一般设定为 LEN/2, 然后相隔这个步长的元素进行插入排序, 这个步长逐步缩小, 直到步长为1 .

    #include<stdio.h>

    # define LEN 10
    int a[LEN] = {
        10, 2, 4, 1, 6, 8, 3, 5, 9, 7
    } ;


    void Shell_sort()
    {
        int d = LEN / 2;
        int j;
        int i;
        int temp;
        while (d > 0) {    /* 步长控制总的循环次数 */
            for (j=d; j<LEN; j++) {  /* 类似插入排序中的 j=1 */
                i = j-d;             /* 从插入为的前一位开始比较, 注意这个前一位是间隔前步长位 */
                temp = a[j];
                /* 移位 */
                while (i>=0 && a[i] > temp) {   /* 注意: 这里一定要是 temp, 而不能是 a[j], 因为循环内部已经改变了a[j]的值 */
                    a[i+d] = a[i];
                    i -= d;
                }
                a[i+d] = temp;     /* 插入操作 */ 
            }
           
            d = d/2;   
        }
    }

    int main(void)
    {
        int i;
        Shell_sort();   
        for (i=0; i<10; i++) {
            printf("%d, ", a[i]);
        }
    }

    6. 快速排序

    快速排序是冒泡排序的升级版, 采用了分治策略, 首先把序列分成两个子序列, 递归对子序列进行排序. 首先找到一个轴, 对序列进行重新排序, 比轴小的放到轴左边, 比轴的放到轴右边, 划分后, 轴的位置就是正确的(即数组下标不会在发生改变了), 递归对两个子序列进行重新排序.

    #include<stdio.h>

    #define LEN 10

    int a[LEN] = {
        10, 5, 3, 2, 1, 7, 8, 6, 9, 4
    };

    int position(int start, int end)
    {
        int dp = start;
        int i = start; /* 左边指针 */
        int j = end;   /* 右边指针 */
        int temp;
        while (i < j) {
            for(; i<dp; i++) {
                if (a[i] > a[dp]) {
                    temp = a[i];
                    a[i] = a[dp];
                    a[dp] = temp;
                    dp = i;
                }   
            }
           
            for (; j>dp; j--) {
                if (a[j] < a[dp]) {
                    temp = a[j];
                    a[j] = a[dp];
                    a[dp] = temp;
                    dp = j;
                }   
            }
        }
        return dp;
           
    }


    void short_sort(int start, int end)
    {
        int dp;
        dp = position(start, end);
        printf(" dp location: %d ", dp);
        if (start < end) {
            short_sort(start, dp-1);
            short_sort(dp+1, end);
        }   
    }

    int main(void)
    {
        int i;
        short_sort(0, LEN-1);
        for (i=0; i<LEN; i++) {
            printf("%d, ", a[i]);
        }   
    }


    迷宫深度优先, 广度优先

    参考本blog中的 栈和队列

    深度优先 用栈实现

    广度优先 用队列实现, 特别的地方是, 用栈实现的广度优先, 在入队列时, 要记录对应的上一步的位置, 因为它不同栈, 栈的上一步的位置是按照栈的先后顺序存储的.

  • 相关阅读:
    PAIP: Paradigms of Artificial Intelligence Programming
    Common Lisp第三方库介绍 | (R "think-of-lisper" 'Albertlee)
    悲惨世界
    Lisp: Common Lisp, Racket, Clojure, Emacs Lisp
    Github上四种Lisp方言的流行度 | 肉山博客 (Wenshan's Blog)
    Nginx系列~负载均衡服务器与WWW服务器的实现
    Nginx系列~Nginx服务启动不了
    知方可补不足~数据库名称和数据库别名不同了怎么办
    WebApi系列~通过HttpClient来调用Web Api接口~续~实体参数的传递
    WebApi系列~通过HttpClient来调用Web Api接口
  • 原文地址:https://www.cnblogs.com/moveofgod/p/4059871.html
Copyright © 2011-2022 走看看