排序算法其实就是通过特定的算法将一组数据或多组数据按照既定的模式或者规则进行排列
排序的稳定性是指在排序的过程中如果有两个数据的主关键词一致,那么结果如果存在多样性,那么就说明该排序方法不稳定,反之说明稳定。
假设a=b,在排序之前a的位置在b的前面,在排序之后a的位置仍然在b的前面,那么说明稳定,反之就代表不稳定。
内排序是指在排序的过程中,待排序的数据全部放在内存中。外排序是指由于数据比较多,数据需要在内存和硬盘之间进行数据读写才能进行。这次主要总结几个比较重要的内排序算法。
内排序算法的优劣主要可以通过时间复杂度,空间复杂度以及算法的复杂度(算法本身的难度)来衡量。这次主要总结几个常用的排序算法,冒泡排序,插入排序,希尔排序,快速排序以及堆排序。
本篇文章的代码主要通过c/c++语句书写
typedef struct
{
int *arr;//数组指针,用来传递可变数组
int length;//指定数组的大小
}sqList;
void swap(sqList*L, int i, int j)//交换函数,用来交换数组中指定的两个数据
{
int temp = L->arr[i];
L->arr[i] = L->arr[j];
L->arr[j] = temp;
}
实现思想
冒泡排序是一种交换排序他的实现思想是两两数据之间进行比较,如果正序则继续比较,如果反序则进行交换,这样每循环比较一次就把最大或者最小的数据放到最左或者最右边,就像是冒泡,一次比较完把最大的泡泡浮出来,然后继续比较剩下的n-1个数据,这样进行n次循环比较之后就把顺序排好了。
代码实现
优化过后,如果在一次循环排序的过程中没有数据再做比较,说明后续数据已经有序,不需要排列,这时候可以通过一个标志位来判断,没有比较后直接退出循环,减少时间的复杂度
void BubSort(sqList*L)
{
if (L->length == 0)
{
cout << "数组无数据" << endl;
return;
}
int flag = 1;//标志位,判断后续的数据中是否还存在比较
for (int i = 0; i < (L->length - 1)&&flag; ++i)
{
flag = 0;//默认不再存在比较,置0
for (int j = L->length - 2; j >= i; j--)
{
if (L->arr[j] > L->arr[j + 1])
{
flag = 1;//当存在比较时再置一
swap(L, j, j + 1);
}
}
}
}
void ChoiceSort(sqList*L)
{
if (L->length == 0)
{
cout << "数组无数据" << endl;
return;
}
for (int i = 0; i < L->length; ++i)
{
int min = i;//用来最后确定是否需要数据交换
for (int j = i + 1; j < L->length - 1; ++j)
{
if (L->arr[min] > L->arr[j])
{
min = j;//如果有更小的值,将其下标赋值给min,用来进行数据交换
}
}
if (min != i)
{
swap(L, i, min);
}
}
}
void InsertSort(sqList*L)
{
if (L->length == 0)
{
cout << "数组无数据" << endl;
return;
}
for (int i = 1; i < L->length; ++i)//把下标等于0的数据作为定标,从他的下一个数据依次进行插入
{
if (L->arr[i] < L->arr[i - 1])//如果当前数据比前一数据小才进行插入,否则有序
{
int j = 0;
int temp = L->arr[i];
//依次和前面的所有数据比较,直到遇到更小的数据
for ( j= i - 1; j >= 0 && L->arr[j] > temp; --j)
L->arr[j + 1] = L->arr[j];
L->arr[j + 1] = temp;//插入数据到合适位置
}
}
}
void ShellSort(sqList*L)
{
if (L->length == 0)
{
cout << "数组无数据" << endl;
return;
}
int i, j;
int increment = L->length;
do
{
increment = increment / 3 + 1;//设置**增量**
for (i = increment; i < L->length; ++i)
{
if (L->arr[i] < L->arr[i - increment])
{
int temp = L->arr[i];
//依次对子序列中的数据实行直接插入排序
for (j = i - increment; j >= 0 && L->arr[j] > temp; j -= increment)
L->arr[j + increment] = L->arr[j];
L->arr[j + increment] = temp;//插入到合适位置
}
}
} while (increment > 1);
}
void HeapSort(sqList*L)
{
int i;
for (i = L->length / 2 - 1; i >= 0; i--)//根据二叉树性质,i是所有有子节点的节点
{
HeapAdjust(L,i,L->length-1);//大顶堆调整函数
}
for (i = L->length - 1; i > 0; i--)//把二叉树的根节点(最大节点)排到最后一位
{
swap(L, 0, i);
HeapAdjust(L, 0, i - 1);
}
}
void HeapAdjust(sqList*L, int s, int m)//s是需要调整的节点,m是调整范围
{
int j, temp;
temp = L->arr[s];
for (j = 2*s + 1; j <= m; j = j*2+1)//遍历子节点
{
if (j<m&&(L->arr[j] < L->arr[j + 1]))//找出子节点中较大的一个
++j;
if (temp > L->arr[j])//把父节点调整为最大
break;
L->arr[s] = L->arr[j];//插入数据
s = j;
}
L->arr[s] = temp;
}
void QuickSort(sqList*L)
{
Qsort(L, 0, L->length - 1);
}
void Qsort(sqList*L, int low, int high)
{
int flag;
if (high - low <= MAX_INSERT)//判断,当数据量较小时用插入排序更好
{
//递归进行循环排序
flag = partition(L, low, high);
Qsort(L, low, flag - 1);
Qsort(L, flag + 1, high);
}
else
InsertSort(L);
}
int partition(sqList*L, int low, int high)
{
int flag;
//使用三序选择法找出一个最优枢轴
int m = low + (high - low) / 2;
if (L->arr[m] > L->arr[high])
swap(L, m, high);
if (L->arr[low] > L->arr[high])
swap(L, low, high);
if (L->arr[low] > L->arr[high])
swap(L, low, high);
if(L->arr[m] > L->arr[low])
swap(L, low, m);
flag = L->arr[low];//记录最优枢轴
//对数组排序,使枢轴左边全是小于其的元素,右边全是大于其的元素
while (low < high)
{
while (low<high&&L->arr[high]>=flag)
high--;
L->arr[low] = L->arr[high];
while (low<high&&L->arr[low]<=flag)
low++;
L->arr[high] = L->arr[low];
}
L->arr[low] = flag;
return low;
}
本人编程小白一枚,本文章是根据自己看的书以及别人的博客,并且经过测试改写之后进行编写的一篇文章,文中的图片是从百度上找的便于理解,如有侵权可以联系我删除,如有代码有错误,或者有更好的方法欢迎大佬指出,我会对此表示感谢!!!