直接插入法是最简单的排序法,其排序思想如下:
打牌时,每抓一张牌就将其放到对应的顺序位置。
下面是待排记录的类型定义:
#define MAXSIZE 200
typedef int KeyType//关键字类型
typedef struct{
KeyType key;//关键字
InfoType otherinfo;//其他数据项
}RedType;//记录类型
typededf struct{
RedType r[MAXSIZE+1];//r[0]闲置或作为哨兵
int length;//顺序表长度
}SqList;
上述的RedType结构体类型实际上是没必要定义的,实际做题时可以写成如下代码,更方便一点:
#define MAXSIZE 200
typedef int KeyType//关键字类型
typededf struct{
KeyType r[MAXSIZE+1];//r[0]闲置或作为哨兵
int length;//顺序表长度
}SqList;
直接插入排序算法的描述:
void InsertSort(SqList &L)
{
//对顺序表L做直接插入排序
for(i=2;i<=L.length;i++)
{
if(L.r[i]<L.r[i-1])
{
L.r[0]=L.r[i];//r[i]暂存到监视哨中
L.r[i]=L.r[i-1];//r[i-1]后移
//记录逐个后移,直到找到插入位置
for(j=i-2;L.r[0]<L.r[j];j--)
L.r[j+1]=L.r[j];
L.r[j+1]=L.r[0];
}
}
}
常见错误by小胡:
1)低位输出随机数。(记录逐个后移,找到插入位置)三行代码的位置放在了if语句外,导致即便低位符合降序,但仍执行代码,致溢出。
直接插入排序算法分析:
希尔排序法是直接插入法的优化,它的思想是先将整个排序序列分成若干子序列,并分别进行直接插入排序,当整个记录中的序列基本有序时,再对全体记录进行一次直接插入排序。
希尔排序法的描述:
void ShellInsert(SqList& L, int dk)
{//对顺序表 L 做一趟增量是 dk 的希尔插入排序
int i, j;
for (i = dk + 1; i <= L.length; ++i)
{
if (L.r[i] < L.r[i - dk]) {
//需将 L.r[i] 插入有序增量子表
L.r[0] = L.r[i]; //暂存在L.r[0]
for (j = i - dk; j > 0 && L.r[0] < L.r[j]; j -= dk)
L.r[j + dk] = L.r[j];//记录后移
L.r[j + dk] = L.r[0];//将 r[0] 插入
}//if
}//for
}//ShellInsert
void ShellSort(SqList& L, int dt[], int t)
{//按增量序列 dt[0..t-1] 对顺序表 L 作 t 趟希尔排序
int k;
for (k = 0; k < t; ++k)
ShellInsert(L, dt[k]);
}
希尔排序法算法分析:
利用希尔排序解决如下问题:
输入
输入的第一行包含1个正整数n,表示共有n个整数需要参与排序。其中n不超过1000。
第二行包含n个用空格隔开的正整数,表示n个需要排序的整数.
输出
只有1行,包含n个整数,表示从小到大排序完毕的所有整数。
请在每个整数后输出一个空格,并请注意行尾输出换行。
样例输入
10
2 8 4 6 1 10 7 3 5 9
样例输出
1 2 3 4 5 6 7 8 9 10
下面是源码:
#include
using namespace std;
#define KeyType int
#define MAXSIZE 1000
typedef struct {
KeyType r[MAXSIZE+1];
int length;
}SqList;
void ShellInsert(SqList& L, int dk)
{//对顺序表 L 做一趟增量是 dk 的希尔插入排序
int i, j;
for (i = dk + 1; i <= L.length; ++i)
{
if (L.r[i] < L.r[i - dk]) {
//需将 L.r[i] 插入有序增量子表
L.r[0] = L.r[i]; //暂存在L.r[0]
for (j = i - dk; j > 0 && L.r[0] < L.r[j]; j -= dk)
L.r[j + dk] = L.r[j];//记录后移
L.r[j + dk] = L.r[0];//将 r[0] 插入
}//if
}//for
}//ShellInsert
void ShellSort(SqList& L, int dt[], int t)
{//按增量序列 dt[0..t-1] 对顺序表 L 作 t 趟希尔排序
int k;
for (k = 0; k < t; ++k)
ShellInsert(L, dt[k]);
}
int main()
{
int n;
cin >> n;
SqList L;
int dlta[1000];
L.length = n;
for (int i = 1; i <= n; i++)
{
cin >> L.r[i];
dlta[i - 1] = n-i;
}
ShellSort(L,dlta,n);
for (int i = 1; i <= n; i++)
cout << L.r[i] << " ";
cout << endl;
return 0;
}
冒泡排序排序法,相邻元素之间进行比较,如果逆序则交换位置。
冒泡排序法的描述:
void BubbleSort(SqList &L)
{//对顺序表L做冒泡排序
m = L.length − 1;
flag = 1;//用来标记某一趟排序是否发生交换
while((m > 0) && (flag == 1)) {
flag = 0; //没有发生交换
for(j = 1; j <= m; j++)
if(L.r[j].key > L.r[j + 1].key) {
flag = 1;//表示本趟排序发生了交换
t = L.r[j];
L.r[j] = L.r[j + 1];
L.r[j + 1] = t;//交换前后两个记录
}//if
−−m;
}//while
}//BubbleSort
实际上此冒泡排序是对原冒泡排序的一种优化,flag标识符实现了优化。
例如:1 2 5 3 7 8 9 10
原冒泡排序要比较7趟,而此冒泡排序只需比较3趟。
下面贴上原冒泡排序算法描述:
void BubbleSort(SqList &L)
{
int i, j,temp;
int m=L.length-1;
while(m>0)
for (j = 1; j <= m; j++)
if (L.r[j] > L.r[j + 1])
{
temp = L.r[j];
L.r[j] = L.r[j + 1];
L.r[j + 1] = temp;
}
--m;
}
冒泡排序算法分析:
快速排序法是最常用的一种排序方法,同时也是很典型的分治思想,分而治之。它的排序思路如下:
1.任取一个记录作为枢轴
2.划分:所有比枢轴小的记录一律前放,比枢轴大的记录一律后放,形成左右两个子表
3.对子表重新进行前两步操作,直到每个子表元素只剩一个
快速排序法算法描述:
int Partition(SqList &L,int low,int high)
{//对表 r[low..high] 进行一趟排序,返回枢轴位置
L.r[0]=L.r[low]; //子表的第一个记录做枢轴
pivotkey=L.r[low];
while(low<high){//从表两端交替向中间扫描
while(low<high&&L.r[high]>=pivotkey)
−−high;
L.r[low]=L.r[high];//比枢轴小的移到低端
while(low<high&&L.r[low]<=pivotkey)
++low;
L.r[high]=L.r[low];//比枢轴大的移到高端
}//while
L.r[low]=L.r[0]; //枢轴记录到位
return low; //返回枢轴位置
}//Partition
void QSort(SqList &L, int low, int high)
{ //对顺序表 L 中的子序列 L.r[low..high] 做快速排序
if(low < high) { //长度大于1
pivotloc = Partition(L, low, high);
QSort(L, low, pivotloc − 1);//左子表排序
QSort(L, pivotloc + 1, high);//右子表排序
}//if
}//QSort
void QuickSort(SqList &L)
{ //对顺序表L做快速排序
QSort(L, 1, L.length);
}//QuickSort
快速排序算法分析: