排序算法的稳定性
排序算法的世间复杂度
简单说就是程序循环执行的总次数,算法的时间复杂度是一个函数,定量的描述了算法运行的时间用符号O表示,即O(f(n));
对九种排序的详细介绍
一、插入排序(1、直接插入排序;2、折半插入排序;3、希尔排序)
插入排序在对几乎已经拍好序的数据来进行操作时,效率高,可以达到线性效率O(n)
最坏的情况时间复杂度为O(n*n)
但是插入排序是低效的排序,因为插入排序每次只能将数据移动一个位置。
1、直接插入排序
插入排序基本思路: 每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。即边插入边排序,保证子序列中随时都是排好序的。
2、折半插入排序
step1:查找插入位置
(1)待查找范围的下标
(2)每次跟中间位置的元素比较
(3)根据比较结果调整查找范围(改变low或者high)
(4)重复上述步骤直到查找不成功(low>high)或者查找成功
查找不成功(原来有序表中没有待插入元素)插入位置如何确定
查找成功(原来有序表中有待插入元素)插入位置如何确定
step2:插入操作
1、挪动元素
2、插入操作
3、希尔排序
基本思想:
1、将待排序的序列分为n个子序列,然后对每个子序列进行直接插入排序,
2、重复多次 1 的方法,直到 n=1,完成排序
一般情况:
一般是分成length/2个组,然后并行同时进行分组排序,之后再不断分组,一直到每组数据只有一个元素时再交换完之后,就已经将无序序列变成有序序列了。
二、交换排序(1、冒泡排序;2、快速排序)
基本思想:两两比较,如果发生逆序则交换,直到所有记录都排好序为止。
1、冒泡排序
方法:从头到尾重复遍历要排序的数列,一次比较相邻的两个元素,如果他们顺序是错的,就交换,遍历操作重复执行,直到没有元素需要交换为止。
算法步骤:
(1)比较第一个和第二个元素,如果第一个大于第二个,则交换,
(2)比较第二个和第三个元素,若果第二个大于第三个则交换
......
(n)比较第n-1和第n个元素,如果第n-1个比第n个大,则交换
做完一趟之后,最大的元素就到了最后的位置上,每一趟冒泡都会把最大的元素归位。
上面的冒泡最多重复 n-1 次,所有元素都会归位,排序完成。
2、快速排序
基本思想:
不断执行一个操作:
选取一个基准值pivot,然后把原来序列花分为两个部分,一个部分小于基准值,另一部分大于等于基准值,又称为花分交换排序。
采用分治算法,算法步骤:
(1)从待排序数列中选择一个基准元素pivot,
(2)把剩余的元素划分为两个序列:
小于基准值的子序列s1和大于等于基准值的子序列s2
(3)子序列s1和s2同样方法递归执行(1)和(2),直到序列中元素个数为0或者1
pivot的选择策略:
1、每次固定选取序列中第一个或者最后一个元素作为pivot
如果输入序列是随机的,那么这种策略可以被接受,
但是如果输入的序列是预排序或者逆序的,那么这种策略的分割是非常糟糕的,因为所有元素不是被划入s1就是s2
2、随机选区一个元素作为pivot
一般来说这种策略非常安全,因为随机的pivot不可能总是产生劣质的分割,
但是随机数生成一般是昂贵的,因此这种策略根本上减少不了算法其余的平均时间。
3、pivot最好是选择数列中值,但是中值很难算出,只能通过估计,中值的估量可以随机取三个元素,并采用他们的中值作为pivot而得到。
事实上,随机性并没有太大的帮助,因此一般做法是使用左端、右端、中心位置上的三个元素的中值作为pivot(三数中值分割法)。
三、选择排序(1、简单排序;2、堆排序)
1、选择排序是一种直观的排序算法,
工作原理:
在未排序的序列中选择最大或最小的元素和序列中的第一个元素交换位置,再从剩余未排序的元素中寻找最大最小元素,重复之前操作,直至所有元素归位,排序完成。
算法步骤:
1、通过n-1次关键字比较,从n个记录中找出关键字最小的记录,将它与第一个记录交换。
2、再通过n-2次关键字比较,从剩余n-1个记录中寻找关键字次小的记录,将它与第二个记录交换。
3、重复上述操作,共进行n-1次排序,排序结束。
一、简单选择排序算法步骤:
1、从待排数列中选择一个关键字最小的元素。
2、如果最小元素不是待排序列中的第一个元素,则交换他们
3、从剩下的n-1个元素中选择最小的重复上面两个步骤,直到完成排序。
四、归并排序
五、基数排序
代码部分
1、直接排序
代码:
#include<iostream>
using namespace std;
void InsertSort(int* a, int length)
{
int i = 0, j = 0, temp = 0;
for (i = 1; i < length; i++)
{
temp = a[i]; //将下一个要插入的元素赋值给temp(记录下来)
for (j = i - 1; j >= 0; j--)//j从他本身的前一个开始,循环找正确的位置,退出循环时,j=-1
{
if (temp < a[j])
a[j + 1] = a[j]; //如果已经找到小于它的就交换小于他的都向后移位
else
break; //如果要插入的元素已经大于或等于(找到正确位置)直接退出
}
a[j + 1] = temp;//此时j=-1
}
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
InsertSort(array, sizeof(array)/sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]);i++)
cout<<array[i]<<" ";
return 0;
}
2、折半插入排序
#include<iostream>
using namespace std;
void BinInsertSort(int a[], int length, int elem)
{
int low = 0;
int high = length - 1;
int mid;
//step1:查找插入位置
while (low <= high)
{
mid = (low + high) / 2;
if (elem >= a[mid])
low = mid + 1;
else
high = mid - 1;
}
//step2:插入操作(先挪动元素,再插入)
for (int i = length - 1; i >= high + 1; i--)
a[i + 1] = a[i];
a[high + 1] = elem;
}
void InsertSort(int a[], int length)
{
int i;
for (i = 1; i < length; i++)
{
BinInsertSort(a, i, a[i]);
}
}
int main()
{
int array[10] = { 3,8,45,13,20,6,9,11,22,33 };
InsertSort(array, sizeof(array) / sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
cout << array[i] << " ";
return 0;
}
3、希尔排序
#include<iostream>
using namespace std;
void ShellSort(int* a, int length)
{
int i = 0, j = 0, temp = 0;
int h = 0;
for (h = length / 2; h > 0; h /= 2)
{
for (i = h; i < length; i++)
{
temp = a[i]; //将下一个要插入的元素赋值给temp(记录下来)
for (j = i - h; j >= 0; j-=h)//j从他本身的前一个开始,循环找正确的位置,退出循环时,j=-1
{
if (temp < a[j])
a[j + h] = a[j]; //如果已经找到小于它的就交换小于他的都向后移位
else
break; //如果要插入的元素已经大于或等于(找到正确位置)直接退出
}
a[j + h] = temp;//此时j=-1
}
}
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
ShellSort(array, sizeof(array)/sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]);i++)
cout<<array[i]<<" ";
return 0;
}
3、冒泡排序
#include<iostream>
using namespace std;
//冒泡排序
void BubbleSort(int* arr, int length)
{
while (length)
{
int flag = 0;
for (int i = 1; i < length; ++i)
{
if (arr[i - 1] > arr[i])
{
int temp = arr[i];
arr[i] = arr[i - 1];
arr[i - 1] = temp;
flag = 1;
}
}
if (flag == 0)
{
break;
}
--length;
}
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
BubbleSort(array, sizeof(array)/sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]);i++)
cout<<array[i]<<" ";
return 0;
}
4、快速排序
#include<iostream>
using namespace std;
int get_mid(int a[], int l, int r)
{
int pivot = a[l];
while (l < r)
{
while (a[r] >= pivot && l < r)
r--;
a[l] = a[r];
while (a[l] <= pivot && l < r)
l++;
a[r] = a[l];
}
a[l] = pivot;
return l;
}
void QuickSort(int a[], int l,int r)
{
if (l < r)
{
int mid = get_mid(a, l, r);
QuickSort(a, l, mid - 1);
QuickSort(a, mid + 1, r);
}
}
int main()
{
int array[10] = { 3,15,0,13,16,6,9,11,22,33 };
int l=0;
int r=9;
QuickSort(array,l,r);
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
cout << array[i] << " ";
return 0;
}
#include<iostream>
using namespace std;
//冒泡排序
void QuickSort(int* arr,int start, int end)
{
if (start >= end)
return;
int x = start;
int y = end;
int base = arr[start];
while (x < y)
{
while (arr[y] > base && x < y)
{
y--;
}
if (x < y)
{
arr[x] = arr[y];
x++;
}
while (arr[x] < base && x < y)
{
x++;
}
if (x < y)
{
arr[y] = arr[x];
y--;
}
}
arr[x] = base;
QuickSort(arr, start, x - 1);
QuickSort(arr, x + 1, end);
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
QuickSort(array,0, sizeof(array)/sizeof(array[0])-1);
for (int i = 0; i < sizeof(array) / sizeof(array[0]);i++)
cout<<array[i]<<" ";
return 0;
}
5、简单选择排序
#include<iostream>
using namespace std;
void SelectSort(int* a, int length)
{
int i = 0, j = 0, temp = 0, index = 0;
for (i = 0; i < length - 1; i++)
{
temp = a[i];
index = i;//记录下标
for (j = i + 1; j < length; j++)
{
if (a[j] < temp)
{
temp = a[j];
index = j;
}
}
if (index != i)
{
a[index] = a[i];
a[i] = temp;
}
}
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
SelectSort(array, sizeof(array) / sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
cout << array[i] << " ";
return 0;
}
#include<iostream>
using namespace std;
void swap(int* x, int* y)
{
int* t = x;
x = y;
y = t;
}
void SelectSort(int* a, int length)
{
int t = 0, flag = 0;
for (int i = 0; i < length - 1; i++)
{
t = i;
for (int j = i + 1; j < length - 1; j++)
{
if (a[i] > a[j])
{
t = j;//找出未排序序列中最大元素的下标,赋值给t
flag = 1;
}
}
if (flag)//如果未排序序列中第一个元素不是最大,则交换
swap(a[t], a[i]);
}
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
SelectSort(array, sizeof(array) / sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
cout << array[i] << " ";
return 0;
}
6、堆排序
#include<iostream>
using namespace std;
void AdjustHeapSort(int* a, int root, int last)
{
int child, temp = a[root];
for (;2*root+1<=last;root=child)
{
child = 2 * root + 1;
if (child + 1 <= last && a[child] < a[child + 1])
child++;
if (a[child] > a[root])
{
a[root] = a[child];
a[child] = temp;
}
}
}
void swap(int* x, int* y)
{
int t = *x;
*x = *y;
*y = t;
}
void HeapSort(int* a, int length)
{
//构建大顶堆
int i = 0;
for (i = length / 2 - 1; i >= 0; i--)
{
AdjustHeapSort(a, i, length - 1);
}
for (i = length - 1; i > 0; i--)
{
swap(&a[0],&a[i]);
AdjustHeapSort(a, 0, i-1);
}
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
HeapSort(array, sizeof(array) / sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
cout << array[i] << " ";
return 0;
}
7、归并排序
#include<iostream>
#include<malloc.h>
using namespace std;
void Merge(int* a, int start, int mid, int end)
{
int llength = mid - start + 1;
int rlength = end - mid;
int* L = (int *)malloc(sizeof(int) * llength);
int* R = (int *)malloc(sizeof(int) * rlength);
int i=0, j=0, k=0;
for (i = 0, k = start; i < llength; i++, k++)
L[i] = a[k];
for (j = 0; j < rlength; j++, k++)
R[j] = a[k];
for (i = 0, j = 0, k = start; i < llength && j < rlength; k++)
{
if (L[i] < R[j])
a[k] = L[i++];
else
a[k] = R[j++];
}
if (i < llength)
for (; i < llength; i++, k++)
a[k] = L[i];
if (j < rlength)
for (; j < rlength; j++, k++)
a[k] = R[j];
free(L);
free(R);
}
void MergeSort(int* a, int start, int end)
{
if (start >= end)
return;
int mid = (start + end) / 2;
MergeSort(a, start, mid);
MergeSort(a, mid + 1, end);
Merge(a, start, mid, end);
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
MergeSort(array, 0,sizeof(array) / sizeof(array[0])-1);
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
cout << array[i] << " ";
return 0;
}
8、基数排
#include<iostream>
#include<malloc.h>
using namespace std;
void TadixSort(int* a, int length)
{
int i = 0, max = a[0], base = 1;
for (i = 1; i < length; i++)
{
if (a[i] > max)
max = a[i];
}
int* t = (int*)malloc(sizeof(int) * length);
while (max / base > 0)
{
int bucket[10] = { 0 };
for (i = 0; i < length; i++)
{
bucket[a[i] / base % 10]++;
}
for (i = 1; i < 10; i++)
bucket[i] += bucket[i - 1];
for (i = length - 1; i >= 0; i--)
{
t[bucket[a[i] / base % 10] - 1] = a[i];
bucket[a[i] / base % 10]--;
}
for (i = 0; i < length; i++)
a[i] = t[i];
base = base * 10;
}
}
int main()
{
int array[10] = { 3,8,10,13,16,6,9,11,22,33 };
TadixSort(array,sizeof(array) / sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
cout << array[i] << " ";
return 0;
}
2021/12/12