zoukankan      html  css  js  c++  java
  • 数据结构(二)——排序

    排序:稳定排序算法,不稳定排序算法

    如上图,若两个5排序之后交换了位置就是不稳定的,没有交换位置就是稳定排序

    1.选择排序

      

      冒泡是相邻的两个交换,选择法是首元素与最小的交换。

     1 void xuanzhepaixu(int* my_array, int len)
     2 {
     3     for (int i = 0; i < len - 1; ++i) {
     4         for (int j = i + 1; j < len; ++j) {
     5             if (my_array[i] > my_array[j]) {// 交换次数多,不如记录下表位置效率高
     6                 int temp = my_array[i];
     7                 my_array[i] = my_array[j];
     8                 my_array[j] = temp;
     9             }
    10         }
    11 
    12     }
    13 }
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 // 选择法排序
     6 void xuanzhepaixu(int* my_array, int len)
     7 {
     8     int min = 0;
     9     for (int i = 0; i < len - 1; ++i) {
    10         min = i;
    11         for (int j = i + 1; j < len; ++j) {
    12             if (my_array[min] > my_array[j]) {
    13                 min = j;// 保存最小元素的位置
    14             }
    15         }
    16         if ( min != i ) {
    17             int temp = my_array[i];
    18             my_array[i] = my_array[min];
    19             my_array[min] = temp;
    20         }
    21     }
    22 }
    23 
    24 void my_print_array(int* my_array, int len)
    25 {
    26     for (int i = 0; i < len; ++i) {
    27         printf("%5d", my_array[i]);
    28     }
    29     printf("
    ");
    30 }
    31 
    32 int main()
    33 {
    34     int my_array[] = {10, 6, 7, 4, 9, 8, 5, 1, 3, 2};
    35     int len = sizeof(my_array) / sizeof(int);
    36 
    37     xuanzhepaixu(my_array, len);
    38 
    39     my_print_array(my_array, len);
    40 
    41     system("pause");
    42     return 0;
    43 }

    2.冒泡排序

     1 void maopaopaixu(int* my_array, int len)
     2 {
     3     for (int i = 0; i < len; ++i) {
     4         for (int j = 1; j < len; ++j) {
     5             if ( my_array[j] > my_array[j - 1] ) {
     6                 int temp = my_array[j];
     7                 my_array[j] = my_array[j - 1];
     8                 my_array[j - 1] = temp;
     9             }
    10         }
    11     }
    12 }

    冒泡算法的优化,在待排序数据处于一种趋于有序的情况,可以减少判断次数,比如:1,2,3,4,7,5,6

     1 void maopaopaixu(int* my_array, int len)
     2 {
     3     bool flag = false;
     4     for (int i = 0; i < len && !flag; ++i) {
     5         flag = true;
     6         for (int j = 1; j < len; ++j) {
     7             if ( my_array[j] > my_array[j - 1] ) {
     8                 int temp = my_array[j];
     9                 my_array[j] = my_array[j - 1];
    10                 my_array[j - 1] = temp;
    11                 flag = false;
    12             }
    13         }
    14     }
    15 }

    3.插入排序

      默认对两个序列进行操作:有序序列,无序序列。

      可以将无序序列分为两个部分

    void insert_paixu(int* my_array, int len)
    {
        int temp = 0;// 存储基准数
        int index = 0; // 存储坑的位置
    
        for (int i = 1; i < len; ++i) {
            temp = my_array[i];
            index = i;
            for (int j = i - 1; j >= 0; --j) {// 从后往前遍历
                if (temp < my_array[j]) {
                    my_array[j + 1] = my_array[j];
                    index = j;
                }
                else break;//最后一个保存的是最大的元素,此语句可以减少判断
            }
            my_array[index] = temp;
        }
    }

    4.希尔排序


      先分组,再对每组进行插入排序。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分为一组,算法便终止;

      

    void shell_sort(int* my_array, int len)
    {
        // 步长
        int gap = len;
        while (gap > 1) {
            // 步长递减公式,此步长下的希尔排序效率最高
            // 直到步长等于1
            gap = gap / 3 + 1;
            // 分组,对每一组进行插入排序
            for (int i = 0; i < gap; ++i) {
                // 插入排序
                int temp = 0;
                int index = 0;
                // 无序序列
                for (int j = i + gap; j < len; j += gap) {
                    temp = my_array[j];
                    index = j;
                    // 有序序列(从后往前遍历)
                    for (int k = j - gap; k >= 0; k -= gap) {
                        if (temp < my_array[k]) {
                            // 元素后移
                            my_array[k + gap] = my_array[k];
                            index = k;
                        }
                        else break;
                    }
                    my_array[index] = temp;// 填坑
                }
            }
        }
    }

    5.快速排序

      快速排序 = 挖坑填数 + 分治法

      分治法的思想:

        1.先从数列中取出一个数作为基准数

        2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边

        3.再对左右区间重复第二步,直到各区间只有一个数

    // 快速排序
    void fast_sort(int* my_array, int left, int right)
    {
        if (left >= right)
            return;
        int index = left, temp = 0;
        int i = left, j = right;
        temp = my_array[left];//基准位置
        while ( i < j ) {
            if (i == index) {
                if (my_array[j] < temp) {
                    my_array[index] = my_array[j];
                    index = j;
                    ++i;
                }
                else --j;
            }
            if (j == index && i != j) {
                if (my_array[i] > temp) {
                    my_array[index] = my_array[i];
                    index = i;
                    --j;
                }
                else ++i;
            }
        }
        my_array[i] = temp;
        fast_sort(my_array, left, i -1);
        fast_sort(my_array, i + 1, right);
        
    }
    void q_sort(int* my_array, int left, int right)
    {
        if (left >= right)
            return;
        int i = left;// 开始位置
        int j = right;// 最后一个元素的位置
        int temp = my_array[left];//基准数
        while (i < j) {
            // j位置的元素,大于基准数
            while (i < j && my_array[j] >= temp) {
                // j 前移
                --j;
            }
            if (i < j) {
                my_array[i] = my_array[j];// 填坑
                ++i;
            }
            // 移动i
            while (i < j && my_array[i] <= temp) {
                ++i;
            }
            if (i < j) {
                my_array[j] = my_array[i];
                --j;
            }
        }
        my_array[i] = temp;//填坑
        q_sort(my_array, left, i -1);
        q_sort(my_array, i + 1, right);
    }

    6.归并排序

      空间换时间的算法

      将两个或两个以上的有序序列合并成一个新的有序序列:

        有序序列V[1]...V[m]和V[m+1]...V[n] ===>V[1]...V[n]

    void merge_array(int a[], int first, int mid, int last, int temp[])
    {
        int i = first;// 第一个有序序列的开始下标
        int j = mid + 1;//第二个有序序列的开始下标
        int length = 0;
        // 开始合并
        while (i <= mid && j <= last) {
            // 找二者中比较小的数
            if (a[i] < a[j]) {
                temp[length] = a[i];
                ++i;
            }
            else {
                temp[length] = a[j];
                ++j;
            }
            ++length;
        }
        // 还剩下一个有序序列有元素
        while (i <= mid) {
            temp[length] = a[i];
            ++i;
            ++length;
        }
        while (j <= last) {
            temp[length++] = a[j++];
        }
        // 覆盖原来位置的无序序列
        for (int i = 0; i < length; ++i) {
            //找到原来的第一个有序序列的开始位置
            a[first + i] = temp[i];
        }
    }
    
    //归并排序
    void merge_sort(int a[], int first, int last, int temp[])
    {
        //递归结束条件
        if (first == last) {
            return;
        }
        // 从中间位置拆分
        int mid = (first + last) / 2;
        //拆分
        //左半边
        merge_sort(a, first, mid, temp);
        //右半边
        merge_sort(a, mid + 1, last, temp);
        //合并两个有序序列
        merge_array(a, first, mid, last, temp);
    }
    
    void my_print_array(int* my_array, int len)
    {
        for (int i = 0; i < len; ++i) {
            printf("%5d", my_array[i]);
        }
        printf("
    ");
    }
    
    int main()
    {
        int my_array[] = {10, 6, 7, 4, 9, 8, 5, 1, 3, 2};
        int len = sizeof(my_array) / sizeof(int);
        int* temp = (int*)malloc(sizeof(my_array));
        merge_sort(my_array, 0, len -1, temp);
        free(temp);
        my_print_array(my_array, len);
    
        system("pause");
        return 0;
    }

    7.堆排序

    构建一个堆(构建一个完全二叉树——存到数组中):

      1>大顶堆——根节点大于两个子节点(降序排列)

      2>小顶堆——根节点小于两个子节点(升序排列)

    操作:

      根节点-1

      左子树2i(i是父节点的序号)

      右子树2i+1

    (未完待续......)

  • 相关阅读:
    数据库外键约束
    mysql查询数据
    操作mysql操作数据库
    自定义标签
    jstl标签
    getattibute 与 getparameter区别
    2017.3.2
    java中静态,抽象,接口,继承总结
    关于使用css伪类实现小图标
    动态生成的dom元素绑定事件
  • 原文地址:https://www.cnblogs.com/xiangtingshen/p/10349454.html
Copyright © 2011-2022 走看看