排序的概念
(1,3,5,2[a],6,2[b],7,4)
-
排序方法是稳点: (1,2[a],2[b],3,4,5,6,7) 相等数,排序前后,位置不变
-
排序方法是不稳点:(1,2[b],2[a],3,4,5,6,7)
-
内部排序:排序记录数量不大。
-
外部排序:排序记录数量大,内存不能一次容纳所有记录,需要对外存访问。
内部排序分类:
1.排序过程中 依据不同规则:
-
插入排序
-
交换排序,
-
选择排序,
-
归并排序,
-
2.排序过程中所需的工作量:基数排序 等五类。
-
1.简单的排序方法,时间复杂度为O(n^2).
-
2.先进的排序方法,时间复杂度为O(nlogn).
-
3.基数排序, 时间复杂度为O(d*n). 等三类。
内部排序
1.直接插入排序
- 算法思路:最简单的排序方法,将一个记录插入到 已经排好序 的 有序表中,
- 先将序列中的 第一个记录 看成是一个有序的子序列,从第二个记录插入。
- 空间复杂度:
- 时间复杂度:O(n^2)
- 尽管如此,对于小规模数据或基本有序的数据,插入排序仍然是一个不错的选择。
//直接插入排序(从小到大)
void straiggtInsertionSort(int* array, int n) {
cout << "--直接插入排序--" << endl;
int i, key, j;
for (i = 1; i < n; i++)
{
key = array[i]; //标记插入数据,(先从第二个数据开始)
j = i - 1; //有序数列,(先是第一个数据)
while (j >= 0 && key < array[j] ) //从小到大,有序数列下标,插入值
{
array[j + 1] = array[j]; //数据后移
j = j - 1; //有序数列下标前移,再次比较
}
array[j + 1] = key; //找到合适位置,插入
}
}
//直接插入排序(从大到小)
void straiggtInsertionSort2(int* array, int n) {
cout << "--直接插入排序(从大到小)--" << endl;
int i, key, j;
for (i = 1; i < n; i++)
{
key = array[i]; //标记插入数据,(先从第二个数据开始)
j = i - 1; //有序数列,(先是第一个数据)
while (j >= 0 && key >array[j] ) //从大到小,有序数列下标,插入值
{
array[j + 1] = array[j]; //数据后移
j = j - 1; //有序数列下标前移,再次比较
}
array[j + 1] = key; //找到合适位置,插入
}
}
2.折半插入排序(从小到大)
- 在直接插入的基础上,查找用折半,减少了比较次数,移动没变.(数据较大是用)
- 空间复杂度:和直接插入相同
- 时间复杂度:O(n^2)
void binaryInsertionSort(int* array, int n) {
cout << "--折半插入排序--" << endl;
int i, key, j;
for (i = 1; i < n; i++)
{
key = array[i]; //标记插入数据,(先从第二个数据开始)
//折半查找
int low = 0, higt= i - 1;
while (low <= higt) { //找到higt+1位置
int m= (low +higt)/2;
if (key < array[m]) higt = m - 1;
else low = m + 1;
}
for (int j = i - 1; j >= higt + 1; j--)
array[j + 1] = array[j]; //后移
array[higt + 1] = key; //找到合适位置,插入
}
}
3. 2—路插入排序(从小到大)
- 在折半插入排序的基础上,在改进,减少移动次数,比较没变.
- 空间复杂度: s=O(n)
- 时间复杂度:O(n^2)
- 因此,若希望在排序过程中不移动记录,只有改变存储结构,进行表插入排序
4.希尔排序
- 基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,
待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。 - 在直接插入排序的基础上,改进
- 空间复杂度:
- 时间复杂度:O(n^1.5)
void shellInsert(int* array, int dk, int num_array) {
cout << "--希尔排序排序--" << endl;
int i, key, j;
/**开始从增量处,每次加1。设增量dk = 3,
开始(0, 3)(1, 4)(2, 5)(0, 3, 6)(1, 4, 7)(2, 5, 8)
(0, 3, 6,9)(1, 4, 7,10)
**/
for (i = dk; i < num_array; i++)
{
key = array[i]; //标记插入数据
for (j = i - dk; j >= 0 && key < array[j]; j=j-dk)
array[j + dk] = array[j]; //数据后移
array[j + dk] = key; //找到合适位置,插入
}
}
void shellSort(int* array, int dlta[],int num_array,int num_dkta) { //增量序列dlta[]
for (int k = 0; k < num_dkta; k++)
shellInsert(array, dlta[k], num_array); //一趟dka[k]增量排序
}
代码
头文件
inside_sort.h
#pragma once
#include<iostream>
#include "Straiggt_Insertion_Sort.h"
//遍历数组
void traverseTheArray(int a[], int n);
//内部排序
void inside_sort();
Straiggt_Insertion_Sort.h
#pragma once
#include<iostream>
#include "inside_sort.h"
//直接插入排序
void straiggtInsertionSort(int* array, int n);
//直接插入排序(从大到小)
void straiggtInsertionSort2(int* array, int n);
//折半插入排序(从小到大)
void binaryInsertionSort(int* array, int n);
//2-路插入排序(从小到大)
//希尔排序
void shellInsert(int* array, int dk, int num_array);
void shellSort(int* array, int dlta[], int num_array, int num_dkta);
cpp文件
inside_sort.cpp
#include "inside_sort.h"
using namespace std;
//遍历数组
void traverseTheArray(int a[], int n) //n,数组的大小
{
for (int i = 0; i < n; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
void inside_sort() {
cout << "----内部排序---" << endl;
int ddff[] = { 2,1,12,32,14,36,15,65 };
int ddff1[] = { 12,32,14,33,35,65 };
int m = sizeof(ddff) / sizeof(ddff[0]); //sizeof()运算符,求的内存的大小
//直接插入排序
traverseTheArray(ddff, m);
straiggtInsertionSort(ddff, m);
traverseTheArray(ddff, m);
straiggtInsertionSort2(ddff, m);
traverseTheArray(ddff, m);
//折半插入排序(从小到大)
binaryInsertionSort(ddff, m);
traverseTheArray(ddff, m);
//希尔排序
int ddff_shell[] = { 2,1,12,32,14,36,15,65 }; //要排序的数列
int m_shell = sizeof(ddff_shell) / sizeof(ddff_shell[0]);
int dkta[] = { 5,3,1 }; //增量数组
int m_dkta = sizeof(dkta) / sizeof(dkta[0]);
cout << "----要排序的数列---" << endl;
traverseTheArray(ddff_shell, m_shell);
shellSort(ddff_shell, dkta, m_shell, m_dkta);
traverseTheArray(ddff_shell, m_shell);
}
Straiggt_Insertion_Sort.cpp
#include "Straiggt_Insertion_Sort.h"
using namespace std;
//直接插入排序
/**
* 算法思路:最简单的排序方法,将一个记录插入到 已经排好序 的 有序表中,
* 先将序列中的 第一个记录 看成是一个有序的子序列,从第二个记录插入。
* 空间复杂度:
* 时间复杂度:O(n^2)
* 尽管如此,对于小规模数据或基本有序的数据,插入排序仍然是一个不错的选择。
**/
//直接插入排序(从小到大)
void straiggtInsertionSort(int* array, int n) {
cout << "--直接插入排序--" << endl;
int i, key, j;
for (i = 1; i < n; i++)
{
key = array[i]; //标记插入数据,(先从第二个数据开始)
j = i - 1; //有序数列,(先是第一个数据)
while (j >= 0 && key < array[j] ) //从小到大,有序数列下标,插入值
{
array[j + 1] = array[j]; //数据后移
j = j - 1; //有序数列下标前移,再次比较
}
array[j + 1] = key; //找到合适位置,插入
}
}
//直接插入排序(从大到小)
void straiggtInsertionSort2(int* array, int n) {
cout << "--直接插入排序(从大到小)--" << endl;
int i, key, j;
for (i = 1; i < n; i++)
{
key = array[i]; //标记插入数据,(先从第二个数据开始)
j = i - 1; //有序数列,(先是第一个数据)
while (j >= 0 && key >array[j] ) //从大到小,有序数列下标,插入值
{
array[j + 1] = array[j]; //数据后移
j = j - 1; //有序数列下标前移,再次比较
}
array[j + 1] = key; //找到合适位置,插入
}
}
//折半插入排序(从小到大)
/**
* 在直接插入的基础上,查找用折半,减少了比较次数,移动没变.(数据较大是用)
* 空间复杂度:和直接插入相同
* 时间复杂度:O(n^2)
**/
void binaryInsertionSort(int* array, int n) {
cout << "--折半插入排序--" << endl;
int i, key, j;
for (i = 1; i < n; i++)
{
key = array[i]; //标记插入数据,(先从第二个数据开始)
//折半查找
int low = 0, higt= i - 1;
while (low <= higt) { //找到higt+1位置
int m= (low +higt)/2;
if (key < array[m]) higt = m - 1;
else low = m + 1;
}
for (int j = i - 1; j >= higt + 1; j--)
array[j + 1] = array[j]; //后移
array[higt + 1] = key; //找到合适位置,插入
}
}
//2-路插入排序(从小到大)
/**
* 在折半插入排序的基础上,在改进,减少移动次数,比较没变.
* 空间复杂度: s=O(n)
* 时间复杂度:O(n^2)
*
* 因此,若希望在排序过程中不移动记录,只有改变存储结构,进行表插入排序。
**/
//希尔排序
/**
* 基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,
* 待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
*
* 在直接插入排序的基础上,改进
* 空间复杂度:
* 时间复杂度:O(n^1.5)
**/
void shellInsert(int* array, int dk, int num_array) {
cout << "--希尔排序排序--" << endl;
int i, key, j;
/**开始从增量处,每次加1。设增量dk = 3,
开始(0, 3)(1, 4)(2, 5)(0, 3, 6)(1, 4, 7)(2, 5, 8)
(0, 3, 6,9)(1, 4, 7,10)
**/
for (i = dk; i < num_array; i++)
{
key = array[i]; //标记插入数据
for (j = i - dk; j >= 0 && key < array[j]; j=j-dk)
array[j + dk] = array[j]; //数据后移
array[j + dk] = key; //找到合适位置,插入
}
}
void shellSort(int* array, int dlta[],int num_array,int num_dkta) { //增量序列dlta[]
for (int k = 0; k < num_dkta; k++)
shellInsert(array, dlta[k], num_array); //一趟dlta[k]增量排序
}
自己写个开始函数,int main(),和头文件
int main()
{
cout << "------排序------" << endl;
//内部排序
inside_sort();
//外部排序
return 0;
}