内排序算法所涉及的结构体类型
typedef int KeyType;
typedef char InfoType;
typedef struct
{
KeyType key;
//InfoType otherinfo;
}RecType;
时间处理--计算排序所花费的时间
LARGE_INTEGER nFreq;
LARGE_INTEGER nBeginTime;
LARGE_INTEGER nEndTime;
double T;
srand(time(0));
cout.setf(ios::fixed);
Random(R, 80);
cout << "\n冒泡排序" << endl;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
BubbleSort(R, 80);
QueryPerformanceCounter(&nEndTime);
T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
Disp(R, 80);
cout << "\n\n";
随机数生成
void Random(RecType *R,int n)
{
cout << "排序前" << endl;
for (int i = 0; i < n; i++)
{
R[i].key = rand() % 10000;
cout<<R[i].key<<" ";
}
}
一、插入排序
1.简单插入排序
void InsertSort(RecType R[], int n)
{
int i, j;
RecType tmp;
for (i = 1; i < n; i++)//比较n-1次
{
if (R[i].key < R[i - 1].key)//反序时
{
tmp = R[i];
j = i - 1;
do //寻找R[i]的插入位置
{
R[j + 1] = R[j];//将关键字大于R[i].key的记录后移
j--;
} while (j >= 0 && R[j].key > tmp.key);//
R[j + 1] = tmp; //在j+1处插入R[i].
}
}
}
2.折半插入排序
因为每次排序时,前面是有序区(局部有序),可以采用折半查找的思想,找到相应的位置,再进行元素的插入。
void BinInsertSort(RecType R[],int n)
{
int i, j, low, high, mid;
RecType tmp;
for (i = 1; i < n; i++)//比较n-1次
{
if (R[i].key < R[i - 1].key) //反序时
{
low = 0;
high = i-1;
tmp = R[i]; //将R[i]保存到tmp中
while (low <= high) //寻找查找位置
{
mid = (high + low) / 2; //取中间位置
if (tmp.key > R[mid].key)
{
low = mid + 1; //插入点在右半区
}
else
{
high = mid - 1; //插入点在左半区
}
} //找位置high+1
for (j = i - 1; j >= high + 1; j--)
{
R[j + 1] = R[j];
}
R[high + 1] = tmp; //插入tmp
}
}
}
3.希尔排序
void ShellSort(RecType R[],int n)//希尔排序算法
{
int i, j, d;
RecType tmp;
d = n / 2; //增量置初值
while (d > 0)
{
for (i = d; i < n; i++) //对所有组采用直接插入排序
{
tmp = R[i]; //对相隔位置为d的一组进行直接插入排序
j = i - d;
while (j>=0 && tmp.key>R[j].key)
{
R[j + 1] = R[j];
j = j - d;
}
R[j + d] = tmp;
}
d /= 2; //减小增量
}
}
二、交换排序
1.冒泡排序
void BubbleSort(RecType R[], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = n-1; j >0; j--) //将R[i]元素归位
{
if (R[j].key > R[j-1].key) //相邻的两个元素反序时
{
RecType temp = R[j]; //将R[j]和R[j-1]进行交换
R[j ] = R[j-1];
R[j-1] = temp;
}
}
}
}
2.快速排序
采用了递归的思想
注意递归的出口,每次递归的参数
a. Partition(RecType R[],int s,int t);获取已排序完成的元素的位置--此处是全局有序(归位)。
b.QuickSort(RecType R[],int s,int t);反复递归,直到只剩下一个元素,即有序。
int Partition(RecType R[],int s,int t)
{
int i = s, j = t;
RecType base = R[i];
while (i < j)
{
while (j > i && R[j].key >= base.key)
{
j--;
}
if (R[j].key < base.key)
{
R[i] = R[j];
i++;
}
while (j > i && R[i].key <= base.key)
{
i++;
}
if (R[i].key > base.key)
{
R[j] = R[i];
j--;
}
}
R[i] = base;
return i;
}
void QuickSort(RecType R[],int s,int t)
{
int i;
if (s < t)
{
i = Partition(R, s, t);
QuickSort(R, s, i - 1);
QuickSort(R, i + 1, t);
}
}
三、选择排序
1.选择排序
void SortAlgorithm(RecType R[], int n)
{
for (int i = 0; i < n; i++)
{
int minindex = i;
for (int j = i + 1; j < n; j++)
{
if (R[minindex].key > R[j].key)
{
minindex = j;
}
}
RecType temp = R[i];
R[i] = R[minindex];
R[minindex] = temp;
}
}
2.堆排序
此排序涉及大小根堆等相关概念。
排序开始,先初始化一个大根堆
接着不断地交换根节点的元素,此过程中,会不断通过sift函数进行根堆的调整。(复杂)
//堆排序 -- 树形选择排序方法
void sift(RecType R[], int low, int high)
{
int i = low, j = 2 * i; //R[j]是R[i]的左孩子
RecType tmp = R[i];
while (j <= high)
{
if (j < high && R[j].key < R[j + 1].key)//若右孩子较大,则j指向右孩子
{
j++;
}
if (tmp.key < R[j].key) //若根结点小于最大孩子的关键字
{
R[i] = R[j]; //将R[j]调整到双亲结点位置上
i = j; //修改i和j值,以便继续向下筛选
j = 2 * i;
}
else break; //若根节点大于或等于最大孩子的关键字,筛选结束
}
R[i] = tmp; //被筛选节点放到最终位置上
}
void HeapSort(RecType R[],int n)
{
int i;
for (i = n / 2; i >= 1; i--)
{
sift(R, i, n); //循环建立初始堆,调用sift算法
}
for (i = n; i >= 2; i--) //进行n-1趟完成堆排序,每一趟堆的元素个数-1
{
swap(R[1], R[i]); //将最后一个元素与根R[1]交换
sift(R, 1, i - 1); //将R[1…i-1]进行筛选,得到i-1个结点的堆
}
}
四、完整代码实现
注意:代码中有两个Random,两个Disp(堆排序的缘故),目前只能做到这样,水平有限,希望获得宝贵的意见。
#include<iostream>
using namespace std;
#define MAXL 100
#include <ctime>
#include <windows.h>
#include <iomanip>
typedef int KeyType;
typedef char InfoType;
typedef struct
{
KeyType key;
//InfoType otherinfo;
}RecType;
//交换排序
//冒泡排序
void BubbleSort(RecType R[], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = n-1; j >0; j--) //将R[i]元素归位
{
if (R[j].key > R[j-1].key) //相邻的两个元素反序时
{
RecType temp = R[j]; //将R[j]和R[j-1]进行交换
R[j ] = R[j-1];
R[j-1] = temp;
}
}
}
}
//快速排序
int Partition(RecType R[],int s,int t)
{
int i = s, j = t;
RecType base = R[i];
while (i < j)
{
while (j > i && R[j].key >= base.key)
{
j--;
}
if (R[j].key < base.key)
{
R[i] = R[j];
i++;
}
while (j > i && R[i].key <= base.key)
{
i++;
}
if (R[i].key > base.key)
{
R[j] = R[i];
j--;
}
}
R[i] = base;
return i;
}
void QuickSort(RecType R[],int s,int t)
{
int i;
if (s < t)
{
i = Partition(R, s, t);
QuickSort(R, s, i - 1);
QuickSort(R, i + 1, t);
}
}
//选择排序
//简单选择排序
void SortAlgorithm(RecType R[], int n)
{
for (int i = 0; i < n; i++)
{
int minindex = i;
for (int j = i + 1; j < n; j++)
{
if (R[minindex].key > R[j].key)
{
minindex = j;
}
}
RecType temp = R[i];
R[i] = R[minindex];
R[minindex] = temp;
}
}
//堆排序 -- 树形选择排序方法
void sift(RecType R[], int low, int high)
{
int i = low, j = 2 * i; //R[j]是R[i]的左孩子
RecType tmp = R[i];
while (j <= high)
{
if (j < high && R[j].key < R[j + 1].key)//若右孩子较大,则j指向右孩子
{
j++;
}
if (tmp.key < R[j].key) //若根结点小于最大孩子的关键字
{
R[i] = R[j]; //将R[j]调整到双亲结点位置上
i = j; //修改i和j值,以便继续向下筛选
j = 2 * i;
}
else break; //若根节点大于或等于最大孩子的关键字,筛选结束
}
R[i] = tmp; //被筛选节点放到最终位置上
}
void HeapSort(RecType R[],int n)
{
int i;
for (i = n / 2; i >= 1; i--)
{
sift(R, i, n); //循环建立初始堆,调用sift算法
}
for (i = n; i >= 2; i--) //进行n-1趟完成堆排序,每一趟堆的元素个数-1
{
swap(R[1], R[i]); //将最后一个元素与根R[1]交换
sift(R, 1, i - 1); //将R[1…i-1]进行筛选,得到i-1个结点的堆
}
}
//插入排序
//直接插入排序
void InsertSort(RecType R[], int n)
{
int i, j;
RecType tmp;
for (i = 1; i < n; i++)//比较n-1次
{
if (R[i].key < R[i - 1].key)//反序时
{
tmp = R[i];
j = i - 1;
do //寻找R[i]的插入位置
{
R[j + 1] = R[j];//将关键字大于R[i].key的记录后移
j--;
} while (j >= 0 && R[j].key > tmp.key);//
R[j + 1] = tmp; //在j+1处插入R[i].
}
}
}
//折半插入排序
void BinInsertSort(RecType R[],int n)
{
int i, j, low, high, mid;
RecType tmp;
for (i = 1; i < n; i++)//比较n-1次
{
if (R[i].key < R[i - 1].key) //反序时
{
low = 0;
high = i-1;
tmp = R[i]; //将R[i]保存到tmp中
while (low <= high) //寻找查找位置
{
mid = (high + low) / 2; //取中间位置
if (tmp.key > R[mid].key)
{
low = mid + 1; //插入点在右半区
}
else
{
high = mid - 1; //插入点在左半区
}
} //找位置high+1
for (j = i - 1; j >= high + 1; j--)
{
R[j + 1] = R[j];
}
R[high + 1] = tmp; //插入tmp
}
}
}
//希尔排序
void ShellSort(RecType R[],int n)//希尔排序算法
{
int i, j, d;
RecType tmp;
d = n / 2; //增量置初值
while (d > 0)
{
for (i = d; i < n; i++) //对所有组采用直接插入排序
{
tmp = R[i]; //对相隔位置为d的一组进行直接插入排序
j = i - d;
while (j>=0 && tmp.key>R[j].key)
{
R[j + 1] = R[j];
j = j - d;
}
R[j + d] = tmp;
}
d /= 2; //减小增量
}
}
//打印数据
void Disp(RecType* arr, int n)
{
cout << "排序后" << endl;
for (int i = 0; i < n; i++)
{
cout << arr[i].key<< " ";
}
}
void Dispsift(RecType* arr, int n)
{
cout << "排序后" << endl;
for (int i = 1; i < n; i++)
{
cout << arr[i].key << " ";
}
}
void Random(RecType *R,int n)
{
cout << "排序前" << endl;
for (int i = 0; i < n; i++)
{
R[i].key = rand() % 10000;
cout<<R[i].key<<" ";
}
}
void random0(RecType* R, int n)
{
cout << "排序前" << endl;
for (int i = 1; i < n; i++)
{
R[i].key = rand() % 10000;
cout << R[i].key << " ";
}
}
void Time(RecType R[], int n)
{
LARGE_INTEGER nFreq;
LARGE_INTEGER nBeginTime;
LARGE_INTEGER nEndTime;
double T;
srand(time(0));
cout.setf(ios::fixed);
Random(R, 80);
cout << "\n冒泡排序" << endl;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
BubbleSort(R, 80);
QueryPerformanceCounter(&nEndTime);
T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
Disp(R, 80);
cout << "\n\n";
Random(R, 80);
cout << "\n快速排序" << endl;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
QuickSort(R, 0, 79);
QueryPerformanceCounter(&nEndTime);
T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
Disp(R, 80);
cout << "\n\n";
Random(R, 80);
cout << "\n希尔排序" << endl;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
ShellSort(R, 79);
QueryPerformanceCounter(&nEndTime);
T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
Disp(R, 80);
cout << "\n\n";
Random(R, 80);
cout << "\n折半插入排序" << endl;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
BinInsertSort(R, 80);
QueryPerformanceCounter(&nEndTime);
T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
Disp(R, 80);
cout << "\n\n";
Random(R, 80);
cout << "\n简单插入排序" << endl;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
InsertSort(R, 80);
QueryPerformanceCounter(&nEndTime);
T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
cout <<"时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
Disp(R, 80);
cout << "\n\n";
Random(R, 80);
cout << "\n选择排序" << endl;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
SortAlgorithm(R, 80);
QueryPerformanceCounter(&nEndTime);
T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
Disp(R, 80);
cout << "\n\n";
RecType R0[81];
random0(R0,81);
cout << "\n堆排序" << endl;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
HeapSort(R0, 80);
QueryPerformanceCounter(&nEndTime);
T = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) * 1000000000 / (double)(nFreq.QuadPart);
cout << "时间:" << setprecision(2) << setiosflags(ios::fixed) << (double)T << endl;
Dispsift(R0, 81);
cout << "\n";
}
int main()
{
RecType R[80];
Time(R, 80);
return 0;
}