总结一些算法的实现:
交换排序*****
1.冒泡算法
typedef struct arr1
{
int data;
int key; //关键字项必须能比较大小
}arr1;
void BubbleSort(arr1 goal[], int n)
{
int i;
int j;
arr1 tmp;
bool flag;
for (i = 0; i < n - 1; ++i)//每次循环确定一个最小数排在最前面,每次得出的有序区都是全局有序
{
flag = false;
for (j = n - 1; j > i; --j) //遍历一次元素数为n的数组,22对比,得出最小的排在前面
{
if (goal[j].key < goal[j - 1].key) //这要用j-1,因为j+1超过数组下标了。
{
tmp = goal[j];
goal[j] = goal[j - 1];
goal[j - 1] = tmp;
flag = true; // 有交换时证明没有排序完
}
}
if (!flag) // m没有交换时证明排玩了,跳出循环结束排序。
return;
}
}
2.快速排序
//时间复杂度为O(nlog2n),空间复杂度为O(log2n);
void QuickSort(arr1 goal[], int s, int t)
{
int i, j;
arr1 tmp;
//s t是数组的开始和结束
i = s;
j = t;
if (s < t)
{
tmp = goal[i]; //第一个中心,中心用哪个都得
while (i != j)
{
while (j > i && goal[j].key >= tmp.key) //把小于中心标志的数抛到左边
{
--j;
}
goal[i] = goal[j];
while (i < j && goal[i].key < tmp.key) //把大于中心标志的数抛到右边
{
++i;
}
goal[j] = goal[i];
}
goal[i] = tmp; // 当i = j时跳出循环,这时i和前面的某个值是一样的,
//把他换为tmp的中心标志,这样一轮的替换完成,左边小于tmp,右边大于tmp
QuickSort(goal, s, i - 1); //对左区间递归
QuickSort(goal, i + 1, t); //对右区间递归
}
}
插入排序*****
3.直接插入
//该算法的时间复杂度最坏的情况是倒序时的O(n2),最好是正序时的O(n);其平均复杂度是O(n2)
void InsertSort1(arr1 goal[], int n)
{
int i;
int j;
arr1 tmp;
for (i = 1; i < n; ++i)
{
tmp = goal[i]; //第一轮是arr【1】,因为用第一项来做最开始的对比,之后就慢慢插入
j = i - 1; //新的有序区范围
while (j >= 0 && tmp.key < goal[j].key) // 遍历查找tmp的插入下标
{
goal[j + 1] = goal[j]; //因为要插入元素,后面的元素要往后挪动
j--;
}
goal[j + 1] = tmp; //向有序区插入
}
}
4.希尔排序
//直接排序法的一种,时间复杂度一般认为是O(n1.3),一般是最后一趟出有序区,他是不稳定的排序(还没有想向出他的插入图)
void InsertSort3(arr1 goal[], int n)
{
int i;
int j;
int gap;
arr1 tmp;
gap = n/2; //初始增量
while (gap > 0)
{
//确定增量之后用直接插入法
for (i = gap; i < n; ++i)
{
tmp = goal[i]; //第一轮是arr【1】,因为用第一项来做最开始的对比,之后就慢慢插入
j = i - gap;
while (j >= 0 && tmp.key < goal[j].key) // 遍历查找tmp的插入下标
{
goal[j + gap] = goal[j];
j = j - gap; //j是一个增量一个增量的减少(可以说吧希尔的增量变为1就是直接插入)
}
goal[j + gap] = tmp; //向有序区插入
}
gap = gap / 2; //减小增量
}
}
选择排序*****
5.直接选择
//和冒泡差不多,就是把排序放到外循环,使得可以定一个需要的有序区。
void SelectSort(arr1 goal[], int n)
{
int i, j, k;
arr1 tmp;
for (i = 0; i < n; ++i) //在这里定一个需要的有序区,例如在10000个数理找最小的前10个数,就是把n设为10;
{
k = i;
for (j = i + 1; j < n - 1; ++j)
{
if (goal[j].key < goal[k].key)
{
k = j; //确定最小值的下标
}
}
if (k != i) //排序
{
tmp = goal[i];
goal[i] = goal[k];
goal[k] = tmp;
}
}
}
6.归并排序
//2路归并排序
void Merge(arr1 goal[], int low, int mid, int hight)
{
arr1 *R1;
int i = low, j = mid + 1, k = 0; //k是R1的下标, i,j分别是1,2段的下标
R1 = new arr1[hight - low + 1]();
while (i <= mid && j <= hight)
{
if (goal[i].key <= goal[j].key) //将第一段复制到R1
{
R1[k] = goal[i];
++i, ++k;
}
else //将第二段复制到R1
{
R1[k] = goal[j];
++j, ++k;
}
}
while (i <= mid) //将第一段余下部分复制到R1
{
R1[k] = goal[i];
++i, ++k;
}
while (j <= hight) //将第二段余下部分复制到R1
{
R1[k] = goal[j];
++j, ++k;
}
for (k = 0, i = low; i <= hight; k++, i++) //将R1复制会goal中
{
goal[i] = R1[k];
}
delete[] R1;
}
void MergePass(arr1 goal[], int lenght, int n) //对整个表进行归并
{
int i;
for (i = 0; i + 2 * lenght - 1 < n; i = i + 2 * lenght) //归并lenght长度的2个表
{
Merge(goal, i, i + lenght - 1, i + lenght * 2 - 1); //
}
if (i + lenght - 1 < n) //余下这2个表的长度,后者小于lenght,归并这2个表
{
Merge(goal, i, i + lenght - 1, n - 1);
}
}
//二路归并排序
void MergeSort(arr1 goal[], int n)
{
int lenght;
for (lenght = 1; lenght < n; lenght = 2 * lenght)
{
MergePass(goal, lenght, n);
}
}