初等排序
一、插入排序法
将开头元素视为已排序
执行以下处理,直至未排序部分消失:
- 取出未排序首位元素,赋值给变量v
- 在已排序部分,将所有比v大的元素向后移动一个单位
- 将已取出的元素v插入空位
#include<stdio.h>
/* 按顺序输出数组元素 */
void trace(int A[], int N)
{
int i;
for (i = 0; i < N; i++)
{
if (i > 0) printf(" ");//在相邻元素之间输出1个空格
printf("%d",A[i]);
}
printf("\n");
}
/* 插入排序(0起点数组) */
void insertionSort(int A[], int N)
{
int v,j;
for (int i = 1; i < N; i++)
{
v = A[i];
j = i - 1;
while (j >= 0 && A[j] > v)
{
A[j + 1] = A[j];
j--;
}
A[j + 1] = v;
trace(A, N);
}
}
void main()
{
int N;
printf("请输入数列长度:");
scanf("%d", &N);
printf("\n请输入数列元素:");
int A[100];
for (int i = 0; i < N ; i++)
scanf("%d", &A[i]);
trace(A,N);
insertionSort(A, N);
return 0;
}
二、冒泡排序法
第一种:从数组末尾开始依次比较相邻两个元素,如果大小关系相反则交换位置
#include<iostream>
using namespace std;
/* 按顺序输出数组元素 */
void trace(int A[], int N)
{
int i;
for (i = 0; i < N; i++)
{
if (i > 0) cout << " ";//在相邻元素之间输出1个空格
cout << A[i];
}
cout << endl;
}
void BubbleSort(int A[], int N)
{
bool flag = 1;
int i = 0;//外围i控制每趟比较元素逐渐减少
while (flag)
{
flag = 0; //flag用于确定数列是否已有序
for (int j = N - 1; j > i; j--)//内部j从后端往前遍历,推出最小值
{
if (A[j] < A[j - 1])//交换相邻元素
{
int temp = A[j];
A[j] = A[j - 1];
A[j - 1] = temp;
flag = 1;
}
}
trace(A, N);
i++;
}
}
int main()
{
int N;
cout << "请输入数列长度:";
cin >> N;
cout << "\n请输入数列元素:";
int A[100];
for (int i = 0; i < N; i++)
cin >> A[i];
BubbleSort(A, N);
return 0;
}
第二种:从数组首位开始依次比较相邻两个元素,如果大小关系相反则交换位置
void BubbleSort(int A[], int N)
{
bool flag = 1;
int i = N-1;//外围i控制每趟比较元素逐渐减少
while (flag)
{
flag = 0;
for (int j = 0; j < i; j++)//内部j从前往后遍历,推出最大值
{
if (A[j] > A[j + 1])//交换相邻元素
{
int temp = A[j];
A[j] = A[j + 1];
A[j + 1] = temp;
flag = 1;
}
}
trace(A, N);
i--;
}
}
三、选择排序法
重复执行N-1次下述处理:
- 找出未排序部分最小值的位置minj
- 将minj位置的元素与未排序部分的起始元素交换
#include<stdio.h>
void trace(int A[], int N)
{
int i;
for (i = 0; i < N; i++)
{
if (i > 0) printf(" ");//在相邻元素之间输出1个空格
printf("%d", A[i]);
}
printf("\n");
}
/* 元素交换 */
void Reverse(int *p,int *q)
{
int temp = *p;
*p = *q;
*q = temp;
}
void selectionSort(int A[], int N)
{
for (int i = 0; i < N - 1; i++)//表示未排序部分的开头元素,从开头向末尾移动
{
int minj = i;
for (int j = i; j < N; j++) //若是N-1,则遍历不到最后一个元素
{
if (A[j] < A[minj])
minj = j;
}
Reverse(&A[i], &A[minj]);
trace(A, N);
}
}
int main()
{
int N;
printf("请输入数列长度:");
scanf_s("%d", &N);
printf("\n请输入数列元素:");
int A[100];
for (int i = 0; i < N; i++)
scanf_s("%d", &A[i]);
selectionSort(A, N);
return 0;
}
四、希尔排序
希尔排序是一种充分发挥插入排序的高速算法。在希尔排序中,程序会重复进行以间隔g为元素对象的插入排序。这里g的选取方法假定为
g
n
+
1
=
3
∗
g
n
+
1
g_{n+1} = 3*g_{n} + 1
gn+1=3∗gn+1
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int l;
int A[1000000];
int n;
vector<int> G;
void trace(int A[], int N)
{
int i;
for (i = 0; i < N; i++)
{
if (i > 0) printf(" ");//在相邻元素之间输出1个空格
printf("%d", A[i]);
}
printf("\n");
}
//指定了间隔g的插入排序
void insertionSort(int A[], int n, int g)
{
for (int i = g; i < n; i++){
int v = A[i];
int j = i - g;
while (j >= 0 && A[j] > v) {
A[j + g] = A[j];
j -= g;
}
A[j + g] = v;
}
}
void shellSort(int A[], int n)
{
for (int h = 1;;)//生成数列G={1,4,13,40,121,364,1093...}
{
if (h > n) break;
G.push_back(h);
h = 3 * h + 1;
}
for (int i = G.size() - 1; i >= 0; i--)//按逆序指定G[i]=g
{
insertionSort(A, n, G[i]);
trace(A, n);
}
}
int main()
{
cout << "请输入数列长度:" << endl;
cin >> n;
cout << "请输入数列元素:" << endl;
for (int i = 0; i < n; i++)
scanf_s("%d",&A[i]);
cout << "排序结果为:" << endl;
shellSort(A, n);
cout << "间隔g的取值为:" << endl;
for (int i = G.size() - 1; i >= 0; i--)
{
printf("%d ",G[i]);
if (i) printf(" ");
}
printf("\n");
return 0;
}