关于排序算法小结
//插入排序
void InserSort(int arr[], int len)
{
int temp;
int i, j;
for(i = 1;i < len;i++)
{
temp = arr[i];
for(j = i - 1;j >= 0 && arr[j] > temp;j--)
{
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
}
}
插入排序将数组中的一个元素拿出来,然后将它和它前面的元素进行比较,如果不等则调整顺序
代码空间复杂度O(1)
代码时间复杂度:
最好情况:O(n)
最坏情况:O(n^2)
平均情况:O(n^2)
算法稳定
//二分插入排序
//二分插入排序
void BinaryInsertSort(int arr[], int len)
{
for(int i = 1; i < len; i++)
{
int get = arr[i];//拿到新牌
int left = 0;//左边的手牌已经排好序
int right = i - 1;//从右边开始
while(left <= right)//采用二分法定位新牌的位置
{
int mid = ((right - left) >> 1) + left;
if(arr[mid] > get)
right = mid - 1;
else
left = mid + 1;
}
for(int j = i - 1; j >= left; j--)
{
arr[j + 1] = arr[j];
}
arr[left] = get;
}
}
代码空间复杂度O(1)
代码时间复杂度:
最好情况:O(nlogn)
最坏情况:O(n^2)
平均情况:O(n^2)
算法稳定
//希尔排序
void Shell(int arr[],int len, int dk)
{
int temp;
int i,j;
for(i = dk;i < len;i++)
{
temp = arr[i];
for(j = i - dk;j >= 0 && arr[j] > temp; j -= dk)
{
arr[j + dk] = arr[j];
}
arr[j + dk] = temp;
}
}
void ShellSort(int arr[],int len,int dk[],int dk_len)
{
for(int i = 0;i < dk_len;i++)
{
Shell(arr,len,dk[i]);
}
}
希尔排序是一种优化的插入排序,它引入了一种步长的概念,在步长为1时候,它就是一个插入排序
另外,希尔排序的步长最好选择素数,避免元素比较重复,并且步长最终需要变为1
算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(n)
最坏情况下:O(n^2)
平均情况下:O(n^2)
算法不稳定
//冒泡排序
void BubbleSort(int arr[], int len)
{
int temp,flag = 0;
for(int i = 0; i < len - 1; ++i)
{
flag = 0;
for(int j = 0; j < len - 1; ++j)
{
if(arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 1;
}
}
if(flag == 0)
{
break;
}
}
}
算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(n)
最坏情况下:O(n^2)
平均情况下:O(n^2)
算法稳定
//定向冒泡排序
//鸡尾酒排序,前到后后到前
void CocktailSort(int arr[], int len)
{
int left = 0;
int right = len - 1;
while(left < right)
{
for(int i = left; i < right; ++i)//第一轮找出一个最大的
{
if(arr[i + 1] < arr[i])
{
Swap(arr[i + 1], arr[i]);
}
}
right--;
for(int i = right; i > left; i--)//第二轮找一个最小的
{
if(arr[i - 1] > arr[i])
{
Swap(arr[i - 1], arr[i]);
}
}
left++;
}
}
算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(n)
最坏情况下:O(n^2)
平均情况下:O(n^2)
算法稳定
//选择排序
void SelectSort(int arr[], int len)
{
int min_index;
int tmp;
for(int i = 0; i < len - 1; i++)
{
min_index = i;
for(int j = i + 1; j < len; j++)
{
if(arr[min_index] > arr[j])
{
min_index = j;
}
}
if(arr[min_index] < arr[i])
{
tmp = arr[i];
arr[i] = arr[min_index];
arr[min_index] = tmp;
}
}
}
算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(n^2)
最坏情况下:O(n^2)
平均情况下:O(n^2)
算法不稳定
//堆排序
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void HeapAdjust2(int arr[], int i, int len)
{
int lr = 2 * i + 1;
int lc = 2 * i;
if(lc > len)
{
return;
}
if(i * 2 + 1> len)
{
lr = lc;
}
(arr[i] > arr[lc])?((arr[i] > arr[lr])?NULL:swap(arr[i], arr[lr]),HeapAdjust(arr,lr,len)):((arr[lc] > arr[lr])?swap(arr[i], arr[lc]), HeapAdjust(arr, lc, len):swap(arr[i], arr[lr]),HeapAdjust(arr, lr, len));
}
void HeapAdjust(int arr[], int i,int len)
{
int temp;
for(int j = i * 2; j <= len; j *= 2)
{
if(j < len && arr[j] < arr[j + 1])
{
j++;
}
//j出来时是左右子树最大值的下标
if(arr[j] <= arr[i])
{
break;
}
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i = j;
}
}
void HeapSort(int arr[], int len)
{
int temp;
//建堆
for(int i = len / 2; i > 0; --i)
{
HeapAdjust(arr, i, len);
}
//排序
for(int i = len; i > 0; --i)
{
temp = arr[i];
arr[i] = arr[1];
arr[i] = temp;
HeapAdjust(arr, 1, i - 1);
}
}
算法空间复杂度:O(1)
算法时间复杂度:
最好情况下:O(nlogn)
最坏情况下:O(nlogn)
平均情况下:O(nlogn)
算法不稳定
//计数排序
//计数排序
#define Max 100
int c[Max];
void CountingSort(int arr[], int len)
{
//填充c数组
memset(c, 0, sizeof(int)* Max);
for(int i = 0; i < len; ++i)
{
c[arr[i]]++;
}
//调整c数组
for(int i = 1; i < Max; ++i)
{
c[i] += c[i - 1];
}
int *b = (int *)malloc(sizeof(int) * len);
for(int i = len - 1; i >= 0; --i)//从后往前扫保证计数的稳定性
{
b[--c[arr[i]]] = arr[i];
}
memmove(arr, b, sizeof(int)* len);
delete[] b;
}
算法空间复杂度:O(n+k)
算法时间复杂度:
最好情况下:O(n+k)
最坏情况下:O(n+k)
平均情况下:O(n+k)
算法稳定
//基数排序
#define SIZE 10
// 返回number第digit位数字
inline int GetDigit(int num, int digit)
{
for(int i = 0; i < digit; i++)
{
num /= 10;
}
return num % 10;
}
// 根据元素的第dig位来进行计数排序
void Radix(int arr[], int len, int dig)
{
int bucket[10][SIZE] = {0};
int count[10] = {0};
for(int i = 0; i < len; i++)
{
int fig_num = GetDigit(arr[i], dig);
bucket[fig_num][count[fig_num]] = arr[i];
count[fig_num]++;
}
int k = 0;
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < count[i]; j++)
{
arr[k++] = bucket[i][j];
}
}
}
inline int FindMaxDigit(int arr[], int len)
{
int max = arr[0];
for(int i = 1; i < len; i++)
{
if(max < arr[i])
{
max = arr[i];
}
}
return log10(max) + 1;
}
void RadixSort(int arr[], int len)
{
for(int i = 0; i < FindMaxDigit(arr, len); i++)
{
Radix(arr, len, i);
}
}
基数排序可以建桶用个队列,这里用的数组有点浪费空间
算法空间复杂度:O(桶数*桶长度+数组长度)
算法时间复杂度:
最好情况下:O(数组长度) //(最好情况下最大数字位数为1)
最坏情况下:O(数组长度 + 数组中最大数的位数 X (数组长度 X 数组最大位数))
平均情况下:O(数组长度 + 数组中最大数的位数 X (数组长度 X 数组最大位数))
算法稳定
//归并排序
#include<iostream>
using namespace std;
template<class Type>
void Print2Array(Type s, int n, int m)
{
for(int i = 0;i<n;++i)
{
for(int j = 0;j<m;++j)
{
cout << setw(3) << s[i][j];
}
cout << endl;
}
cout << endl;
}
template<class Type>
void PrintArray(Type *ar, int n)
{
for(int i = 0;i<n;++i)
{
cout << ar[i] << " ";
}
cout << endl;
}
template<typename T>
void Copy(T *sd, T *si, int left, int right)
{
for(int i = left; i <= right; ++i)
{
sd[i] = si[i];
}
}
template<typename T>
void Merge(T *sd, T *si, int left, int m, int right)
{
int indexA = left;
int indexB = m + 1;
int k = left;
while(indexA <= m && indexB <= right)
{
sd[k++] = si[indexA] < si[indexB]?si[indexA++]:si[indexB++];
}
while(indexA <= m)
{
sd[k++] = si[indexA++];
}
while(indexB <= right)
{
sd[k++] = si[indexB++];
}
}
template<typename T>
void MSort(T *ar, T *br, int left, int right)
{
if(left < right)
{
int m = (right - left) / 2 + left;
MSort(ar, br, left, m);
MSort(ar, br, m + 1, right);
Merge(br, ar, left, m, right);
Copy(ar, br, left, right);
}
}
template<typename T>
void MergeSort(T *ar, int n)
{
if(ar != nullptr && n > 0)
{
T *br = new T[n];
MSort(ar, br, 0, n - 1);
delete[]br;
}
}
template<typename Ty>
void NiceMerge(Ty *ds, Ty si, int n, int size)
{
int i = 0;
for(; i + 2 * size <= n;i += 2 * size)
{
Merge(ds, si, i, i + size - 1, i + 2 * size - 1);
}
if(n - 1 > i + size)
{
Merge(ds, si, i, i + size - 1, n - 1);
}
else
{
for(int j = i; j < n; ++j)
{
ds[j] = si[j];
}
}
}
template<typename Ty>
void NiceMergeSort(Ty *ar, int len)
{
if(ar != nullptr && len > 0)
{
Ty *br = new Ty[len];
int s = 1;//每次递归的长度,开始是一个一个,到两个两个,到四个四个,二倍增长
while(s < len)
{
NiceMerge(br, ar, len, s);
s += s;
NiceMerge(ar, br, len, s);
s += s;
}
delete[] br;
}
}
int main()
{
int ar[] = {23,45,78,12,19,57,90,78};
int n = sizeof(ar) / sizeof(ar[0]);
PrintArray(ar, n);
//MergeSort(ar, n);
NiceMergeSort(ar, n);
PrintArray(ar, n);
return 0;
}
算法空间复杂度:O(n)
算法时间复杂度:
最好情况下:O(nlogn)
最坏情况下:O(nlogn)
平均情况下:O(nlogn)
算法稳定
好久没来填坑了,其实我今天也没法把这个填完。。。。。之后有时间继续吧,补上快排
**//快速排序**
-----
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//普通快排
//优化1:最坏情况 随机选取基准点值
//优化2:三分取中法
//优化3:数据量小时 用插排
//优化4:聚集优化 和基准点相同的数据剔除
void Swap(int arr[], int, int);
void findSecondMaxNumber(int arr[], int low,int mid, int high)
{
if (arr[mid] > arr[high])
{
Swap(arr, mid, high);
}
if (arr[low] < arr[mid])
{
Swap(arr, low, mid);
}
if (arr[low] > arr[high])
{
Swap(arr, low, high);
}
}
void Swap(int arr[], int fristIndex, int secondIndex)
{
int tmp = arr[fristIndex];
arr[fristIndex] = arr[secondIndex];
arr[secondIndex] = tmp;
}
void Gather(int arr[], int low, int bounIndex, int high, int *left, int *right)
{
if (low < high)
{
int count = bounIndex - 1;
for (int i = bounIndex - 1; i >= low; i--)
{
if (i != count && arr[i] == arr[bounIndex])
{
Swap(arr, count, i);
count--;
}
}
*left = count;
count = bounIndex + 1;
for (int i = bounIndex + 1; i <= high; i++)
{
if (i != count && arr[i] == arr[bounIndex])
{
Swap(arr, count, i);
count++;
}
}
*right = count;
}
}
int Parition(int arr[], int low, int high)
{
int tmp = arr[low];
while (low < high)
{
//1 2 3 4 5 6
while (low < high && arr[high] >= tmp)high--;
arr[low] = arr[high];
while (low < high && arr[low] <= tmp)low++;
arr[high] = arr[low];
}
arr[low] = tmp;
return low;
}
void InsertSort(int arr[], int low,int high);
void QSort(int arr[], int low, int high)
{
if (low < high)
{
//if (high - low + 1 < 20)
//{
// InsertSort(arr, low, high);
// return;
//}
//Swap(arr, low, rand() % (high - low)+low);
//findSecondMaxNumber(arr, low, (high-low)/2+low, high);
int boundKey = Parition(arr, low, high);
int left = boundKey - 1;
int right = boundKey + 1;
Gather(arr, low, boundKey, high, &left, &right);
QSort(arr, low, left);
QSort(arr, right, high);
//QSort(arr, low, boundKey - 1);
//QSort(arr, boundKey + 1, high);
}
}
void QuickSort(int arr[], int len)
{
QSort(arr, 0, len - 1);
}
算法空间复杂度:O(logn)
算法时间复杂度:
最好情况下:O(nlogn)
最坏情况下:O(n^2)
平均情况下:O(nlogn)
算法不稳定
暂时就这样子了,加上了定向冒泡排序和二分插入以及计数,久违的把这个做完了,路漫漫兮~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。