直接插入排序: 时间复杂度:O(n^2) 空间复杂度: O(1) 稳定 越有序越快
希尔排序: 时间复杂度:O(n^1.3-n^1.5) 空间复杂度:O(1) 不稳定 越有序越快
冒泡排序: 时间复杂度:0(n^2) 空间复杂度:O(1) 稳定
选择排序: 时间复杂度: 0(n^2) 空间复杂度:0(1) 不稳定
快速排序: 时间复杂度: 0(nlogn) 空间复杂度: 0(logn) 不稳定 越有序越差;
归并排序: 时间复杂度:0(nlog2n) 空间复杂度:O(1) 稳定
堆排序: 时间复杂度: 0(nlog2n) 空间复杂度: 0(1) 不稳定
基数排序: 时间复杂度: 0(dn) 空间复杂度: 0(n) 稳定
直接插入排序:
//插入排序 越有序越快,完全有序则为0(n)
//每次在末尾插入一个数字,依次向前比较,类似与抓扑克牌(插入排序, 每次左边的子序列都是有序的)
void InsertSort(int *arr,int len)//O(n^2),O(1),稳定,
{
int tmp;
int i;
int j;
for(i=1;i<len;i++)//1 2 3 4 5
{
tmp = arr[i];
for(j=i-1;j>=0;j--)
{
if(arr[j] <= tmp)
{
break;
}
else
{
arr[j+1] = arr[j];
}
}
arr[j+1] = tmp;
}
}
希尔排序:
//希尔排序 间隔性的分组,分组插入排序,相隔gap个数的都为一组,从第gap个数开始
//一趟shell过程
void Shell(int *arr,int len,int gap)
{
int tmp;
int i;
int j;
for(i=gap;i<len;i++)
{
tmp = arr[i];
for(j=i-gap;j>=0;j-=gap)
{
if(arr[j] <= tmp)
{
break;
}
else
{
arr[j+gap] = arr[j];
}
}
arr[j+gap] = tmp;
}
}
void ShellSort(int *arr,int len)//O(n^1.3)~O(n^1.5),O(1),不稳定
{
int d[] = {5,3,1};
for(int i=0;i<sizeof(d)/sizeof(d[0]);i++)
{
Shell(arr,len,d[i]);
}
}
冒泡排序:
//冒泡排序 两两交换 比较慢, 数从前向后冒泡比较,冒泡过程中,数列无序状态
void BubbleSort(int *arr,int len)//O(n^2),O(1),稳定
{
int tmp;
for(int i=1;i<len;i++)
{
for(int j=0;j<len-i;j++)
{
if(arr[j] > arr[j+1])
{
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
选择排序:
//选择排序,每次找出数值最小的下标,交换未排序区域第一个与最小的(与冒泡的区别,只交换一次)
void SelectSort(int *arr,int len)//O(n^2),O(1),不稳定
{
int minIndex;
int tmp;
for(int i=0;i<len-1;i++)
{
minIndex = i;
for(int j=i+1;j<len;j++)
{
if(arr[minIndex] > arr[j])
{
minIndex = j;
}
}
if(minIndex != i)
{
tmp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = tmp;
}
}
}
快速排序
//快速排序:对数组找出一个中间大小的合适哨兵,把小于哨兵的放左边,大于哨兵的放右边,中间是等于哨兵的,分别对左右递归调用快排
//快速排序的一次划分,很重要
int Partition(int *arr,int low,int high)//O(n),O(1)
{
int tmp = arr[low];//基准
while(low < high)
{
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;//low==high
return low;
}
static void Quick(int*arr,int low,int high)
{
int par = Partition(arr,low,high);
if(low+1 < par)//左边至少两个数据
{
Quick(arr,low,par-1);
}
if(par+1 < high)//右边至少两个数据
{
Quick(arr,par+1,high);
}
}
void QuickSort(int *arr,int len)//O(nlogn),O(logn),不稳定
{
Quick(arr,0,len-1);
}
//非递归的快排
void QuickSort2(int *arr,int len)//O(n),O(logn),不稳定
{
SeqStack s;
InitStack(&s);
int low = 0;
int high = len-1;
int par = Partition(arr,low,high);
if(low+1 < par)
{
Push(&s,low);
Push(&s,par-1);
}
if(par+1 < high)
{
Push(&s,par+1);
Push(&s,high);
}
while(!IsEmpty(&s))
{
Pop(&s,&high);
Pop(&s,&low);
par = Partition(arr,low,high);
if(low+1 < par)
{
Push(&s,low);
Push(&s,par-1);
}
if(par+1 < high)
{
Push(&s,par+1);
Push(&s,high);
}
}
Destroy(&s);
}
归并排序:
//归并排序,自顶向下,递归,先让每个数字为一组,组内都有序,再两个两个为一组,再4个4个为一组。最终让数组完全有序。
//一趟归并
static void Merge(int *arr,int len,int gap)
{
int low1 = 0;//第一个归并的的起始下标
int high1 = gap-1;//第一个归并段的结尾下标
int low2 = high1+1;//第二个归并段的起始下标
int high2 = low2+gap-1<len-1 ? low2+gap-1 : len-1;//第二个归并段的结尾下标
int *brr = (int *)malloc(sizeof(int)*len);//存放归并好的数据
int i = 0;//brr下标
//有两个归并段
while(low2 <= high2)
{
//两个归并段都还有数据
while(low1<=high1 && low2<=high2)
{
if(arr[low1] <= arr[low2])
{
brr[i++] = arr[low1++];
}
else
{
brr[i++] = arr[low2++];
}
}
//一个段数据归并完成,另一个还有数据
while(low1 <= high1)
{
brr[i++] = arr[low1++];
}
while(low2 <= high2)
{
brr[i++] = arr[low2++];
}
low1 = high2+1;
high1 = low1+gap-1;
low2 = high1+1;
high2 = low2+gap-1<len-1 ? low2+gap-1 : len-1;
}
//不足两个归并段
while(low1 < len)
{
brr[i++] = arr[low1++];
}
for(i=0;i<len;i++)
{
arr[i] = brr[i];
}
free(brr);
}
void MergeSort(int *arr,int len)//O(nlogn),O(n),稳定
{
for(int i=1;i<len;i*=2)//归并段的长度
{
Merge(arr,len,i);
}
}
堆排序:
//堆排序,建堆(升序建大堆,降序建小堆),交换堆顶与最后一位无序数据,调整堆,递归,交换调整
//一次堆调整
void HeapAdjust(int *arr,int start,int end)//O(logn),O(1)
{
int tmp = arr[start];
int i;
for(i=2*start+1;i<=end;i=2*i+1)
{
if(i+1<=end && arr[i]<arr[i+1])//i是左右孩子较大值的下标
i++;
if(tmp < arr[i])//arr[i]需要上移
{
arr[(i-1)/2] = arr[i];
}
else //找到位置
{
break;
}
}
arr[(i-1)/2] = tmp;
}
void HeapSort(int *arr,int len)//O(nlogn),O(1),不稳定
{
//第一次建大根堆
for(int i=(len-1-1)/2;i>=0;i--)
{
HeapAdjust(arr,i,len-1);
}
int tmp;
for(int i=0;i<len-1;i++)
{
tmp = arr[0];
arr[0] = arr[len-1-i];
arr[len-1-i] = tmp;
HeapAdjust(arr,0,len-1-i-1);
}
}
基数排序:
//基数排序
static int Count(int n)
{
int tmp = 0;
do
{
tmp++;
n /= 10;
}while(n != 0);
return tmp;
}
//数字n的右数第fig位
int FigNum(int n,int fig)//123
{
for(int i=0;i<fig;i++)
n /= 10;
return n%10;
}
//fig右数第几位,从0开始
static void Radix(int *arr,int len,int fig)
{
queue<int> que[10];//queue<int>创建整型队列
int tmp;
for(int i=0;i<len;i++)
{
tmp = FigNum(arr[i],fig);
que[tmp].push(arr[i]);
}
int j = 0;//队列的下标
int i = 0;
while(i<len)
{
while(!que[j].empty())
{
arr[i++] = que[j].front();//获取对头的值
que[j].pop();//删除队头
}
j++;
}
}
void RadixSort(int *arr,int len)//O(dn),O(n),稳定
{
int i;
int max = arr[0];//保存最大值
for(i=1;i<len;i++)
{
if(max < arr[i])
{
max = arr[i];
}
}
int count = Count(max);
for(i=0;i<count;i++)
{
Radix(arr,len,i);//i右数第几位,从0开始
}
}
5128

被折叠的 条评论
为什么被折叠?



