十大排序算法及实现
0、总述排序
0.1、排序的概念
排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序,若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。内部排序的过程是一个逐步扩大记录的有序序列长度的过程
0.2、稳定性概念
稳定排序:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
不稳定排序:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
0.3、内部排序和外部排序
内部排序:排序不占用外存
外部排序:数据过大,排序占用外存。
0.4、时空复杂度
时间复杂度:排序消耗的时间
空间复杂度:排序所需的内存
0.5、排序总结
1、冒泡排序
1.1、冒泡排序概念
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
1.2、冒泡排序算法
1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
1.3、冒泡排序实现
void BubbleSort(SeqList *psl)
{
if (psl->_size == 0)
{
return;
}
for (int i = 0; i < psl->_size; i++)
{
for (int j = 0; j < psl->_size - i - 1; j++)
{
if (psl->_array[j] > psl->_array[j + 1])
{
Swap(&psl->_array[j], &psl->_array[j + 1]);
}
}
1.4、冒泡排序的时间复杂度和稳定性
时间复杂度:O(n^2);
稳定性:稳定
2、选择排序
2.1、选择排序概念
第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零
2.2、选择排序算法
1、初始状态:无序区为R[1…n],有序区为空;
2、第i趟排序(i = 1,2,3,…,n - 1)开始时,当前有序区和无序区分别为R[1,…,i - 1]和R[i,…,n]。该趟排序从当前无序区中选出关键字最小的记录R[k],将它与无序区的第1个记录交换,使R[1,…i]和R[i + 1,…,n]分别变为记录个数增加1个的新有序区和记录个数减少一个的无序区
3、n -1趟结束,数组有序
2.3、选择排序实现
void SelectSort(SeqList *psl)
{
if (psl->_size == 0)
{
return;
}
for (int i = 0; i < psl->_size - 1; i++)
{
int min = i;
for (int j = i + 1; j < psl->_size; j++)
{
if (psl->_array[j] < psl->_array[min])
{
min = j;
}
}
Swap(&psl->_array[i], &psl->_array[min]);
}
}
2.4、选择排序的时间复杂度和稳定性
时间复杂度:O(n^2);
稳定性:不稳定
3、插入排序
3.1、插入排序概念
插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。
适用于待排序元素基本有序的情况
3.2、插入排序算法
1、从第一个元素开始,该元素可以认为已经被排序;
2: 取出下一个元素,在已经排序的元素序列中从后向前扫描;
3: 如果该元素(已排序)大于新元素,将该元素移到下一位置;
4: 重复3,直到找到已排序的元素小于或者等于新元素的位置;
5: 将新元素插入到该位置后;
6: 重复2~5。
3.3、插入排序实现
void InstertSort(SeqList *psl)
{
if (psl->_size == 0)
{
return;
}
for (int i = 0; i < psl->_size; i++)
{
int tmp = psl->_array[i];
int j;
for (j = i; j > 0 && psl->_array[j - 1] > tmp; j--)
{
psl->_array[j] = psl->_array[j - 1];
}
psl->_array[j] = tmp;
}
}
3.4、选择排序的时间复杂度和稳定性
时间复杂度:O(n^2);
稳定性:不稳定
4、希尔排序
4.1、希尔排序概念
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
4.2、希尔排序算法
1:选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
2:按增量序列个数k,对序列进行k 趟排序;
3:每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
4.3、希尔排序实现
void ShellSort(SeqList *psl)
{
if (psl->_size == 0)
{
return;
}
for (int gap = psl->_size / 2; gap; gap /= 2)
{
for (int k = 0; k < gap; k++)
{
for (int i = k + gap; i < psl->_size; i += gap)
{
int tmp = psl->_array[i];
int j;
for (j = i; j > gap && psl->_array[j - gap] > tmp; j -= gap)
{
psl->_array[j] = psl->_array[j - gap];
}
psl->_array[j] = tmp;
}
}
}
}
4.4、希尔排序的时间复杂度和稳定性
时间复杂度:O(n*logn);
稳定性:不稳定
5、快速排序
5.1、快速排序概念
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
5.2、快速排序算法
1:从数列中挑出一个元素,称为 “基准”(pivot );
2:重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3:递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
5.3、快速排序实现
//QuickSort(快速排序)
//寻找基准值下标的方法
//hoare法
int GetIndexHoareWay(SeqList *psl, int left, int right)
{
int a = left + 1;
int b = right - 2;
int mid = (left + right) / 2;
if (psl->_array[left] > psl->_array[mid])
{
Swap(&psl->_array[left], &psl->_array[mid]);
}
if (psl->_array[mid] > psl->_array[right])
{
Swap(&psl->_array[mid], &psl->_array[right]);
}
if (psl->_array[left] > psl->_array[mid])
{
Swap(&psl->_array[left], &psl->_array[mid]);
}
if (right - left <= 2)
{
return mid;
}
Swap(&psl->_array[mid], &psl->_array[right - 1]);
while (a <= b)
{
while (a < right - 1 && psl->_array[a] <= psl->_array[right - 1])
{
a++;
}
while (b > 1 && psl->_array[b] >= psl->_array[right - 1])
{
b--;
}
if (a == b && (a == 1 || a == right - 1))
{
break;
}
if (a < b)
{
Swap(&psl->_array[a], &psl->_array[b]);
}
}
Swap(&psl->_array[a], &psl->_array[right - 1]);
return a;
}
//双指针法1
int GetIndexDoublePointWay1(SeqList *psl, int left, int right)
{
int a = left;
int b = right;
int flag = 0;
while (psl->_array[b] > psl->_array[a])
{
b--;
}
while (a < b)
{
Swap(&psl->_array[a], &psl->_array[b]);
flag = !flag;
while (psl->_array[b] >= psl->_array[a])
{
flag ? a++ : b--;
}
}
return flag ? b : a;
}
//双指针法2
int GetIndexDoublePointWay2(SeqList *psl, int left, int right)
{
int a = left;
int b = right - 1;
int mid = (left + right) / 2;
Swap(&psl->_array[mid], &psl->_array[right]);
while (a <= b)
{
while (a < right && psl->_array[a] <= psl->_array[right])
{
a++;
}
while (b > 0 && psl->_array[b] >= psl->_array[right])
{
b--;
}
if ((a == b) && (a == 0 || a == right))
{
break;
}
if (a < b)
{
Swap(&psl->_array[a], &psl->_array[b]);
}
}
Swap(&psl->_array[a], &psl->_array[right]);
return a;
}
//挖坑法
int GetIndexDigWay(SeqList *psl, int left, int right)
{
SLDataType tmp;
tmp = psl->_array[left];
while (left < right)
{
while (psl->_array[right] >= tmp && left < right)
{
right--;
}
psl->_array[left] = psl->_array[right];
while (psl->_array[left] <= tmp && left < right)
{
left++;
}
psl->_array[right] = psl->_array[left];
}
psl->_array[left] = tmp;
return left;
}
void DealQuickSort(SeqList *psl, int left, int right)
{
if (left >= right)
{
return;
}
int index = GetIndexHoareWay(psl, left, right);
DealQuickSort(psl, left, index - 1);
DealQuickSort(psl, index + 1, right);
}
void QuickSort(SeqList *psl)
{
DealQuickSort(psl, 0, psl->_size - 1);
}
//快速排序非递归
void QuickSortNonR(SeqList *psl)
{
int left;
int right;
int index;
Queue queue;
QueueInit(&queue);
QueuePush(&queue, 0);
QueuePush(&queue, psl->_size - 1);
while (!QueueEmpty(&queue))
{
left = QueueFront(&queue);
QueuePop(&queue);
right = QueueFront(&queue);
QueuePop(&queue);
index = GetIndexDigWay(psl, left, right);
if (left < index - 1)
{
QueuePush(&queue, left);
QueuePush(&queue, index);
}
if (index + 1 < right)
{
QueuePush(&queue, index + 1);
QueuePush(&queue, right);
}
}
QueueDestory(&queue);
}
5.4、快速排序的时间复杂度和稳定性
时间复杂度:O(n*logn);
稳定性:不稳定
6、归并排序
6.1、归并排序概念
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。
6.2、归并排序算法
1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2、设定两个指针,最初位置分别为两个已经排序序列的起始位置
3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4、重复3直到某一指针超出序列尾
5、将另一序列剩下的所有元素直接复制到合并序列尾
6.3、归并排序实现
//MergeSort(归并排序)
void DealMergeSort(SeqList *psl, SeqList *tmp, int start, int end)
{
if (start >= end)
{
return;
}
int mid = (start + end) / 2;
DealMergeSort(psl, tmp, start, mid);
DealMergeSort(psl, tmp, mid + 1, end);
int a = start;
int b = mid + 1;
int c = start;
while (a <= mid && b <= end)
{
if (psl->_array[a] < psl->_array[b])
{
tmp->_array[c] = psl->_array[a];
a++;
}
else
{
tmp->_array[c] = psl->_array[b];
b++;
}
c++;
}
for (; a <= mid; a++)
{
tmp->_array[c] = psl->_array[a];
c++;
}
for (; b <= end; b++)
{
tmp->_array[c] = psl->_array[b];
c++;
}
for (int i = start; i <= end; i++)
{
psl->_array[i] = tmp->_array[i];
}
}
void MergeSort(SeqList *psl)
{
SeqList tmp;
SeqListInit(&tmp, 5000);
DealMergeSort(psl, &tmp, 0, psl->_size);
SeqListDestory(&tmp);
}
6.4、快速排序的时间复杂度和稳定性
时间复杂度:O(n*logn);
稳定性:稳定
7、堆排序
7.1、堆排序概念
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
7.2、堆排序算法
1、将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
2、将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];
3、由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
7.3、堆排序实现
void HeapAdjustDown(SeqList *psl, int root)
{
while (2 * root + 1 < psl->_size)
{
int min;
int left = 2 * root + 1;
int right = 2 * root + 2;
if (right >= psl->_size)
{
min = left;
}
else
{
if (psl->_array[left] > psl->_array[right])
{
min = left;
}
else
{
min = right;
}
}
if (psl->_array[root] < psl->_array[min])
{
Swap(&psl->_array[root], &psl->_array[min]);
root = min;
}
else
{
break;
}
}
}
void HeapSort(SeqList *psl)
{
for (int i = (psl->_size / 2) - 1; i >= 0; i--)
{
HeapAdjustDown(psl, i);
}
int tmp = psl->_size;
while (psl->_size > 0)
{
Swap(&psl->_array[0], &psl->_array[psl->_size - 1]);
psl->_size--;
HeapAdjustDown(psl, 0);
}
psl->_size = tmp;
}
7.4、堆排序的时间复杂度和稳定性
时间复杂度:O(n*logn);
稳定性:不稳定
8、计数排序
8.1、计数排序概念
计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(nlog(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序)
8.2、计数排序算法
1、找出待排序的数组中最大和最小的元素;
2、统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
3、对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
4、反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
8.3、计数排序实现
//CountSort(计数排序)
void CountSort(SeqList *psl)
{
int index = 0;
SeqList tmp;
SeqListInit(&tmp, 5000);
int _max = psl->_array[0];
int _min = psl->_array[0];
for (int i = 0; i < psl->_size; i++)
{
if (psl->_array[i]>_max)
{
_max = psl->_array[i];
}
if (psl->_array[i] < _min)
{
_min = psl->_array[i];
}
}
SeqList count;
SeqListInit(&count, _max - _min + 1);
for (int i = _min; i < _max; i++)
{
SeqListPushBack(&count, 0);
}
for (int i = _min; i < _max; i++)
{
count._array[psl->_array[i] - _min]++;
}
for (int i = _min; i < _max; i++)
{
for (int j = 0; j < count._array[i]; j++)
{
tmp._array[index++] = i;
}
}
for (int i = 0; i < psl->_size; i++)
{
psl->_array[i] = tmp._array[i];
}
SeqListDestory(&count);
SeqListDestory(&tmp);
}
8.4、计数排序的时间复杂度和稳定性
时间复杂度:O(n+k);
稳定性:稳定
9、桶排序
1.1、桶排序概念
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
1.2、桶排序算法
1、人为设置一个BucketSize,作为每个桶所能放置多少个不同数值;
2、遍历输入数据,并且把数据一个一个放到对应的桶里去;
3、对每个不是空的桶进行排序,可以使用其它排序方法,也可以递归使用桶排序;
4、从不是空的桶里把排好序的数据拼接起来。
1.3、桶排序实现
//BucketSort(桶排序)
void BucketSort(SeqList *psl)
{
int index = 0;
SeqList tmp;
SeqListInit(&tmp, 5000);
int _max = psl->_array[0];
int _min = psl->_array[0];
for (int i = 0; i < psl->_size; i++)
{
if (psl->_array[i]>_max)
{
_max = psl->_array[i];
}
if (psl->_array[i] < _min)
{
_min = psl->_array[i];
}
}
SeqList count;
SeqListInit(&count, _max - _min + 1);
for (int i = _min; i < _max; i++)
{
SeqListPushBack(&count, 0);
}
for (int i = _min; i < _max; i++)
{
count._array[psl->_array[i] - _min]++;
}
for (int i = _min; i < _max; i++)
{
for (int j = 0; j < count._array[i]; j++)
{
tmp._array[index++] = i;
}
}
for (int i = 0; i < psl->_size; i++)
{
psl->_array[i] = tmp._array[i];
}
SeqListDestory(&count);
SeqListDestory(&tmp);
}
9.4、桶排序的时间复杂度和稳定性
时间复杂度:O(n+k);
稳定性:稳定
10、基数排序
10.1、基数排序概念
基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog®m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
10.2、基数排序算法
1、取得数组中的最大数,并取得位数;
2、arr为原始数组,从最低位开始取每个位组成radix数组;
3、对radix进行计数排序(利用计数排序适用于小范围数的特点);
10.3、基数排序实现
//RadixSort(基数排序)
int GetDigit(SeqList *psl)
{
int _digit = 1;
int base = 10;
for (int i = 0; i < psl->_size; i++)
{
while (psl->_array[i] >= base)
{
_digit++;
base *= 10;
}
}
return _digit;
}
void RadixSort(SeqList *psl)
{
int index;
int _digit = GetDigit(psl);
int base = 1;
SeqList tmp;
SeqListInit(&tmp, 5000);
SeqList count;
SeqListInit(&count, 10);
for (int i = 0; i < 10; i++)
{
SeqListPushBack(&count, 0);
}
for (int i = 0; i < _digit; i++)
{
for (int j = 0; j < psl->_size; j++)
{
index = (psl->_array[j] / base) % 10;
count._array[index]++;
}
for (int j = 0; j < 10; j++)
{
count._array[j] += count._array[j - 1];
}
for (int j = psl->_array - 1; j >= 0; j--)
{
index = (psl->_array[j] / base) % 10;
tmp._array[count._array[index] - 1] = psl->_array[j];
count._array[index]--;
}
for (int j = 0; j < psl->_size; j++)
{
psl->_array[j] = tmp._array[j];
}
base *= 10;
}
}
10.4、计数排序的时间复杂度和稳定性
时间复杂度:O(n*k);
稳定性:稳定
11、总体实现
Sort.h
#ifndef _SORT_H_
#define _SORT_H_
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include "SeqList.h"
#include "Queue.h"
//交换函数
void Swap(int *x, int *y);
//BubbleSort(冒泡排序)
void BubbleSort(SeqList *psl);
//SelectSort(选择排序)
void SelectSort(SeqList *psl);
//InstertSort(插入排序)
void InstertSort(SeqList *psl);
//ShellSort(希尔排序)
void ShellSort(SeqList *psl);
//MergeSort(归并排序)
void DealMergeSort(SeqList *psl, SeqList *tmp, int start, int end);
void MergeSort(SeqList *psl);
//QuickSort(快速排序)
//寻找基准值下标的方法
//hoare法
int GetIndexHoareWay(SeqList *psl, int left, int right);
//双指针法1
int GetIndexDoublePointWay1(SeqList *psl, int left, int right);
//双指针法2
int GetIndexDoublePointWay2(SeqList *psl, int left, int right);
//挖坑法
int GetIndexDigWay(SeqList *psl, int left, int right);
void DealQuickSort(SeqList *psl, int left, int right);
void QuickSort(SeqList *psl);
//快速排序非递归
void QuickSortNonR(SeqList *psl);
//HeapSort(堆排序)
void HeapAdjustDown(SeqList *psl, int root);
void HeapSort(SeqList *psl);
//CountSort(计数排序)
void CountSort(SeqList *psl);
//BucketSort(桶排序)
void BucketSort(SeqList *psl);
//RadixSort(基数排序)
int GetDigit(SeqList *psl);
void RadixSort(SeqList *psl);
#endif //_SORT_H_
SeqList.h
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "Queue.h"
#define CAPACITY 2
typedef int SLDataType;
//顺序表的动态存储
typedef struct SeqList
{
SLDataType *_array;//指向动态开辟的数组
size_t _size;//有效数据长度
size_t _capacity;//当前容量大小
}SeqList;
//初始化顺序表
void SeqListInit(SeqList *psl, size_t capacity);
//销毁顺序表
void SeqListDestory(SeqList *psl);
//顺序表扩容
void CheckCapacity(SeqList *psl);
//尾插
void SeqListPushBack(SeqList *psl, SLDataType x);
//尾删
void SeqListPopBack(SeqList *psl);
//头插
void SeqListPushFront(SeqList *psl, SLDataType x);
//头删
void SeqListPopFront(SeqList *psl);
//查找元素
int SeqListFind(SeqList *psl, SLDataType x);
//pos位置插入x
void SeqListInsert(SeqList *psl, size_t pos, SLDataType x);
//删除pos位置
void SeqListErase(SeqList *psl, size_t pos);
//删除x
void SeqListRemove(SeqList *psl, SLDataType x);
//修改pos位置为x
void SeqListModify(SeqList *psl, size_t pos, SLDataType x);
//打印顺序表
void SeqListPrint(SeqList *psl);
//顺序表的冒泡排序
void SeqListBubbleSort(SeqList *psl);
//顺序表的二分查找
int SeqListBinarySearch(SeqList *psl, SLDataType x);
//删除顺序表的所有x元素
void SeqListRemoveAll(SeqList *psl, SLDataType x);
//返回顺序表大小
int SeqListSize(SeqList *psl);
#endif//_SEQLIST_H_
Queue.h
#ifndef _QUEUE_H_
#define _QUEUE_H_
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef int QueueDataType;
typedef struct QueueNode
{
struct QueueNode *_next;
QueueDataType _data;
}QueueNode;
typedef struct Queue
{
QueueNode *_front;
QueueNode *_rear;
}Queue;
//初始化
void QueueInit(Queue *pqueue);
//销毁
void QueueDestory(Queue *pqueue);
//为链表开辟结点
QueueNode* BuyQueueNode(QueueDataType x);
//尾插
void QueuePush(Queue *pqueue, QueueDataType x);
//头删
void QueuePop(Queue *pqueue);
//返回队首元素
QueueDataType QueueFront(Queue *pqueue);
//返回队尾元素
QueueDataType QueueRear(Queue *pqueue);
//判空
int QueueEmpty(Queue *pqueue);
//返回队列长度
int QueueSize(Queue *pqueue);
//打印
void QueuePrint(Queue *pqueue);
#endif //_QUEUE_H_
Queue.c
#include "Queue.h"
//初始化
void QueueInit(Queue *pqueue)
{
assert(pqueue);
pqueue->_front = NULL;
pqueue->_rear = NULL;
}
//销毁
void QueueDestory(Queue *pqueue)
{
assert(pqueue);
QueueNode *cur = pqueue->_front;
while (cur)
{
QueueNode *tmp = cur->_next;
free(cur);
cur = tmp;
}
pqueue->_front = NULL;
pqueue->_rear = NULL;
}
//为链表开辟结点
QueueNode* BuyQueueNode(QueueDataType x)
{
QueueNode *queuenode = (QueueNode *)malloc(sizeof(QueueNode));
if (queuenode != NULL)
{
queuenode->_data = x;
queuenode->_next = NULL;
return queuenode;
}
return NULL;
}
//尾插
void QueuePush(Queue *pqueue, QueueDataType x)
{
assert(pqueue);
QueueNode *queuenode = BuyQueueNode(x);
if (QueueEmpty(pqueue))
{
pqueue->_front = queuenode;
pqueue->_rear = queuenode;
}
else
{
pqueue->_rear->_next = queuenode;
pqueue->_rear = queuenode;
}
}
//头删
void QueuePop(Queue *pqueue)
{
assert(pqueue);
QueueNode *tmp = pqueue->_front;
pqueue->_front = tmp->_next;
free(tmp);
tmp = NULL;
}
//返回队首元素
QueueDataType QueueFront(Queue *pqueue)
{
assert(pqueue);
return pqueue->_front->_data;
}
//返回队尾元素
QueueDataType QueueRear(Queue *pqueue)
{
assert(pqueue);
return pqueue->_rear->_data;
}
//判空
int QueueEmpty(Queue *pqueue)
{
assert(pqueue);
return pqueue->_front == NULL;
}
//返回队列长度
int QueueSize(Queue *pqueue)
{
assert(pqueue);
int count = 0;
QueueNode *cur = pqueue->_front;
for (; cur; cur = cur->_next)
{
count++;
}
return count;
}
//打印
void QueuePrint(Queue *pqueue)
{
assert(pqueue);
printf("front <== ");
QueueNode *cur = pqueue->_front;
for (; cur; cur = cur->_next)
{
printf(" %d <==", cur->_data);
}
printf(" real\n");
}
SeqList.c
#include "SeqList.h"
//初始化顺序表
void SeqListInit(SeqList *psl, size_t _capacity)
{
assert(psl);
psl->_capacity = _capacity;
psl->_array = (SLDataType *)malloc(_capacity*sizeof(SLDataType));
assert(psl->_array);
psl->_size = 0;
}
//销毁顺序表
void SeqListDestory(SeqList *psl)
{
assert(psl);
if (psl->_array)
{
free(psl->_array);
psl->_array = NULL;
psl->_capacity = 0;
psl->_size = 0;
}
}
//顺序表扩容
void Check_capacity(SeqList *psl)
{
assert(psl);
if (psl->_size == psl->_capacity)
{
psl->_capacity *= CAPACITY;
psl->_array = (SLDataType *)realloc(psl->_size, psl->_capacity*sizeof(SLDataType));
}
}
//尾插
void SeqListPushBack(SeqList *psl, SLDataType x)
{
assert(psl);
Check_capacity(psl);
psl->_array[psl->_size] = x;
psl->_size++;
}
//尾删
void SeqListPopBack(SeqList *psl)
{
assert(psl || psl->_size);
psl->_size--;
}
//头插
void SeqListPushFront(SeqList *psl, SLDataType x)
{
assert(psl);
Check_capacity(psl);
for (int i = psl->_size - 1; i >= 0; i--)
{
psl->_array[i + 1] = psl->_array[i];
}
psl->_array[0] = x;
psl->_size++;
}
//头删
void SeqListPopFront(SeqList *psl)
{
assert(psl);
psl->_size--;
for (size_t i = 0; i < psl->_size; i++)
{
psl->_array[i] = psl->_array[i + 1];
}
}
//查找元素
int SeqListFind(SeqList *psl, SLDataType x)
{
assert(psl);
for (int i = 0; i < psl->_size; i++)
{
if (psl->_array[i] == x)
{
return i;
}
}
return -1;
}
//pos位置插入x
void SeqListInsert(SeqList *psl, size_t pos, SLDataType x)
{
assert(psl || pos <= psl->_size);
Check_capacity(psl);
for (int i = psl->_size - 1; i >= pos; i--)
{
psl->_array[i + 1] = psl->_array[i];
}
psl->_array[pos] = x;
psl->_size++;
}
//删除pos位置
void SeqListErase(SeqList *psl, size_t pos)
{
assert(psl || pos <= psl->_size);
psl->_size--;
for (int i = pos; i < psl->_size; i++)
{
psl->_array[i] = psl->_array[i + 1];
}
}
//删除x
void SeqListRemove(SeqList *psl, SLDataType x)
{
assert(psl);
size_t pos = SeqListFind(psl, x);
if (pos)
{
SeqListErase(psl, pos);
}
}
//修改pos位置为x
void SeqListModify(SeqList *psl, size_t pos, SLDataType x)
{
assert(psl || pos <= psl->_size);
psl->_array[pos] = x;
}
//打印顺序表
void SeqListPrint(SeqList *psl)
{
for (int i = 0; i < psl->_size; i++)
{
printf("%d ", psl->_array[i]);
}
putchar('\n');
}
//顺序表的冒泡排序
void SeqListBubbleSort(SeqList *psl)
{
assert(psl);
int flag = 0;
for (int i = 0; i < psl->_size - 1; i++)
{
for (int j = 0; j < psl->_size - 1; j++)
{
if (psl->_array[j] > psl->_array[j + 1])
{
SLDataType tmp = psl->_array[j];
psl->_array[j] = psl->_array[j + 1];
psl->_array[j + 1] = tmp;
flag = 1;
}
if (flag == 0)
{
return;
}
}
}
}
//顺序表的二分查找
int SeqListBinarySearch(SeqList *psl, SLDataType x)
{
assert(psl);
int left = 0;
int right = psl->_size - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (psl->_array[mid] < x)
{
left = mid + 1;
}
else if (psl->_array[mid] > x)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
//删除顺序表的所有x元素
void SeqListRemoveAll(SeqList *psl, SLDataType x)
{
assert(psl);
size_t pos = SeqListFind(psl, x);
if (pos == 0 || pos)
{
SeqListErase(psl, pos);
}
}
//返回顺序表大小
int SeqList_size(SeqList *psl)
{
assert(psl);
return (psl->_size >= 0) ? (psl->_size) : (-1);
}
Sort.c
#include "Sort.h"
//交换函数
void Swap(int *x, int *y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
//BubbleSort(冒泡排序)
// O(n^2) O(1) 稳定
void BubbleSort(SeqList *psl)
{
if (psl->_size == 0)
{
return;
}
for (int i = 0; i < psl->_size; i++)
{
for (int j = 0; j < psl->_size - i - 1; j++)
{
if (psl->_array[j] > psl->_array[j + 1])
{
Swap(&psl->_array[j], &psl->_array[j + 1]);
}
}
}
}
//SelectSort(选择排序)
// O(n^2) O(1) 不稳定
void SelectSort(SeqList *psl)
{
if (psl->_size == 0)
{
return;
}
for (int i = 0; i < psl->_size - 1; i++)
{
int min = i;
for (int j = i + 1; j < psl->_size; j++)
{
if (psl->_array[j] < psl->_array[min])
{
min = j;
}
}
Swap(&psl->_array[i], &psl->_array[min]);
}
}
//InstertSort(插入排序)
// O(n^2) O(1) 稳定
// 最坏 O(n^2) 最好 O(n)
void InstertSort(SeqList *psl)
{
if (psl->_size == 0)
{
return;
}
for (int i = 0; i < psl->_size; i++)
{
int tmp = psl->_array[i];
int j;
for (j = i; j > 0 && psl->_array[j - 1] > tmp; j--)
{
psl->_array[j] = psl->_array[j - 1];
}
psl->_array[j] = tmp;
}
}
//ShellSort(希尔排序)
void ShellSort(SeqList *psl)
{
if (psl->_size == 0)
{
return;
}
for (int gap = psl->_size / 2; gap; gap /= 2)
{
for (int k = 0; k < gap; k++)
{
for (int i = k + gap; i < psl->_size; i += gap)
{
int tmp = psl->_array[i];
int j;
for (j = i; j > gap && psl->_array[j - gap] > tmp; j -= gap)
{
psl->_array[j] = psl->_array[j - gap];
}
psl->_array[j] = tmp;
}
}
}
}
//MergeSort(归并排序)
void DealMergeSort(SeqList *psl, SeqList *tmp, int start, int end)
{
if (start >= end)
{
return;
}
int mid = (start + end) / 2;
DealMergeSort(psl, tmp, start, mid);
DealMergeSort(psl, tmp, mid + 1, end);
int a = start;
int b = mid + 1;
int c = start;
while (a <= mid && b <= end)
{
if (psl->_array[a] < psl->_array[b])
{
tmp->_array[c] = psl->_array[a];
a++;
}
else
{
tmp->_array[c] = psl->_array[b];
b++;
}
c++;
}
for (; a <= mid; a++)
{
tmp->_array[c] = psl->_array[a];
c++;
}
for (; b <= end; b++)
{
tmp->_array[c] = psl->_array[b];
c++;
}
for (int i = start; i <= end; i++)
{
psl->_array[i] = tmp->_array[i];
}
}
void MergeSort(SeqList *psl)
{
SeqList tmp;
SeqListInit(&tmp, 5000);
DealMergeSort(psl, &tmp, 0, psl->_size);
SeqListDestory(&tmp);
}
//QuickSort(快速排序)
//寻找基准值下标的方法
//hoare法
int GetIndexHoareWay(SeqList *psl, int left, int right)
{
int a = left + 1;
int b = right - 2;
int mid = (left + right) / 2;
if (psl->_array[left] > psl->_array[mid])
{
Swap(&psl->_array[left], &psl->_array[mid]);
}
if (psl->_array[mid] > psl->_array[right])
{
Swap(&psl->_array[mid], &psl->_array[right]);
}
if (psl->_array[left] > psl->_array[mid])
{
Swap(&psl->_array[left], &psl->_array[mid]);
}
if (right - left <= 2)
{
return mid;
}
Swap(&psl->_array[mid], &psl->_array[right - 1]);
while (a <= b)
{
while (a < right - 1 && psl->_array[a] <= psl->_array[right - 1])
{
a++;
}
while (b > 1 && psl->_array[b] >= psl->_array[right - 1])
{
b--;
}
if (a == b && (a == 1 || a == right - 1))
{
break;
}
if (a < b)
{
Swap(&psl->_array[a], &psl->_array[b]);
}
}
Swap(&psl->_array[a], &psl->_array[right - 1]);
return a;
}
//双指针法1
int GetIndexDoublePointWay1(SeqList *psl, int left, int right)
{
int a = left;
int b = right;
int flag = 0;
while (psl->_array[b] > psl->_array[a])
{
b--;
}
while (a < b)
{
Swap(&psl->_array[a], &psl->_array[b]);
flag = !flag;
while (psl->_array[b] >= psl->_array[a])
{
flag ? a++ : b--;
}
}
return flag ? b : a;
}
//双指针法2
int GetIndexDoublePointWay2(SeqList *psl, int left, int right)
{
int a = left;
int b = right - 1;
int mid = (left + right) / 2;
Swap(&psl->_array[mid], &psl->_array[right]);
while (a <= b)
{
while (a < right && psl->_array[a] <= psl->_array[right])
{
a++;
}
while (b > 0 && psl->_array[b] >= psl->_array[right])
{
b--;
}
if ((a == b) && (a == 0 || a == right))
{
break;
}
if (a < b)
{
Swap(&psl->_array[a], &psl->_array[b]);
}
}
Swap(&psl->_array[a], &psl->_array[right]);
return a;
}
//挖坑法
int GetIndexDigWay(SeqList *psl, int left, int right)
{
SLDataType tmp;
tmp = psl->_array[left];
while (left < right)
{
while (psl->_array[right] >= tmp && left < right)
{
right--;
}
psl->_array[left] = psl->_array[right];
while (psl->_array[left] <= tmp && left < right)
{
left++;
}
psl->_array[right] = psl->_array[left];
}
psl->_array[left] = tmp;
return left;
}
void DealQuickSort(SeqList *psl, int left, int right)
{
if (left >= right)
{
return;
}
int index = GetIndexHoareWay(psl, left, right);
DealQuickSort(psl, left, index - 1);
DealQuickSort(psl, index + 1, right);
}
void QuickSort(SeqList *psl)
{
DealQuickSort(psl, 0, psl->_size - 1);
}
//快速排序非递归
void QuickSortNonR(SeqList *psl)
{
int left;
int right;
int index;
Queue queue;
QueueInit(&queue);
QueuePush(&queue, 0);
QueuePush(&queue, psl->_size - 1);
while (!QueueEmpty(&queue))
{
left = QueueFront(&queue);
QueuePop(&queue);
right = QueueFront(&queue);
QueuePop(&queue);
index = GetIndexDigWay(psl, left, right);
if (left < index - 1)
{
QueuePush(&queue, left);
QueuePush(&queue, index);
}
if (index + 1 < right)
{
QueuePush(&queue, index + 1);
QueuePush(&queue, right);
}
}
QueueDestory(&queue);
}
//HeapSort(堆排序)
void HeapAdjustDown(SeqList *psl, int root)
{
while (2 * root + 1 < psl->_size)
{
int min;
int left = 2 * root + 1;
int right = 2 * root + 2;
if (right >= psl->_size)
{
min = left;
}
else
{
if (psl->_array[left] > psl->_array[right])
{
min = left;
}
else
{
min = right;
}
}
if (psl->_array[root] < psl->_array[min])
{
Swap(&psl->_array[root], &psl->_array[min]);
root = min;
}
else
{
break;
}
}
}
void HeapSort(SeqList *psl)
{
for (int i = (psl->_size / 2) - 1; i >= 0; i--)
{
HeapAdjustDown(psl, i);
}
int tmp = psl->_size;
while (psl->_size > 0)
{
Swap(&psl->_array[0], &psl->_array[psl->_size - 1]);
psl->_size--;
HeapAdjustDown(psl, 0);
}
psl->_size = tmp;
}
//CountSort(计数排序)
void CountSort(SeqList *psl)
{
int index = 0;
SeqList tmp;
SeqListInit(&tmp, 5000);
int _max = psl->_array[0];
int _min = psl->_array[0];
for (int i = 0; i < psl->_size; i++)
{
if (psl->_array[i]>_max)
{
_max = psl->_array[i];
}
if (psl->_array[i] < _min)
{
_min = psl->_array[i];
}
}
SeqList count;
SeqListInit(&count, _max - _min + 1);
for (int i = _min; i < _max; i++)
{
SeqListPushBack(&count, 0);
}
for (int i = _min; i < _max; i++)
{
count._array[psl->_array[i] - _min]++;
}
for (int i = _min; i < _max; i++)
{
for (int j = 0; j < count._array[i]; j++)
{
tmp._array[index++] = i;
}
}
for (int i = 0; i < psl->_size; i++)
{
psl->_array[i] = tmp._array[i];
}
SeqListDestory(&count);
SeqListDestory(&tmp);
}
//BucketSort(桶排序)
void BucketSort(SeqList *psl)
{
int index = 0;
SeqList tmp;
SeqListInit(&tmp, 5000);
int _max = psl->_array[0];
int _min = psl->_array[0];
for (int i = 0; i < psl->_size; i++)
{
if (psl->_array[i]>_max)
{
_max = psl->_array[i];
}
if (psl->_array[i] < _min)
{
_min = psl->_array[i];
}
}
SeqList count;
SeqListInit(&count, _max - _min + 1);
for (int i = _min; i < _max; i++)
{
SeqListPushBack(&count, 0);
}
for (int i = _min; i < _max; i++)
{
count._array[psl->_array[i] - _min]++;
}
for (int i = _min; i < _max; i++)
{
for (int j = 0; j < count._array[i]; j++)
{
tmp._array[index++] = i;
}
}
for (int i = 0; i < psl->_size; i++)
{
psl->_array[i] = tmp._array[i];
}
SeqListDestory(&count);
SeqListDestory(&tmp);
}
//RadixSort(基数排序)
int GetDigit(SeqList *psl)
{
int _digit = 1;
int base = 10;
for (int i = 0; i < psl->_size; i++)
{
while (psl->_array[i] >= base)
{
_digit++;
base *= 10;
}
}
return _digit;
}
void RadixSort(SeqList *psl)
{
int index;
int _digit = GetDigit(psl);
int base = 1;
SeqList tmp;
SeqListInit(&tmp, 5000);
SeqList count;
SeqListInit(&count, 10);
for (int i = 0; i < 10; i++)
{
SeqListPushBack(&count, 0);
}
for (int i = 0; i < _digit; i++)
{
for (int j = 0; j < psl->_size; j++)
{
index = (psl->_array[j] / base) % 10;
count._array[index]++;
}
for (int j = 0; j < 10; j++)
{
count._array[j] += count._array[j - 1];
}
for (int j = psl->_array - 1; j >= 0; j--)
{
index = (psl->_array[j] / base) % 10;
tmp._array[count._array[index] - 1] = psl->_array[j];
count._array[index]--;
}
for (int j = 0; j < psl->_size; j++)
{
psl->_array[j] = tmp._array[j];
}
base *= 10;
}
}
main.h
#include "Sort.h"
#include "SeqList.h"
#include "Queue.h"
int main()
{
SeqList seqlist;
SeqListInit(&seqlist, 5000);
//srand((unsigned int)time(NULL));
for (int i = 0; i < 5000; i++)
{
int num = rand() % 5000 + 1;
SeqListPushBack(&seqlist, num);
}
BubbleSort(&seqlist);
SeqListPrint(&seqlist);
SelectSort(&seqlist);
SeqListPrint(&seqlist);
InstertSort(&seqlist);
SeqListPrint(&seqlist);
ShellSort(&seqlist);
SeqListPrint(&seqlist);
MergeSort(&seqlist);
SeqListPrint(&seqlist);
QuickSort(&seqlist);
SeqListPrint(&seqlist);
QuickSortNonR(&seqlist);
SeqListPrint(&seqlist);
HeapSort(&seqlist);
SeqListPrint(&seqlist);
CountSort(&seqlist);
SeqListPrint(&seqlist);
BucketSort(&seqlist);
SeqListPrint(&seqlist);
RadixSort(&seqlist);
SeqListPrint(&seqlist);
system("pause");
return 0;
}