一、选择排序:
时间复杂度:无序O(n^2) 有序O(n)
空间复杂度:O(1)
算法稳定性:不稳定(相同数值都交换了)
原理:选择一个值arr[0]作为标杆,然后循环找到除这个值外最小的值(查找小于标杆的最小值),
交换这两个值,这时最小值就被放到了arr[0]上,然后再将arr[1]作为标杆,从剩下未排序的值中找到最小值,
并交换这两个值。
例:4 1 5 12 0
第一趟:1 4 5 12 0->0 4 5 12 1
第二趟:0 1 5 12 4
第三趟:0 1 4 12 5
第四趟:0 1 4 5 12
void Select_Sort(int *arr, int len)
{
int i, j;
int min, tmp;
for (i = 0; i < len; i++)
{
min = i;//i++后标杆位置后移
for (j = i + 1; j < len; j++)
{
if (arr[j] < arr[min])//j往后走比较arr[j]与arr[min]标杆的大小,使标杆处是最小的值。
{
tmp = arr[j];
arr[j] = arr[min];
arr[min] = tmp;
}
}
}
}
二、冒泡排序:挨个挨个去比较
时间复杂度:O(n^2)
空间复杂度:O(1)
算法稳定性:稳定
原理:从数组的第一个位置开始两两比较arr[j]和arr[j+1],
如果arr[j]大于arr[j+1]则交换他两个的位置,直到数组结束;
从数组的第一个位置开始,重复上面的动作,止到数组长度减一个位置结束;
从数组的第一个位置开始,重复上面的动作,止到数组长度减二个位置结束;
例:4 1 5 12 0
第一趟:1 4 5 0 12 i=0 j<4
第二趟:1 4 0 5 12 i=1 j<3
第三趟:1 0 4 5 12 i=2 j<2
第四趟:0 1 4 5 12 i=3 j<1
void Bubble_Sort(int *arr, int len)//下沉
{
int i, j;
int tmp=0;
bool swap = false;
for (i = 0; i < len - 1; i++)
{
swap = false;
for (j = 0; j < len - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
swap = true;
}
}
if (!swap)//swap==false没有交换
{
return;
}
}
}
void Bubble_Sort1(int *arr, int len)//上浮
{
int i;
int j;
int tmp;
bool swap=false;
for (i = 0; i < len; i++)
{
swap = false;
for (j = i + 1; j < len; j++)
{
if (arr[i] > arr[j])
{
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
swap=true;
}
}
if(!swap)
{
return;
}
}
}
void Bubble_Sort2(int *arr, int len)//不开辟tmp
{
int i, j;
for (i = 0; i<len - 1; i++) //扫描次数len-1
{
for (j = len - 1; j>i; j--)
{
if (arr[j] > arr[j - 1])
{
arr[j] += arr[j - 1];
arr[j - 1] = arr[j] - arr[j - 1];
arr[j] = arr[j] - arr[j - 1];
}
}
}
}
三、直接插入排序:
时间复杂度:无序O(n^2) 有序O(n)
空间复杂度:O(1)
算法稳定性:稳定
原理:把一个元素按升序或(降序)插入已经有序的一个序列里面,插入后保持序列的有序。
假设有序列arr[1..n],则将arr[2]插入arr[1..1]中,将arr[3]插入arr[1..2]中,
将arr[4]插入arr[1..3]中。如此经过n-1次的插入,便可以使arr[1..n]有序。
把待插入数与已有序的数列依次比较,找到合适位置,进行数据挪动,插入到合适位置。
例:4 1 5 12 0
第一趟:tmp=1 1<4 1 4
第二趟:tmp=5 1 4 5
第三趟:tmp=12 1 4 5 12
第四趟:tmp=0 0<12,0<5,0<4,0<1 0 1 4 5 12
void Insert_Sort(int *arr, int len)
{
int i,j;
int tmp=0;
for (i = 1; i < len; i++)
{
tmp = arr[i];//把将要比较的值放入tmp里
for (j = i - 1; j >= 0; j--)//j在i的前一位
{
if (tmp < arr[j])//如果tmp里的值比j的值小就互换tmp和j的值
{
arr[j + 1] = arr[j];//即把j里的值放在下一位,把tmp的值放在原来j的位置
}
else
{
break;
}
}
arr[j + 1] = tmp;//不是则就放在它原来的位置,包扩j减到-1位置 j+1位0号位置
}
}
四、希尔(shell)排序 :直接插入的优化
时间复杂度:O(n^1.3)——O(n^1.5)
空间复杂度:O(1)
算法稳定性:不稳定
原理:设定一个增量gap,每次插入排序使相距为d的元素排成一个有序列,
然后缩小增量,继续插入排序,最后一次gap=1,排序完成 。
在进行大量数据排序上,效率较高,因为相比于冒泡,选择排序,
其每次操作省略了三步赋值的开销,只有一步。
void Shell(int *arr, int len,int gap)
{
int i, j;
int tmp = 0;
for (i = gap; i < len; i++)
{
tmp = arr[i];
for (j = i - gap; j >= 0; j-=gap)
{
if (tmp < arr[j])
{
arr[j + gap] = arr[j];
}
else
{
break;
}
}
arr[j + gap] = tmp;
}
}
void Shell_Sort(int *arr, int len)
{
int drr[] = { 5,3,1 };//素数数组
int lend = sizeof(drr) / sizeof(drr[0]);
for (int i = 0; i < lend; i++)
{
Shell(arr, len, drr[i]);
}
}
主函数及测试:
void Show(int *arr,int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {12,45,68,76,24,5};
int len = sizeof(arr) / sizeof(arr[0]);
//Select_Sort(arr, len);
//Bubble_Sort(arr, len);
Bubble_Sort2(arr,len);
//Insert_Sort(arr,len);
Show(arr, len);
/*int arr[] = { 12,45,68,76,24,5,85,65,2,4,78,95 };
int len = sizeof(arr) / sizeof(arr[0]);
Shell_Sort(arr, len);
Show(arr, len);*/
}