目录
插入排序
---------------------
依次类推,当前元素与前面的元素一一对比
template<typename T>
void insertionSort1(T arr[], int n){
for (int i = 0; i < n; ++i) {
if(arr[i] < arr[i+1])
{
std::swap(arr[i], arr[i+1]);
if (i>=2)
{
for(int j = i-1; j > 0, i > 0; --j,--i)
{
if (arr[j] < arr[i])
{
std::swap(arr[j], arr[i]);
}
}
}
}
}
}
template<typename T>
void insertionSort2(T arr[], int n){
for (int i = 1; i < n; ++i) {
for (int j = i; j > 0 ; --j) {
if (arr[j] > arr[j-1])
std::swap(arr[j], arr[j-1]);
}
}
}
template<typename T>
void insertionSort3(T arr[], int n){
for (int i = 1; i < n; ++i) {
for (int j = i; j > 0 && (arr[j] > arr[j-1]); --j)
//可以提前结束程序通过比较,如果数据有一定的顺序则会更快
{
std::swap(arr[j], arr[j-1]);
// swap操作需要三次赋值,会降低效率
}
}
}
swap操作需要三次赋值,会降低效率,可以改进
将当前元素复制一份,看其是否放在当前的位置,通过与其前面一个元素对比
把交换变成了比较之后的一次赋值
template<typename T>
void insertionSort4(T arr[], int n){
for (int i = 1; i < n; ++i) {
T temp = arr[i];
int j = 0; //保存元素temp应该放的位置
for ( j = i; j > 0 && (arr[j-1] < temp); --j)
{
arr[j] = arr[j-1];
}
arr[j] = temp;
}
}
SortTestHelper.h
//
// Created by 天人合一 on 2020/6/16.
//
#ifndef CLIONBUFFER_SORTTESTHELPER_H
#define CLIONBUFFER_SORTTESTHELPER_H
#include <iostream>
#include <ctime>
#include <cassert>
#include <string>
namespace SortTestHelper{
template<typename T>
void insertionSort1(T arr[], int n){
for (int i = 0; i < n; ++i) {
if(arr[i] < arr[i+1])
{
std::swap(arr[i], arr[i+1]);
if (i>=2)
{
for(int j = i-1; j > 0, i > 0; --j,--i)
{
if (arr[j] < arr[i])
{
std::swap(arr[j], arr[i]);
}
}
}
}
}
}
template<typename T>
void insertionSort2(T arr[], int n){
for (int i = 1; i < n; ++i) {
for (int j = i; j > 0 ; --j) {
if (arr[j] > arr[j-1])
std::swap(arr[j], arr[j-1]);
}
}
}
template<typename T>
void insertionSort3(T arr[], int n){
for (int i = 1; i < n; ++i) {
for (int j = i; j > 0 && (arr[j] > arr[j-1]); --j)
//可以提前结束程序通过比较,如果数据有一定的顺序则会更快
{
std::swap(arr[j], arr[j-1]);
// swap操作需要三次赋值,会降低效率
}
}
}
template<typename T>
void insertionSort4(T arr[], int n){
for (int i = 1; i < n; ++i) {
T temp = arr[i];
int j = 0;
for ( j = i; j > 0 && (arr[j-1] < temp); --j)
{
arr[j] = arr[j-1];
}
arr[j] = temp;
}
}
template<typename T>
bool isSort(T arr[], int n)
{
for (int i = 0; i < n; ++i) {
assert(arr[i] >= arr[i+1]);
return true;
}
}
template<typename T>
bool isSorted(T arr[], int n)
{
for (int i = 0; i < n - 1; ++i) {
if (arr[i] < arr[i+1])
return false;
return true;
}
}
// 返回的创建的数组
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
int* generateRandomArray(int n, int rangeL, int rangeR){
assert( rangeL <= rangeR);
int* arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; ++i) {
// rand()%(rangeR-rangeL+1)表示0到rangeR-rangeL区间的随机数
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
}
return arr;
}
// 生成一个近乎有顺的数组
int *generateNearlyOrderedArray(int n, int swapTimes){
// 先生成一个有顺的数组
int *arr = new int[n];
// for(int i = 0 ; i < n ; i ++ )
for(int i = n-1 ; i >= 0 ; i -- )
arr[i] = n - i;
//再随机的根据自己的需要交换一些数据的顺序
srand(time(NULL));
for( int i = 0 ; i < swapTimes ; i ++ ){
int posx = rand()%n;
int posy = rand()%n;
std::swap( arr[posx] , arr[posy] );
}
return arr;
}
template<typename T>
void selectionSort4(T array[], int n)
{
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if(array[i] < array[j])
{
swap( array[i], array[j]);
}
}
}
}
template <typename T>
void print_array(T array[], int n)
{
for (int i = 0; i < n; ++i)
{
cout << array[i] << " ";
}
cout << endl;
}
template<typename T>
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
template<typename T>
void testSort(const std::string &sortName, void (*sort)(T[], int), T arr[], int n ){
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
assert(isSorted(arr, n));
std::cout << sortName << " : " << double(endTime-startTime) / CLOCKS_PER_SEC << " s " << std::endl;
}
// 数组的copy
int* arrayCopy(int* T, int n)
{
int* arr = new int[n];
std::copy(T, T + n, arr);
return arr;
}
}
#endif //CLIONBUFFER_SORTTESTHELPER_H
main.cpp
#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"
using namespace std;
int main0() {
// 1 整形数组测试
int num = 10;
int* intarr = SortTestHelper::generateRandomArray(num, 2, 100);
// printf("----------------int: sort before ----------------\n");
// SortTestHelper::print_array(intarr, num);
//
//
//
SortTestHelper::selectionSort4(intarr, num);
SortTestHelper::insertionSort1(intarr,num);
// SortTestHelper::insertionSort3(intarr,num);
//
// printf("----------------int: sort after ----------------\n");
// SortTestHelper::print_array(intarr, num);
//插入排序因为先进行两两元素的对比,再交换使得效率更高
int n = 10000;
int *arr = SortTestHelper::generateRandomArray(n,0,n);
int *arrInsert = SortTestHelper::arrayCopy(arr, n);
int *arrImproved = SortTestHelper::arrayCopy(arr, n);
SortTestHelper::testSort("Selection Sort", SortTestHelper::selectionSort4, arr, n);
// SortTestHelper::printArray(arr, n);
SortTestHelper::testSort("insertion sort swap", SortTestHelper::insertionSort3, arrInsert, n);
SortTestHelper::testSort("insertion sort improved", SortTestHelper::insertionSort4, arrImproved, n);
// SortTestHelper::print_array(arr, n);
// for (int i = 0; i < 50; ++i) {
// num += i;
// int* testArr = SortTestHelper::generateRandomArray(num, 2, 100);
// SortTestHelper::insertionSort(testArr, num);
//
// if (SortTestHelper::isSort(intarr, num))
// cout << "-------------------Good--------------" << endl;
// }
delete [] intarr;
delete [] arr;
delete [] arrInsert;
delete [] arrImproved;
return 0;
}
int main() {
//插入排序因为先进行两两元素的对比,再交换使得效率更高
//要排序的数据接近有顺时插入排序效率会很高,两者区别明显
int n = 100000;
int *arr = SortTestHelper::generateNearlyOrderedArray(n,1);
// SortTestHelper::printArray(arr, n);
int *arrInsert = SortTestHelper::arrayCopy(arr, n);
int *arrImproved = SortTestHelper::arrayCopy(arr, n);
SortTestHelper::testSort("Selection Sort", SortTestHelper::selectionSort4, arr, n);
// SortTestHelper::printArray(arr, n);
SortTestHelper::testSort("insertion sort swap", SortTestHelper::insertionSort3, arrInsert, n);
// SortTestHelper::printArray(arr, n);
SortTestHelper::testSort("insertion sort improved", SortTestHelper::insertionSort4, arrImproved, n);
// SortTestHelper::printArray(arr, n);
delete [] arr;
delete [] arrInsert;
delete [] arrImproved;
return 0;
}
SortTestHelper.h
//
// Created by liuyubobobo on 7/13/16.
//
#ifndef INC_04_INSERTION_SORT_SORTTESTHELPER_H
#define INC_04_INSERTION_SORT_SORTTESTHELPER_H
#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cassert>
using namespace std;
namespace SortTestHelper {
int *generateRandomArray(int n, int range_l, int range_r) {
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (range_r - range_l + 1) + range_l;
return arr;
}
int *generateNearlyOrderedArray(int n, int swapTimes){
int *arr = new int[n];
for(int i = 0 ; i < n ; i ++ )
arr[i] = i;
srand(time(NULL));
for( int i = 0 ; i < swapTimes ; i ++ ){
int posx = rand()%n;
int posy = rand()%n;
swap( arr[posx] , arr[posy] );
}
return arr;
}
int *copyIntArray(int a[], int n){
int *arr = new int[n];
copy(a, a+n, arr);
return arr;
}
template<typename T>
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
template<typename T>
bool isSorted(T arr[], int n) {
for (int i = 0; i < n - 1; i++)
if (arr[i] > arr[i + 1])
return false;
return true;
}
template<typename T>
void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl;
assert(isSorted(arr, n));
return;
}
};
#endif //INC_04_INSERTION_SORT_SORTTESTHELPER_H
#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"
using namespace std;
template<typename T>
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
// 寻找元素arr[i]合适的插入位置
// 写法1
// for( int j = i ; j > 0 ; j-- )
// if( arr[j] < arr[j-1] )
// swap( arr[j] , arr[j-1] );
// else
// break;
// 写法2
for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
swap( arr[j] , arr[j-1] );
}
return;
}
int main() {
int n = 10000;
cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
int *arr2 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Insertion Sort", insertionSort,arr1,n);
SortTestHelper::testSort("Selection Sort", selectionSort,arr2,n);
delete[] arr1;
delete[] arr2;
cout<<endl;
return 0;
}
进一步思想
//A:输入数组,len:数组长度
void insertSort(int A[],int len)
{
int temp;
for(int i=1;i<len;i++)
{
int j=i-1;
temp=A[i];
//查找到要插入的位置
while(j>=0&&A[j]>temp)
{
A[j+1]=A[j];
j--;
}
// if(j!=i-1)
A[j+1]=temp;
}
}
//A:输入数组,len:数组长度
void insertSort1(int A[],int len)
{
int temp;
for(int i=1;i<len;i++)
{
int j=i;
temp=A[i];
//查找到要插入的位置
while( j>=1 && A[j-1] > temp )
{
A[j] = A[j-1];
j--;
}
A[j] = temp;
}
}
int main(){
int num = 100;
int* intarr = SortTestHelper::generateRandomArray(num, 2, 100);
insertSort1(intarr,num);
bool door = SortTestHelper::isSorted(intarr,num);
if(!door)
cout << "惊起却回头,有恨无人省。" << endl;
else
cout << "从此小舟逝,江海寄余生!" << endl;
// SortTestHelper::printArray(intarr, num);
return 0;
}
Bubble-Sort
InsertionSort.h
//
// Created by liuyubobobo on 7/15/16.
//
#ifndef OPTIONAL_01_BUBBLE_SORT_INSERTIONSORT_H
#define OPTIONAL_01_BUBBLE_SORT_INSERTIONSORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
T e = arr[i];
int j;
for (j = i; j > 0 && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
#endif //OPTIONAL_01_BUBBLE_SORT_INSERTIONSORT_H
SelectionSort.h
//
// Created by liuyubobobo on 7/15/16.
//
#ifndef OPTIONAL_01_BUBBLE_SORT_SELECTIONSORT_H
#define OPTIONAL_01_BUBBLE_SORT_SELECTIONSORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
#endif //OPTIONAL_01_BUBBLE_SORT_SELECTIONSORT_H
main.cpp
#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"
#include "SelectionSort.h"
#include "InsertionSort.h"
using namespace std;
template<typename T>
void bubbleSort( T arr[] , int n){
bool swapped;
//int newn; // 理论上,可以使用newn进行优化,但实际优化效果较差
do{
swapped = false;
//newn = 0;
for( int i = 1 ; i < n ; i ++ )
if( arr[i-1] > arr[i] ){
swap( arr[i-1] , arr[i] );
swapped = true;
// 可以记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑
// 实际优化效果较差,因为引入了newn这个新的变量
//newn = n;
}
//n = newn;
// 优化,每一趟Bubble Sort都将最大的元素放在了最后的位置
// 所以下一次排序,最后的元素可以不再考虑
// 理论上,newn的优化是这个优化的复杂版本,应该更有效
// 实测,使用这种简单优化,时间性能更好
n --;
}while(swapped);
}
int main() {
int n = 10000;
// Test for Random Array
cout<<"Test for Random Array, size = "<<n<<", randome range [0, "<<n<<"]"<<endl;
int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
int *arr2 = SortTestHelper::copyIntArray(arr1, n);
int *arr3 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
cout<<endl;
// Test for Random Nearly Ordered Array
int swapTimes = 100;
cout<<"Test for Random Nearly Ordered Array, size = "<<n<<", swap time = "<<swapTimes<<endl;
arr1 = SortTestHelper::generateNearlyOrderedArray(n, swapTimes);
arr2 = SortTestHelper::copyIntArray(arr1, n);
arr3 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
return 0;
}
Shell-Sort
BubbleSort.h
//
// Created by liuyubobobo on 7/15/16.
//
#ifndef OPTIONAL_02_SHELL_SORT_BUBBLESORT_H
#define OPTIONAL_02_SHELL_SORT_BUBBLESORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void bubbleSort( T arr[] , int n){
bool swapped;
do{
swapped = false;
for( int i = 1 ; i < n ; i ++ )
if( arr[i-1] > arr[i] ){
swap( arr[i-1] , arr[i] );
swapped = true;
}
n --;
}while(swapped);
}
#endif //OPTIONAL_02_SHELL_SORT_BUBBLESORT_H
InsertionSort.h
//
// Created by liuyubobobo on 7/15/16.
//
#ifndef OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H
#define OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
T e = arr[i];
int j;
for (j = i; j > 0 && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
#endif //OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H
SelectionSort.h
//
// Created by liuyubobobo on 7/15/16.
//
#ifndef OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H
#define OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
#endif //OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H
main.cpp
#include <iostream>
#include "SortTestHelper.h"
#include "SelectionSort.h"
#include "InsertionSort.h"
#include "BubbleSort.h"
using namespace std;
template<typename T>
void shellSort(T arr[], int n){
int h = 1;
while( h < n/3 )
h = 3 * h + 1;
// 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
while( h >= 1 ){
// h-sort the array
for( int i = h ; i < n ; i ++ ){
// 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序
T e = arr[i];
int j;
for( j = i ; j >= h && e < arr[j-h] ; j -= h )
arr[j] = arr[j-h];
arr[j] = e;
}
h /= 3;
}
}
int main() {
int n = 10000;
// Test for Random Array
cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
int *arr2 = SortTestHelper::copyIntArray(arr1, n);
int *arr3 = SortTestHelper::copyIntArray(arr1, n);
int *arr4 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);
SortTestHelper::testSort("Shell Sort", shellSort, arr4, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
delete[] arr4;
cout<<endl;
// Test for Random Nearly Ordered Array
int swapTimes = 100;
cout<<"Test for Random Nearly Ordered Array, size = "<<n<<", swap time = "<<swapTimes<<endl;
arr1 = SortTestHelper::generateNearlyOrderedArray(n, swapTimes);
arr2 = SortTestHelper::copyIntArray(arr1, n);
arr3 = SortTestHelper::copyIntArray(arr1, n);
arr4 = SortTestHelper::copyIntArray(arr1, n);
SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);
SortTestHelper::testSort("Shell Sort", shellSort, arr4, n);
delete[] arr1;
delete[] arr2;
delete[] arr3;
delete[] arr4;
return 0;
}
其它可以参考相关博客
八种经典内部排序算法
八种排序算法以及Java代码的实现
剖析八种经典排序算法
十个常用排序算法python3实现
C/C++八种排序算法原理及实现