几种常见的排序算法:选择排序、插入排序、冒泡排序、希尔排序、快速排序、归并排序。
1、选择排序
基本思想:每一趟(例如第i趟,i=0,1,...,n-2),在后面的n-i个待排的数据元素中选出关键字(最小的元素),作为有序元素序列的第i个元素。
排序过程:
排序算法:
void myswap(int a[], int& i, int& j)
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
//选择排序
void SelectSort(int a[], int len)
{
int i = 0;
int j = 0;
for (i = 0; i < len; i++)
{
for (j = i + 1; j < len; j++)
{
if (a[i] > a[j])
{
myswap(a, i, j);
}
}
}
}
2、插入排序
基本思想:v[0],v[1],...,v[i-1]已经排好序,这时,用v[i]的关键字与v[i-1],v[i-2]的关键字进行比较,找到插入的位置即将v[i]插入,原来位置上的对象向后顺移。
插入排序的关键点:1、拿出一个元素,留出位置;2、符合条件的元素后移
排序过程:
排序算法:
void InsertSort(int a[], int len)
{
int i = 0;
int j = 0;
int k = 0;
for (i = 1; i < len; i++)
{
k = i; //待插入的位置
int tmp = a[k];
for (j = i - 1; (j >= 0)&&(tmp < a[j]); j--)
{
a[j + 1] = a[j];
k = j; //插入位置
}
a[k] = tmp;
}
}
3、冒泡排序
排序过程:
主要是相邻接点进行比较。
排序算法:
void BubbleSort(int a[], int len)
{
int i = 0;
int j = 0;
bool sort_tag = true; //是否排好序的标志,true:未排好序,false:排好序
for (int k = 0; k < len && sort_tag; k++)
{
sort_tag = false; //每一趟默认排好序
for (i = 0; i < len - 1; i++)
{
j = i + 1;
if (a[i] > a[j])
{
myswap(a, i, j);
sort_tag = true; //只要发生了数据交换,就说明这一趟之前未排好序
}//未发生任何交换,则说明已经排好序了,下一趟没必要执行了,sort_tag仍为false
}
}
}
4、希尔排序
基本思想:
1)、先取一个正整数d1<n,把所有相隔d1的记录放一组,组内进行直接插入排序;
2)、然后取d2<d1,重复上述分组和排序操作;直至di=1,即所有记录放进一个组中排序为止。
3)、算法复杂度O(nlogn);希尔排序是不稳定的。d0=len,d(i) = d(i-1)/3+1 //业界公认
排序过程:
排序算法:
void ShellSort(int a[], int len)
{
int i = 0;
int j = 0;
int k = 0;
int gap = len;
do
{
gap = gap / 3 + 1;
for (i = gap; i < len; i++)
{
k = i; //待插入的位置
int tmp = a[k];
for (j = i - gap; (j >= 0) && (tmp < a[j]); j-=gap)
{
a[j + gap] = a[j];
k = j; //插入位置
}
a[k] = tmp;
}
} while (gap > 1);
}
分组化的插入排序,常规插入排序的间隔是1,希尔排序中插入排序的间隔是gap,gap是变化的。
5、快速排序
基本思想:快速排序是对冒泡排序的一种改进。
1)、通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据要小,基准数据排在这两个子序列的中间;
2)、然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列;
3)、算法复杂度:O(nlogn);不稳定分组
递归地把数据分成两部分、partition
排序过程:
排序算法:
int partition(int a[], int low, int high)
{
int tar = a[low];
while (low < high)
{
//low上是tar
while ((low < high) && (a[high] >= tar))
high--;
myswap(a, low, high); //交换之后high上是tar
while ((low < high) && (a[low] <= tar))
low++;
myswap(a, low, high); //再次交换后low上是tar
}
return low;
}
void sort(int a[], int low, int high)
{
if(low<high)
{
int mid_index = partition(a, low, high);
sort(a, low, mid_index-1); //左侧
sort(a, mid_index + 1, high); //右侧
}
}
//快速排序
void QuickSort(int a[], int len)
{
int low = 0;
int high = len-1;
sort(a, low, high);
}
6、归并排序
基本思想:将两个或两个以上的有序序列合并成一个新的有序序列;
排序过程:
排序算法:
void Merge(int src[], int des[], int low, int mid, int high)
{
int i = low;
int j = mid + 1;
int k = low;
while ((i <= mid) && (j <= high))
{
if (src[i] < src[j])
{
des[k++] = src[i++];
}
else
{
des[k++] = src[j++];
}
}
while (i <= mid) //若还剩几个尾部元素
{
des[k++] = src[i++];
}
while (j <= high) //若还剩几个尾部元素
{
des[k++] = src[j++];
}
}
void mSort(int src[], int des[], int low, int high, int max)
{
if (low == high) //只有一个元素时,不需要归并,结果直接赋给des[low]
{
des[low] = src[low];
}
else //如果有多个元素,则进行两路归并
{
int mid = (low + high) / 2;
int* space = (int*)malloc(sizeof(int)*max);
//递归进行两路,两路划分
//当剩下一个元素时,递归划分结束,然后开始merge归并操作
if (nullptr != space)
{
mSort(src, space, low, mid, max);
mSort(src, space, mid+1, high, max);
Merge(space, des, low, mid, high); //调用归并函数进行归并
}
free(space);
}
}
void MergeSort(int a[], int len)
{
mSort(a, a, 0, len-1, len);
}
7、排序方法比较
关于具体的排序算法实现细节可以参考:https://download.csdn.net/download/bailang_zhizun/12670773