记一下
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <io.h>
#include <math.h>
#include <time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAX_LENGTH_INSERT_SORT 7 /* 用于快速排序时判断是否选用插入排序阙值 */
typedef int Status;
#define MAXSIZE 10000 /* 用于要排序数组个数最大值,可根据需要修改 */
typedef struct {
int r[MAXSIZE + 1]; /* 用于存储要排序数组,r[0]用作哨兵或临时变量 */
int length; /* 用于记录顺序表的长度 */
}SqList;
/* 交换L中数组r的下标为i和j的值 */
void swap(SqList *L, int i, int j) {
int temp = L->r[i];
L->r[i] = L->r[j];
L->r[j] = temp;
}
#pragma region 交换
//低端冒泡_从前往后 一个个位置排,找小的上来,大的下去
void BubbleSort0(SqList *L) {
int i, j;
for (i = 1; i < L->length; i++) {//这里把0当哨兵
for (j = i + 1; j <= L->length; j++) {//和现在位置之后的每个比
if (L->r[i] > L->r[j]) {//后面的小?换到现在的位置
swap(L, i, j);
}
}
}
}
//普通冒泡_从后往前,对比邻居,小的会一点点浮上来 大的下去同理,j 1到length-i
void BubbleSort(SqList *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);
}
}
}
}
//优化冒泡_没有数据交换,flag不变成true,说明已经有序 可以结束
void BubbleSort2(SqList *L) {
int i, j;
Status flag = TRUE;
for (i = 1; i < L->length&&flag; i++) {
flag = FALSE;
for (j = L->length - 1; j >= i; j--) {
if (L->r[j] > L->r[j + 1]) {
swap(L, j, j + 1);
flag = TRUE;
}
}
}
}
/********************************************/
void QSort(SqList *L, int low, int high);
int Paritition(SqList *L, int low, int high);
//快速排序
void QuickSort(SqList *L) {
QSort(L, 1, L->length);
}
void QSort(SqList *L, int low, int high) {
int pivot;
if (low < high) {
pivot = Paritition(L, low, high);
QSort(L, low, pivot - 1);
QSort(L, pivot + 1, high);
}
}
int Paritition(SqList *L, int low, int high) {
int pivotkey;
pivotkey = L->r[low];//用low的时候,下面先从high往左;用high,下面先从low往右
while (low < high) {
while (low < high&&pivotkey <= L->r[high])//右边更大,通过检验
high--;//下一个。
swap(L, low, high);//每次循环最多查一个更大的换右边去
while (low < high&&pivotkey >= L->r[low])
low++;
swap(L, low, high);//每次循环最多查一个更小的换左边去
}
return low;
}
/* 改进后快速排序******************************** */
/* 快速排序优化算法 */
int Partition1(SqList *L, int low, int high) {
int pivotkey;
int m = low + (high - low) / 2; /* 计算数组中间的元素的下标 */ /*new*/
if (L->r[low] > L->r[high])
swap(L, low, high); /* 交换左端与右端数据,保证左端较小 */ /*new*/
if (L->r[m] > L->r[high])
swap(L, high, m); /* 交换中间与右端数据,保证中间较小 */ /*new*/
if (L->r[m] > L->r[low])
swap(L, m, low); /* 交换中间与左端数据,保证左端较小 */ /*new*/
pivotkey = L->r[low]; /* 用子表的第一个记录作枢轴记录 */
L->r[0] = pivotkey; /* 将枢轴关键字备份到L->r[0] */ /*new*/
while (low < high) /* 从表的两端交替地向中间扫描 */
{
while (low < high&&L->r[high] >= pivotkey)
high--;
L->r[low] = L->r[high]; /*new*/
while (low < high&&L->r[low] <= pivotkey)
low++;
L->r[high] = L->r[low]; /*new*/
}
L->r[low] = L->r[0]; /*new*/
return low; /* 返回枢轴所在位置 */
}
void QSort1(SqList *L, int low, int high) {
int pivot;
if ((high - low) > MAX_LENGTH_INSERT_SORT) { /*new*/
while (low < high) { /*new*/
pivot = Partition1(L, low, high); /* 将L->r[low..high]一分为二,算出枢轴值pivot */
QSort1(L, low, pivot - 1); /* 对低子表递归排序 */
/* QSort(L,pivot+1,high); /* 对高子表递归排序 */
low = pivot + 1; /* 尾递归 */ /*new*/
}
} else
InsertSort(L);//快排要用到递归,在小数组时,大炮打蚊子也许不如简单排序中性能最好的直接插入
}
/* 对顺序表L作快速排序 */
void QuickSort1(SqList *L) {
QSort1(L, 1, L->length);
}
#pragma endregion
#pragma region 选择
//简单选择_单次循环里选一个最小的,换到当前位置
void SelectSort(SqList *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);
}
}
/********************************************/
void HeapAdjust(SqList *L, int s, int m);//s是顶部,m是下限
//堆排序
void HeapSort(SqList *L) {
int i;
for (i = L->length / 2; i > 0; i--)
HeapAdjust(L, i, L->length);
for (i = L->length; i > 1; i--) {
swap(L, 1, i);//最大放到<当前>最后
HeapAdjust(L, 1, i - 1);//第一个不是最大了,重新调
}
}
void HeapAdjust(SqList *L, int s, int m) {//s是顶部,m是下限
int temp, j;
temp = L->r[s];
for (j = 2 * s; j <= m; j *= 2) {//子是2i和2i+1
if (j < m&&L->r[j] < L->r[j + 1])
j++;
if (temp >= L->r[j]) //下沉到没刚才的顶小为止
break;
L->r[s] = L->r[j];
s = j;//值上去,s顶部标记继续往下走
}
L->r[s] = temp;
}
#pragma endregion
#pragma region 插入
//直接插入
void InsertSort(SqList *L) {
int i, j;
for (i = 2; i <= L->length; i++) {//选要处理的值
if (L->r[i] < L->r[i - 1]) {//比前面的小
L->r[0] = L->r[i]; //设置哨兵
for (j = i - 1; L->r[j] > L->r[0]; j--)//如果比待处理的值大
L->r[j + 1] = L->r[j];//移到后面
L->r[j + 1] = L->r[0];//j--后退出了循环,j+1位移动到了j+2位置,j+1正空缺
}
}
}
void BinaryInsertSort(SqList *L) {
int i, j;
int low, high, mid;
for (i = 2; i <= L->length; i++) {//选要处理的值
L->r[0] = L->r[i];
low = 1;
high = i - 1;
while (low <= high) {
mid = (low + high) / 2;
if (L->r[mid] > L->r[0])
high = mid - 1;//比待处理还大,继续找
else low = mid + 1;
}
for (j = i - 1; j >= high + 1; j--)
L->r[j + 1] = L->r[j];
L->r[high + 1] = L->r[0];
}
}
/********************************************/
//希尔排序
void ShellSort(SqList *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]) {//反着来!以增量后面的i为标杆
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];//把j放到后面 第一波是i-cre放到i,第二波是更前面的后移
L->r[j + increment] = L->r[0];//这时候j是小于0,加回increment,到队列中的刚才位置
}
}
} while (increment > 1);
}
#pragma endregion
#pragma region 归并
void Merge(int SR[], int TR[], int low, int mid, int high);
void MSort(int SR[], int TR1[], int low, int high);
//二路归并
void MergeSort(SqList* L) {
MSort(L->r, L->r, 1, L->length);
}
void MSort(int SR[], int TR1[], int low, int high) {
int mid;
int TR2[MAXSIZE + 1];
if (low == high) TR1[low] = SR[low];
else {
mid = (low + high) / 2;
MSort(SR, TR2, low, mid);
MSort(SR, TR2, mid + 1, high);
Merge(TR2, TR1, low, mid, high);
}
}
void Merge(int SR[], int TR[], int low, int mid, int high) {//第二个参数是目标
int i = low, j = mid + 1, k = low;
while (i <= mid && j <= high) {
if (SR[i] < SR[j]) TR[k++] = SR[i++];
else TR[k++] = SR[j++];
}//一个指针到头,循环结束,剩下的放进来
while (i <= mid) TR[k++] = SR[i++];
while (j <= high) TR[k++] = SR[j++];
}
//非递归归并
void MergePass(int SR[], int TR[], int low, int high) {//第二个参数是目标
int i = 1;
int j;
while (i <= high - 2 * low + 1) {//一二序列、三四序列..
Merge(SR, TR, i, i + low - 1, i + 2 * low - 1);
i = i + 2 * low;
}
if (i < high - low + 1) Merge(SR, TR, i, i + low - 1,high);
else
for (j = i; j <= high; j++)
TR[j] = SR[j];
}
void MergeSort2(SqList *L) {//从最小序列开始
int* TR = (int*)malloc(L->length * sizeof(int));/* 申请额外空间 */
int k = 1;
while (k < L->length) {
MergePass(L->r, TR, k, L->length);//Lr归并n个子序列到TR
k = 2 * k;/* 子序列长度加倍 */
MergePass(TR, L->r, k, L->length);//TR归并更少但更长的序列回到LR
k = 2 * k;/* 子序列长度加倍 */
}
}
#pragma endregion
void print(SqList L) {
int i;
for (i = 1; i < L.length; i++)
printf("%d,", L.r[i]);
printf("%d", L.r[i]);
printf("\n");
}
#define N 9
int main() {
int d[N] = { 50,10,90,30,70,40,80,60,20 };
SqList test;
for (int i = 0; i < N; i++)
test.r[i + 1] = d[i];
test.length = N;
printf("排序前:\n");
print(test);
printf("排序:\n");
MergeSort2(&test);
print(test);
getchar();
}