冒泡,选择,快排,归并,堆排序算法

一、各算法的时间复杂度
①平均时间复杂度
插入排序 O(n^2),冒泡排序 O(n^2),选择排序 O(n^2)

快速排序 O(n log n),堆排序 O(n log n),归并排序 O(n log n),基数排序 O(n),希尔排序 O(n^1.25)

②算法稳定性

选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法;
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。

##################

 

经典排序算法 – 插入排序Insertion sort  
插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。 
插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序,折半插入排序留到“查找”内容中进行。 

  图1演示了对4个元素进行直接插入排序的过程,共需要(a),(b),(c)三次插入。

Image(6)

##################

 

二、各算法的实现

 

 

/***************************************************************************
 * 
 * Copyright (c) 2015 Baidu.com, Inc. All Rights Reserved
 * 
 **************************************************************************/
 
#include <stdio.h>
#include <stdlib.h>
#include <new>

using namespace std;

template <class T>
void swap(T* a, T* b) {
    T temp = *a;
    *a = *b;
    *b = temp;
}

// 冒泡排序
void bubble_sort(int* v, const int& len) {
    if (v == NULL || len <= 0) {
        return ;
    }
    int i;
    int j;
    for (i = 0; i < len - 1; ++i) {
        for (j = 0; j < len - i - 1; ++j) {
            if (v[j] > v[j + 1]) {
                swap<int>(&v[j], &v[j + 1]);
            }
        }
    }
}

// 选择排序
void select_sort(int* v, const int& len) {
    if (v == NULL || len <= 0) {
        return ;
    }
    int i;
    int j;
    for (i = 0; i < len - 1; ++i) {
        for (j = i + 1; j < len; ++j) {
            if (v[i] > v[j]) {
                swap<int>(&v[i], &v[j]);
            }
        }
    }
}

// 优化选择排序
void select_sort_better(int* v, const int& len) {
    if (v == NULL || len <= 0) {
        return ;
    }
    int i;
    int j;
    int k;
    for (i = 0 ; i < len - 1; ++i) {
        k = i;
        for (j = i + 1; j < len; ++j) {
            if (v[i] > v[j]) {
                k = j;
            }
        }
        if (k != i) {
            swap<int>(&v[i], &v[k]);        
        }
    }
}

// 快速排序 
int partition(int*v, const int& low, const int& high) {
    int i = low;
    int j = high;
    const int pivot = v[i];
    while (i < j) {
        while (i < j && pivot <= v[j]) {
            --j;
        }
        if (i < j) {
            v[i++] = v[j];
        }
        while (i < j && pivot >= v[i]) {
            ++i;
        }
        if (i < j) {
            v[j--] = v[i];
        }
    }
    v[i] = pivot;
    return i;
}

void quick_sort(int* v, const int& low, const int& high) {
    if (v == NULL || low < 0 || high <= 0) {
        return ;
    }
    if (low < high) {
        int pos = partition(v, low, high);
        quick_sort(v, 0, pos - 1);
        quick_sort(v, pos + 1, high);
    }
}

// 插入排序
void insert_sort(int *v, const int& len) {
    if (v == NULL || len <= 0 ) {
        return ;
    }
    int i;
    int j;
    int temp;
    for (i = 1; i < len; ++i) {
        temp = v[i];
        for (j = i; j > 0 && temp < v[j - 1]; --j) {
            v[j] = v[j -1];
        }
        v[j] = temp;
    }
}

// 归并排序 
void merge(int* v, const int& low, const int& mid, const int& high) {
    int i = low;
    int j = mid + 1;
    // 小数据测试,不用判断是否分配成功。现实产品线必需判断是否分配成功
    int* buff = new (std::nothrow) int[high - low + 1];
    if (buff == NULL) {
        printf("fail to allocate buff memory");
        exit(-1);
    }
    int index = 0;
    while (i <= mid && j <= high) {
        if (v[i] <= v[j]) {
            buff[index] = v[i++];
        } else {
            buff[index] = v[j++];
        }
        ++index;
    }
    while (i <= mid) {
        buff[index++] = v[i++];
    }
    while (j <= high) {
        buff[index++] = v[j++];
    }
    // 写回原数组
    for (i = low; i <= high; ++i) {
       v[i] = buff[i - low];
    }
    delete []buff;
    buff = NULL;

}

void merge_sort(int* v, const int& low, const int& high) {
    if (v == NULL || low < 0 || high <= 0) {
        return ;
    }
    if (low < high) {
        // mid = low + (high - low) >> 1
        // 错误!栈溢出导致无穷循环
        const int mid = low + ((high - low) >> 1);
        merge_sort(v, low, mid);
        merge_sort(v, mid + 1, high);
        merge(v, low, mid, high);
    }
}

// 希尔排序
void shell_sort(int* v, const int& len) {
    if (v == NULL || len <= 0) {
        return ;
    }
    int i;
    int j;
    int div;
    int temp;
    for (div = len / 2; div >= 1; div /= 2) {
        for (i = div; i < len; ++i) {
            temp = v[i];
            for (j = i - div; j >= 0 && temp < v[j]; j -= div) {
                v[j + div] = v[j]; 
            }
            v[j + div] = temp;
        }
    }
}


int main() {
    int v[] = {1,3,5,7,9,0,8,6,4,2};
    const int len = sizeof(v) / sizeof(int);
    // bubble_sort(v, len);
    // select_sort(v, len);
    // quick_sort(v, 0, len - 1);
    // insert_sort(v, len);
    // merge_sort(v, 0, len - 1);
    shell_sort(v, len);    
    for (int i = 0; i < len; ++i) {
        printf("%d ", v[i]);
    }
    return 0;
}

/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值