一直以来对排序算法没有深刻的理解,只能简单的代码编写,因此今天抽出一些时间对以前排序的不足加以修改。
这里我们来探讨一下常用的比较排序算法,下表给出了常见比较排序算法的性能:
稳定性的判别:如果说排序前两个相等的数位置是a,b,排序后两个数仍然是a,b,则说明这个排序是稳定的。通俗来讲就是说:排序前后两个相等的数相对位置不发生改变。
冒泡排序:
1.比较相邻的元素,如果前者大于后者,则将两个数进行交换。
2.对每一对相邻元素都做相同的工作,从第一对到最后一对,这步做完之后,最后一个元素便是最大值。
3.针对所有元素都重复以上步骤,每重复一次,便对相邻比较次数减一。
4.直到没有相邻元素比较即完成了冒泡排序。
代码实现:
//冒泡排序
//时间复杂度O(N^2)
//空间复杂度O(1)
//稳定性:稳定
void BubbleSort(int array[], int size)
{
int i, j;
for (i = 0; i < size-1; i++)
{
for (j = 0; j < size - 1 - i; j++)
{
if (array[j] > array[j + 1])
swap(&array[j], &array[j + 1]);
}
}
}
选择排序:
1.从第一个元素开始,然后与所有元素进行比较。
2.遇到比他小的进行交换,一直比较完所有元素,得到最小的那个元素。
3.除了最小的那个元素,其余重复以上步骤,直到只剩一个元素为止。
代码实现:
//选择排序
//时间复杂度O(n^2)
//空间复杂度O(1)
//稳定性:不稳定
void SelectSort(int array[], int size)
{
int i = 0;
for (; i < size; i++)
{
for (int j = i; j < size; j++)
{
if (array[i]<array[j])
{
swap(&array[i], &array[j]);
}
}
}
}
插入排序:
1.首先默认第一个元素已经排好序,然后取出下一个元素。
2.将排好序的元素进行从后往前遍历,如果说已排序的元素大于新元素,则进行搬运,将该元素移到下一位置。
3.继续遍历,直到元素小于新元素时,将新元素插入到元素后面。
4.重复以上步骤。直到所有元素比较完成。
代码实现:
//插入排序
//时间复杂度O(N^2)
//空间复杂度O(1)
//稳定性:稳定
void InsertSort(int array[], int size)
{
if (size <= 1)
return;
int bound = 1;//[0,bound)有序空间
for (; bound < size; bound++)
{
int bound_value = array[bound];
int i = bound;
for (; i>0; i--)
{
if (array[i - 1] < bound_value)
{
array[i] = array[i - 1];//进行搬运
}
else{
break;
}
}
array[i] = bound_value;
}
}
堆排序:
1.用给定的无序数组建一个大堆。
2.每次将堆顶元素与最后一个数进行交换。
3.将堆的大小减一,进行重新调整,直到只剩一个元素。
代码实现:
//堆排序
//时间复杂度O(nlogn)
//空间复杂度O(1)
//稳定性:不稳定
void AdjustDown(int array[], int size, int index)//向下调整,大堆
{
int parent = index;
int child = 2 * index + 1;
while (child < size){
if (child + 1 < size&&array[child] < array[child + 1])
{
child = child + 1;
}
if (array[parent]<array[child])
{
swap(&array[parent], &array[child]);
}
else{
break;
}
parent = child;
child = 2 * child + 1;
}
return;
}
void HeapCreate(int array, int size)
{
if (size <= 1)
return;
int i = (size - 1 - 1) / 2;
for (; i >= 0; i--)
{
AdjustDown(array, size, i);
}
}
void HeapPop(int array[], int size)
{
if (size <= 1)
return;
swap(&array[0], &array[size - 1]);
AdjustDown(array, size-1,0);
}
void HeapSort(int array[], int size)
{
if (size <= 1)
return;
HeapCreate(array, size);
int i = 0;
for (; i < size; i++)
{
HeapPop(array, size - i);
}
}
归并排序:
1.申请同等大小的空间,将数组拆分为一小块连续的空间(其实也就是拆成1)。
2.设置两个指针,最初为止为两个已排好序数组的起始位置。
3.比较两个指针所指向的内容,将较小的元素放入到新的空间当中,并且指针向后移动。
4.重复3,直到有一指针指向排好序的末尾。
5.将另一数组剩余的元素全都放入新数组当中。
代码实现:
//归并排序
//时间复杂度O(nlogn)
//空间复杂度O(N)
//稳定性:稳定
void MergeArray(int array[], int beg, int mid, int end, int *tmp)
{
int output = beg;
int cur1 = beg;
int cur2 = mid;
while (cur1 < mid&&cur2 < end)
{
if (array[cur1] < array[cur2])
{
tmp[output++] = array[cur1++];//将较小值放入新空间
}
else{
tmp[output++] = array[cur2++];
}
}
while (cur1 < mid)
{
tmp[output++] = array[cur1++];
}
while (cur2 < end)
{
tmp[output++] = array[cur2++];
}
memcpy(array + beg, tmp + beg, sizeof(int)*(end - beg));//还给原空间
}
void _MergeSort(int array, int beg, int end, int *tmp)
{
if (end - beg <= 1)
return;
int mid = beg + (end - beg) / 2;//分割
_MergeSort(array, beg, mid, tmp);
_MergeSort(array, mid, end, tmp);
MergeArray(array, beg, mid, end, tmp);
}
void MergeSort(int array[], int size)
{
int *tmp = (int *)malloc(sizeof(int)*size);//创建新空间
_MergeSort(array, 0, size, tmp);
free(tmp);
}
快速排序:
1.首先选一个元素,作为它的基准值。
2.定义两个指针,一个指向数组的起始,一个指向数组的末尾。
3.起始指针从前向后移动,找到第一个大于基准值的值,末尾指针从后往前走,找到第一个小于它的值。进行交换。
4.当两个指针交叉时,循环结束。交换起始指针指向的值和基准值的值。
5.返回基准值的下标。得到基准值前面的元素都比基准值小,后面的元素都比基准值大。
6.将基准值前面元素和后面元素进行分区重复以上步骤。
代码实现:
//快速排序
//时间复杂度O(nlogn)
//空间复杂度O(nlogn)
//稳定性:不稳定
int Partion(int array[], int beg, int end)
{
int left = beg;
int right = end - 1;
int tmp = array[end - 1];//基准值
while (left < right){
while (left < right&&array[left] <= tmp)//找到第一个大于基准值的数
{
++left;
}
while (left<right&&array[right]>=tmp)//找到第一个小于基准值的数
{
--right;
}
if (left < right)
{
swap(&array[left], &array[right]);
}
}
swap(&array[left], &array[end-1]);//将得到left左边都小于array[left],右边都大于array[left]
return left;
}
void _QuickSort(int array[], int beg, int end)
{
if (end - beg <= 1)
return;
int mid = Partion(array, beg, end);//分割空间
_QuickSort(array, beg, mid);
_QuickSort(array, mid, end);
}
void QuickSort(int array[], int size)
{
_QuickSort(array, 0, size);
}
int main()
{
int array[] = { 5, 7, 8, 9, 6, 2, 3, 1 };
//BubbleSort(array, sizeof(array) / sizeof(array[0]));
//SelectSort(array, sizeof(array) / sizeof(array[0]));
//InsertSort(array, sizeof(array) / sizeof(array[0]));
//HeapSort(array, sizeof(array) / sizeof(array[0]));
//MergeSort(array, sizeof(array) / sizeof(array[0]));
QuickSort(array, sizeof(array) / sizeof(array[0]));
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
{
printf("%d ", array[i]);
}
printf("\n");
system("pause");
return 0;
}