#include <iostream>
#define MAXSIZE 10
typedef struct
{
int r[MAXSIZE + 1];//用于存储排序的数组,r[0]用作哨兵或临时变量
int length; //用于记录顺序表的长度
}SqlList;
void swap(SqlList* L, int i, int j)
{
int temp = L->r[i];
L->r[i] = L->r[j];
L->r[j] = temp;
}
/*
基本思想:从头开始将每个元素与后面的每个元素比较,将较小的放在当前位置,这样下来就将最小的元素放在了当前位置
但前面排好的对后面的没有作用,也许较小的放到后面了
*/
void BubbleSort0(SqlList* L)
{
int i, j;
for (i = 1; i < L->length; ++i)
{
for (j = i + 1; j <= L->length; ++j)
{
if (L->r[i] > L->r[j])
{
swap(L, i, j); //交换i和j对应元素的值
}
}
}
}
//从后往前比较
void BubbleSort(SqlList* L)
{
int i, j;
for (i = 1; i < L->length; ++i)
{
for (j = L->length - 1; j >= i; j--)
{
if (L->r[j] > L->r[j + 1])
{
swap(L, j, j + 1);
}
}
}
}
//从前往后比较
void BubbleSort1(SqlList* L)
{
int i, j;
bool bFalg = true;//如果一次比较没变动直接退出循环,提高效率
for (i = 1; i < L->length && bFalg; ++i)
{
bFalg = false;
for (j = 1; j <= L->length - i; ++j)
{
if (L->r[j] > L->r[j + 1])
{
swap(L, j, j + 1);
bFalg = true;
}
}
}
}
/*
选择排序,从前往后记录最小位置,然后找出后面最小的然后和当前位置交换,这个是比较次数较多,外层for只进行一次比较
*/
void SelectSort(SqlList* L)
{
int i, j, min;
for (i = 1; i < L->length; ++i)
{
min = i;
for (j = i + 1; j <= L->length; ++j)
{
if (L->r[min] > L->r[j])
{
min = j;
}
}
}
if (i != min)
{
swap(L, i, min);
}
}
/*
基本思想:先假定前面排好序,然后将要排序的插入到前面有序的数组中
o(n2)性能比冒泡和简单选择排序性能要好
*/
void InsertSort(SqlList* L)
{
for (int i = 2; i < L->length; ++i)
{
L->r[0] = L->r[i];//当前元素存储在哨兵中
int j;
for (j = i - 1; j >= 1; --j)
{
if (L->r[j] > L->r[0])
{
L->r[j + 1] = L->r[j];
}
else
{
break;
}
}
L->r[j + 1] = L->r[0];
}
}
int Partition(SqlList* L, int low, int high)
{
int val = L->r[low];// 存放要分割的值
while (low < high && L->r[high] > L->r[low])//先进行high移动,只要比分割值大就左移
high--;
swap(L, low, high);//对应的值小于分割值,则进行替换l对应值
while (low < high && L->r[low] < L->r[high])//进行low移动,比分割之小右移
low++;
swap(L, low, high);//如果大于分割值替换h对应值
return low;
}
void QSort(SqlList* L, int low, int high)
{
int pivot;
if (low < high)
{
pivot = Partition(L, low ,high);
//左右部分的排序
QSort(L, low, pivot - 1);
QSort(L, pivot + 1, high);
}
}
/*
先选择轴值,左右指针,如果右边的索引比轴值小往做移动,然后比较左边,如果左边的索引比轴值大往右移动,当左索引和右索引相等时该位置就是轴值呆的地方
然后再比较轴值左边的,在比较轴值右边的
通过一趟将待排序的记录,将记录分割成两部分,一部分比另一部分小,接下来再进行左右两部分记录的排序
*/
void QuickSort(SqlList* L)
{
QSort(L, 1, L->length);
}
/*
基本思想:每次按照跨度排序,然后这个跨度不断的减小,每次排序内部是插入排序
插入排序对于基本有序和较短的序列有较高的效率,时间复杂度为n1.5次方
并且这个跨度有限制的,例如除以二递减还是n2方的
*/
void ShellSort(SqlList* L)
{
int i, j;
int increment = L->length;
do
{
increment = increment / 3 + 1;//增量选择
for (i = increment + 1; i <= L->length; i++)
{
if (L->r[i] < L->r[i - increment])//内部就是根绝增量的插入排序
{
L->r[0] = L->r[i];
for (j = i - increment; j > 0 && L->r[0] < L->r[j]; j -= increment)
{
L->r[j + increment] = L->r[j];
}
L->r[j + increment] = L->r[0];
}
}
}
while (increment > 1);
}
void MSort(int SR[], int TR1[], int s, int t)
{
int m;
int TR2[MAXSIZE + 1];
if (s == t)
{
TR1[s] = SR[s];
}
else
{
s = (s + t) / 2;
MSort(SR, TR2, s, m);
MSort(SR, TR2, m + 1, t);
//Merge(TR2, TR1, s, m, t);未实现看大话
}
}
/*
看这个归并排序很复杂,程序更是复杂,能写出来的也是牛B
3 4 21 45 52 134 4 67 45 34
3 4 21 45 52 134 4 67 45 34
3 4 21 45 52 134 4 67 45 34
3 4 21 45 52 134 4 67 45 34
3 4 21 45 52 4 134 34 45 67
3 4 21 45 52 4 34 45 67 134
3 4 4 21 34 45 45 52 67 134
其大体思想就是先进行对半分割,然后再两两合并排序一直到所有的都排序了
*/
void MergeSort(SqlList* L)
{
MSort(L->r, L->r, 1, L->length);
}
/*
堆排序(理解思路就行了,写就算了)
先将待排序的数字建成最小值堆,建立最小值堆的速度还是挺快的
堆:分为大根堆和小根堆,属于完全二叉树(完全二叉树可以用数组存储)
加入要从小排序,就每次从根节点取,最从小排序了
*/
/*
优先队列:好像是二叉树实现的
散列表(哈希表):用哈希函数计算存储数据的地址
*/
int main()
{
SqlList qList;
int num[MAXSIZE] = {9, 1, 5, 8, 3, 7, 4, 6, 2, 10};
memcpy(&qList.r[1], &num[0], MAXSIZE * sizeof(int));
qList.length = MAXSIZE;
//BubbleSort0(&qList);
//BubbleSort(&qList);
//BubbleSort1(&qList);
//InsertSort(&qList);
//QuickSort(&qList);
ShellSort(&qList);
for (auto j : qList.r)
{
std::cout << j << " ";
}
getchar();
return 0;
}