一、首先定义以下排序中常用的结构体:
1)SqList结构体:
struct SqList{
int *r; //用于存储要排序的数组,大小是数字个数+1,其中r[0]用作哨兵,目的是减小时间复杂度
int length; //记录数组长度
};
二、直接插入排序:将一个记录插入到已经排好序的有序表中,得到一个长度+1的有序表。
对于一个数组进行插入排序,步骤是:
- 初始状态:将数组第一个元素视为已排序部分(只有一个元素自然有序)。
- 遍历未排序部分:从第二个元素开始,逐个处理每个未排序元素。
- 寻找插入位置:将当前未排序元素与已排序部分的元素从后向前比较,找到其应插入的位置。
- 移动元素:将已排序部分中所有比当前元素大的元素后移一位,为当前元素腾出插入空间。
- 插入元素:将当前元素放入找到的插入位置
(这里需要注意哨兵的使用)
void InsertSort(SqList &L){
int i, j;
for(i = 2; i <= L.length; i++){
L.r[0] = L.r[i]; // 设置哨兵
j = i - 1;
while(L.r[j] > L.r[0]){ // 与哨兵比较
L.r[j+1] = L.r[j]; // 元素后移
j--;
}
L.r[j+1] = L.r[0]; // 插入正确位置
}
}
完整代码:
#include<iostream>
using namespace std;
struct SqList{
int *r; //用于存储要排序的数组,大小是数字个数+1,其中r[0]用作哨兵,目的是减小时间复杂度
int length; //记录数字个数
};
void InsertSort(SqList &L){
int i, j;
for(i = 2; i <= L.length; i++){
L.r[0] = L.r[i]; // 设置哨兵
j = i - 1;
while(L.r[j] > L.r[0]){ // 与哨兵比较
L.r[j+1] = L.r[j]; // 元素后移
j--;
}
L.r[j+1] = L.r[0]; // 插入正确位置
}
}
int main(){
int n,i;
SqList L;
cin>>n;
L.r=new int[n+1];
L.length=n;
for(i=1;i<=L.length;i++){
cin>>L.r[i];
}
InsertSort(L);
for(i=1;i<=L.length;i++){
cout<<L.r[i]<<" ";
}
cout<<endl;
delete[] L.r; // 释放动态分配的内存
return 0;
}
三、希尔排序:先对序列中的元素进行间距分组,先把分出来的这些组进行插入排序,然后缩小间距,再进行分组,在进行插入排序,当间距缩小为1的时候,此时就是直接插入排序。所以,希尔排序又叫缩小增量排序。
关键步骤:
- 初始化增量:
increment = 数组长度
- 循环处理增量:
while(increment > 1)
- 更新增量:
increment = increment/3 + 1
- 更新增量:
- 按增量分组排序:
- 遍历每个子序列(相隔
increment
的元素) - 若当前元素 < 前
increment
位置的元素:- 暂存当前元素到
r[0]
- 移动较大元素:将子序列中比
r[0]
大的元素后移 - 插入元素到正确位置
- 暂存当前元素到
- 遍历每个子序列(相隔
- 当增量为 1 时:完成最后一次标准插入排序
void ShellSort(SqList &L){ int i,j; int increment=L.length; while(increment>1){ 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[j]>L.r[0];j-=increment) { //这个循环的目的是为了给r[i]找到合适的插入位置 L.r[j+increment]=L.r[j]; } L.r[j+increment]=L.r[0]; } } } }
完整代码:
#include<iostream> using namespace std; struct SqList{ int *r; //用于存储要排序的数组,大小是数字个数+1,其中r[0]用作哨兵,目的是减小时间复杂度 int length; //记录数字个数 }; void ShellSort(SqList &L){ int i,j; int increment=L.length; while(increment>1){ 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[j]>L.r[0];j-=increment) { //这个循环的目的是为了给r[i]找到合适的插入位置 L.r[j+increment]=L.r[j]; } L.r[j+increment]=L.r[0]; } } } } int main(){ int n,i; SqList L; cin>>n; L.r=new int[n+1]; L.length=n; for(i=1;i<=L.length;i++){ cin>>L.r[i]; } ShellSort(L); for(i=1;i<=L.length;i++){ cout<<L.r[i]<<" "; } cout<<endl; delete[] L.r; // 释放动态分配的内存 return 0; }