美文网首页
编程笔记(二)

编程笔记(二)

作者: 好之者不如乐之者 | 来源:发表于2018-02-28 20:19 被阅读0次

排序(二)

希尔排序(shell sort)

希尔排序是基于插入排序的基础上进行进一步的优化。
不过首先,我们要先解释一下为什么插入排序比较快。插入排序之所以快是因为它能适可而止,即在a[j] > a[j-1]时,不像冒泡与选择那样,每次都要重排一遍。

下面是希尔排序的写法:

    int gap = 1;
    while (gap < len/3)
        gap = gap*3 + 1;

    while (gap) {
        for (int i = gap; i < len; i++) {
            for (int j = i; j >= gap && a[j] < a[j-gap]; j -= gap) {
                int temp = a[j];
                a[j] = a[j-gap];
                a[j-gap] = temp;
            }   
        }   
        gap /= 3;
    }   

希尔排序的原理就是跳着找。而这样找之所以能比插入排序快的原因是:说不定有时候新加的数前面有许多比它大的数,一个一个找就会比较慢了,此时跳着找就可以避免许多次无用功的循环了。

归并排序 (merge sort)

归并排序的时间复杂度与快速排序一样。
而归并排序使用的原理是先将数组a从中间一个地方截开,使截出的两个部分个数相差不超过一,直到将整个数组a截成一个一个数,再进行排序、合并的循环。
而其排序时的原理是这样的:
比较两个未合并小数组(这两个小数组都已经分别排好序了)的首个,再把大的那个与另一数组中的第二个比较,以此类推。而每次都把小的那一个放入一个临时数组中去,最后把临时数组中的内容全都memcpy到原数组中。
其实现代码如下:

#include <cstring>

int merge_temp[maxn];

void merge(int a[], int start, int end)
{
    int middle = (start + end) / 2;
    int i = start, j = middle, k = start;
    while (i != middle && j != end) {
        merge_temp[k++] = a[i] < a[j] ? a[i++] : a[j++];
    }

    for (int m = j; m < end; m++, k++) {
        merge_temp[k] = a[m];
    }   
    for (int m = i; m < middle; m++, k++) {
        merge_temp[k] = a[m];
    }   
    memcpy(&a[start], &merge_temp[start], sizeof(int)*(end - start));
}

void merge_sort(int a[], int start, int end)
{
    if (start + 1 == end)
        return;

    int middle = (start + end)/2;
    merge_sort(a, start, middle);
    merge_sort(a, middle, end);
    merge(a, start, end);
}

不过,这个归并排序是有一点缺陷的。因为它要使用一个临时数组,而在很多时候,内存容量是有限的,所以给的数不能太多,而数少的话,那些简单的冒泡选择排序也能实现(并不会超时)。所以归并排序适用于数组中数的数量中等时使用。

快速排序 (quick sort)

快速排序的原理是先在数组中找一个基准数,再把数组分为比基准数大的数与比基准数小的数两个部分,再对这两个数组分别进行以上操作。而快速排序唯一的问题就在于如何找出一个很标准的基准数,但是并没有一个固定的方法可以找到,所以笔者就每次都以最后一个为基准数了。
其实现代码如下:

void quick_sort(int a[], int s, int e)
{
    if (s + 1 == e)
        return;

//  printf("s: %d, e: %d\n", s, e);
    int middle = s;
    for (int i = s; i < e; i++) {
        if (a[i] <= a[e-1]) {
            if (middle != i) {
                int temp = a[middle];
                a[middle] = a[i];
                a[i] = temp;
            }
//          printf("i: %d, ini: %d, a[i]: %d, a[ini]: %d\n", i, middle, a[i], a[initial]);
            middle++;
        }
    }

    if (middle == e) {
        quick_sort(a, s, e-1);
    } else {
        quick_sort(a, middle, e);
        quick_sort(a, s, middle);
    }
}

void sort_data(int a[], int len)
{
    quick_sort(a, 0, len);
}

计数排序(counting sort)
计数排序是所有排序中最快的,因为它只要把整个数组浏览几遍就可以排好序了。
计数排序的原理是把同一类的数放在一起。举一个例子,一道题要求输入-500000~500000 中的数,那么可以把所有-500000放在一起,所有-499999放在一起,以此类推。但是要是范围太大了,计数排序就没有任何优势了。
其代码如下:

#include <cstring>

int counting[1000001];

void sort_data(int a[], int len)
{
    memset(counting, 0, sizeof(counting));
    for (int i = 0; i < len; i++) {
        counting[a[i]+500000]++;
    }
    int j = 0;
    for (int i = 0; i < 1000001; i++) {
        while (counting[i] != 0) {
            a[j] = i - 500000;
            j++;
            counting[i]--;
        }
    }
}

相关文章

  • 编程笔记(二)

    排序(二) 希尔排序(shell sort) 希尔排序是基于插入排序的基础上进行进一步的优化。不过首先,我们要先解...

  • Java编程的逻辑

    零 概述 本篇文章是读《Java编程逻辑》的笔记 第一部分 编程基础与二进制 第1章 编程基础 为了操作数据方便,...

  • 大师兄的Python学习笔记(十六): FTP与ftplib

    大师兄的Python学习笔记(十五): Socket编程大师兄的Python学习笔记(十七): Mail编程 一、...

  • 2.25python笔记 高阶编程

    @[TOC](2.25学堂在线python学习笔记 高阶编程) # 高阶编程 1. 利用二分法查找一个字符是否在某...

  • 2.24学堂在线python学习笔记 高阶编程

    @[TOC](2.24学堂在线python学习笔记 高阶编程) # 重要笔记 1. 利用二分搜索法来查找一个字符是...

  • 关于我的二手笔记本

    要买一个二手笔记本,准备给日后编程用的。 因为考虑到日后有编程的需求,然后就买了个Pro,价格也会高一点。这笔记本...

  • 2018-09-21

    java学习笔记(二) 前一篇简单的介绍了Java8函数式编程,这篇还将继续函数式编程之旅。 流 在Java程序中...

  • 别人的笔记

    在简书上看别人的笔记,发现一些好东西,记录一下。 新生大学JavaScript编程入门学习笔记 之一,之二,之三,...

  • 全栈工程师第二天学习笔记

    全栈工程师第二天学习笔记 指令式编程原理 指令式编程是计算机根据指令执行,我们得任何编程语言都可以看作是一种指令,...

  • Android编程权威指南(第二版)学习笔记(六)—— 第6章

    title: Android编程权威指南(第二版)学习笔记(六)—— 第6章 Android SDK 版本与兼容d...

网友评论

      本文标题:编程笔记(二)

      本文链接:https://www.haomeiwen.com/subject/ojeixftx.html