排序动态过程可参考网站:Visualgo
插入排序算法1:直接插入排序
//直接插入排序算法的实现
#include<iostream>
using namespace std;
void InsertSort(int *a, int len)
{
for (int i = 1; i < len; i++)
{
int j = i - 1;//j记录在要插入元素之前还有几个待比较元素
int x = a[i];//先把要插入元素的值保存下来
while (j>-1 && x < a[j])//要插入元素逐个与在它位置之前的元素比较
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = x;
}
}
int main()
{
//测试样例
int a[8] = { 3, 1, 7, 5, 2, 4, 9, 6 };
int len = sizeof(a) / sizeof(int);//计算数组size
InsertSort(a, len);
for (int i = 0; i < len; i++)
cout << a[i];
cout << endl;
system("pause");
return 0;
}
直接插入排序算法的时间复杂度为O(n2)
插入算法2:希尔排序
希尔排序的具体实现思路是:先将整个记录表分割成若干部分,分别进行直接插入排序,然后再对整个记录表进行一次直接插入排序。
一般在记录的数量多的情况下,希尔排序的排序效率较直接插入排序高。
//希尔排序
#include<iostream>
using namespace std;
#define SIZE 15
struct SqNode{
int key;
};
struct Sqlist{
SqNode r[SIZE];
int length;
};
void ShellInsert(Sqlist *L, int dk)
{
for (int i = dk + 1; i <= L->length; i++)
{
if (L->r[i].key < L->r[i - dk].key)
{
int j;
L->r[0] = L->r[i];
for (j = i - dk; j>0 &&( L->r[i].key < L->r[j].key); j -= dk)
{
L->r[j + dk] = L->r[j];
}
L->r[j + dk] = L->r[0];
}
}
}
void ShellSort(Sqlist *L, int dk[], int n)
{
for (int i = 0; i < n; i++)
{
ShellInsert(L, dk[i]);
}
}
int main()
{
Sqlist *L = new Sqlist;
L->r[1].key = 49;
L->r[2].key = 38;
L->r[3].key = 64;
L->r[4].key = 97;
L->r[5].key = 76;
L->r[6].key = 13;
L->r[7].key = 27;
L->r[8].key = 49;
L->r[9].key = 55;
L->r[10].key = 4;
L->length = 10;
int delta[] = { 5, 3, 1 };//最后一次的间隔必须是1,表示对整张表进行一次插入排序
ShellSort(L, delta, 3);
for (int i = 1; i <= L->length; i++)
{
cout << L->r[i].key<<" ";
}
cout << endl;
system("pause");
return 0;
}
冒泡排序
如果是升序排序,则是通过一趟趟冒泡,每次相邻的元素两两比较并将最大的值冒到最后,没冒到最后的最大值将不参与下次的冒泡比较
冒泡排序法的时间复杂度和表中元素的顺序有关,如果记录为正序,则只需比较n-1次且不需要移动元素位置即可完成,若为降序,则是最坏的时间复杂度,每个元素冒一趟,每趟比较次数分别为:n-1,n-2,...1,0,时间复杂度为:O(n*(n-1)/2)即O(n2)
//冒泡排序
#include<iostream>
using namespace std;
//void swap(int &x, int &y)//引用交换
//{
// int temp = x;
// x = y;
// y = temp;
//}
//void swap(int *x, int *y)//指针交换
//{
// int temp = *x;
// *x = *y;
// *y = temp;
//}
int main()
{
int arr[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
int len = sizeof(arr) / sizeof(int);
for (int i = 0; i < len; i++)
for (int j = 0; j + 1 < len - i;j++)
{
if (arr[j] > arr[j + 1])
swap(arr[j], arr[j + 1]);//即使自己不定义swap()函数,C++有自己内嵌的函数可以调用
/*swap(&arr[j], &arr[j + 1]);*/
}
for (int m = 0; m < len; m++)
cout << arr[m] << " ";
cout << endl;
system("pause");
return 0;
}
快速排序法
快速排序算法的时间复杂度为O(nlogn)
,是所有时间复杂度相同的排序方法中性能最好的排序算法。
//快速排序法
#include<iostream>
using namespace std;
#define MAX 12
struct SqNode{
int key;
};
struct Sqlist{
SqNode r[MAX];
int length;
};
int QSort(Sqlist *L, int low, int high)//这只是一次的快排
{
L->r[0] = L->r[low];
int pivot = L->r[low].key;
while (low < high)
{
while (low<high&&L->r[high].key >= pivot)
{
high--;
}
L->r[low] = L->r[high];
while (low < high&&L->r[low].key <= pivot)
{
low++;
}
L->r[high] = L->r[low];
}
L->r[low] = L->r[0];
return low;
}
void QuickSort(Sqlist *L, int low, int high)
{
if (low < high)
{
int pivotloc;
pivotloc=QSort(L, low, high);
QuickSort(L, low, pivotloc - 1);//递归
QuickSort(L, pivotloc + 1, high);//递归
}
}
int main()
{
Sqlist *L = new Sqlist;
L->r[1].key = 49;
L->r[2].key = 38;
L->r[3].key = 65;
L->r[4].key = 97;
L->r[5].key = 76;
L->r[6].key = 13;
L->r[7].key = 27;
L->r[8].key = 49;
L->r[9].key = 9;
L->r[10].key = 3;
L->r[11].key = 100;
L->length = 12;
int low = 1;
int high = L->length - 1;
QuickSort(L, low, high);
for (int i = 1; i < L->length; i++)
cout << L->r[i].key << " ";
cout << endl;
system("pause");
return 0;
}
选择排序算法1:简单排序算法
//选择排序法1:简单选择排序
//从小到大排序
//遍历n-1,每次把表中最小的值与前面位置的值交换位置
#include<iostream>
using namespace std;
void SelectSort(int *a,int len)
{
for (int i = 0; i < len-1; i++)
{
int min_value = a[i];
int index = i;
for (int j = i + 1; j < len; j++)
{
if (min_value > a[j]){
min_value = a[j];
index = j;
}
}
swap(a[i], a[index]);
}
}
int main()
{
int a[5] = { 56, 12, 80, 91, 20 };
int len = sizeof(a) / sizeof(int);
SelectSort(a, len);
for (int i = 0; i < len; i++)
cout << a[i] << " ";
cout << endl;
system("pause");
return 0;
}
堆排序
堆排序在最坏的情况下,其时间复杂度仍为O(nlogn)
。这是相对于快速排序的优点所在。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define MAX 9
//单个记录的结构体
typedef struct {
int key;
}SqNote;
//记录表的结构体
typedef struct {
SqNote r[MAX];
int length;
}SqList;
//将以 r[s]为根结点的子树构成堆,堆中每个根结点的值都比其孩子结点的值大
void swap(SqNote *a, SqNote *b)
{
int temp = a->key;
a->key = b->key;
b->key = temp;
}
void HeapAdjust(SqList *L, int s, int m)
{
SqNote rc = L->r[s];
for (int j = 2 * s; j <= m; j *= 2)
{
if (j + 1 <= m&&L->r[j].key<L->r[j+1].key)
{
j++;
}
if (rc.key>L->r[j].key)
{
break;
}
L->r[s].key = L->r[j].key;
s = j;
}
L->r[s] = rc;
}
void HeapSort(SqList *L)
{
for (int i = L->length / 2; i > 0; i--)
{
HeapAdjust(L, i, L->length);
}
for (int n = L->length; n >1; n--)
{
swap(&L->r[1], &L->r[n]);//交换之后,只有根节点不是按堆排的
HeapAdjust(L, 1, n - 1);//所以这只重排根节点即可
}
}
int main() {
SqList * L = (SqList*)malloc(sizeof(SqList));
L->length = 8;
L->r[1].key = 49;
L->r[2].key = 38;
L->r[3].key = 65;
L->r[4].key = 97;
L->r[5].key = 76;
L->r[6].key = 13;
L->r[7].key = 27;
L->r[8].key = 49;
HeapSort(L);
for (int i = 1; i <= L->length; i++) {
printf("%d ", L->r[i].key);
}
std::cout << std::endl;
system("pause");
return 0;
}