运用自己学过的六类算法中的八个排序(必须覆盖六类排序),对一个无序的数组进行排序并且输出,然后计算每个算法的空间复杂度和时间复杂度,分析其优缺点。
六类排序:交换排序、插入排序、选择排序、归并排序、基排序、桶排序
1.交换排序
(1)冒泡排序冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
(2)快速排序快速排序(Quicksort)是对冒泡排序的一种改进。快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
2.插入排序
(1)简单插入排序插入排序(Insertion Sort),一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。 希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。
3.选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
4.归并排序
归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
5.基数排序
基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog®m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
6.桶排序
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
插入排序
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 20
typedef int KeyType;
//定义结构体
typedef struct
{
KeyType key;
}Data;
typedef struct
{
Data a[MAXSIZE + 1];
int length;
}SqList;
//插入排序
SqList Insertion_Sort(SqList L);
int main(){
int i;
SqList L;
for(i = 1; i < MAXSIZE + 1; i++){ //生成20个随机数
L.a[i].key = rand() % 100;
}
L = Insertion_Sort(L);
}
SqList Insertion_Sort(SqList L){
int i,j,c;
for(c = 1; c < MAXSIZE + 1;c++){
printf("%d ",L.a[c].key); //输出原本的顺序
}
printf("\n");
for(i = 2;i < MAXSIZE + 1;i++){
if(L.a[i].key < L.a[i - 1].key){
L.a[0].key = L.a[i].key; //设置一个哨兵,将小的数放入
L.a[i].key = L.a[i - 1].key; //将数往后移一位
for(j = i -2;L.a[0].key < L.a[j].key;j--) //比较哨兵和已经排好序的大小
L.a[j + 1].key = L.a[j].key; //如果哨兵小,往后移一位
L.a[j + 1].key = L.a[0].key; //将哨兵中的值,放入空出来的位置
}
for(c = 1; c < MAXSIZE + 1;c++){
printf("%d ",L.a[c].key); //输出每次排序的结果
}
printf("\n");
}
return L;
}
归并排序
#include<stdio.h>
#include<stdlib.h>
//冒泡排序
#define MAXSIZE 20
typedef int KeyType;
//定义结构体
typedef struct
{
KeyType key;
}Data;
typedef struct
{
Data a[MAXSIZE + 1];
int length;
}SqList;
void Merge_Sort(SqList &L);
void MSort(Data* R, Data* T, int low, int high);
void Merge(Data* R, Data* T, int low,int mid,int high);
int main()
{
int i;
SqList L;
L.length = 0;
for(i = 1; i < MAXSIZE + 1; i++) //产生20个随机数
{
L.a[i].key = rand() % 100;
L.length++;
}
Merge_Sort(L);
for(int j = 1; j < 21; j++)
{
printf("%d ", L.a[j].key);
}
}
void Merge(Data* R, Data* T, int low,int mid,int high)
{
int i,j,k;
i = low;
j = mid + 1;
k = low;
while(i <= mid && j <= high)
{
if(R[i].key <= R[j].key) T[k++] = R[i++];
else T[k++] = R[j++];
}
while(i <= mid) T[k++] = R[i++];
while(j <= high) T[k++] = R[j++];
}
void MSort(Data* R, Data* T, int low, int high)
{
int mid;
Data S[100];
if(low == high) T[low] = R[low];
else
{
mid = (low + high) / 2;
MSort(R,S,low,mid);
MSort(R,S,mid + 1,high);
Merge(S,T,low,mid,high);
}
}
void Merge_Sort(SqList &L)
{
MSort(L.a, L.a, 1, L.length);
}
基数排序
#include<stdio.h>
#include<stdlib.h>
//基数排序
typedef int KeyType;
//定义结构体
typedef struct
{
KeyType key[500000];
int next;
}Data;
typedef struct
{
Data a[10];
}SqList;
void RadixSort(Data &L, int MAXSIZE);
int get_max_digit(int *array, int n); //找最大值位数
void Distribute(Data &L, int n, int MAXSIZE); //进行排序收集
int main()
{
int i,MAXSIZE;
Data L;
scanf("%d", &MAXSIZE);
for(i = 0; i < MAXSIZE ; i++) //产生MAXSIZE个随机数
{
scanf("%d", &L.key[i]);
}
RadixSort(L, MAXSIZE);
for(int j = 0; j < MAXSIZE ; j++) //排序后的数
{
printf("%d ", L.key[j]);
}
}
int get_max_digit(int *array, int n)
{
int digit, max;
digit = 0;
max = array[0]; //定义一个可以存放最大数位置
for (int i = 0; i < n; i++)
{
if (array[i] > max) //如果大替换
max = array[i];
}
while (max)
{
digit++; //计算几位数
max /= 10;
}
return digit;
}
void RadixSort(Data &L, int MAXSIZE)
{
int j = get_max_digit(L.key, MAXSIZE); //返回最大位数
for(int i = 0; i < j; i++)
{
Distribute(L, i, MAXSIZE);
}
}
void Distribute(Data &L, int n,int MAXSIZE)
{
SqList J;
for(int i = 0; i < 10; i++) //先初始化数组
{
for(int j = 0; j < MAXSIZE; j++)
{
J.a[i].key[j] = -1;
J.a[i].next = 0;
}
}
if(n == 0) //最低位数比较
{
for(int i = 0; i < MAXSIZE; i++)
{
int j = L.key[i] % 10;
J.a[j].key[J.a[j].next++] = L.key[i];
}
}
else //其他位数比较
{
for(int i = 0; i < MAXSIZE; i++)
{
int j = L.key[i] / (n * 10);
J.a[j].key[J.a[j].next++] = L.key[i];
}
}
int k = 0; //收集
for(int i = 0; i < 10; i++)
{
while(1)
{
for(int j = 0; J.a[i].key[j] >= 0; ++j)
{
L.key[k++] = J.a[i].key[j];
}
break;
}
}
}
快速排序
#include<stdio.h>
#include<stdlib.h>
//基数排序
#define MAXSIZE 20
typedef int KeyType;
//定义结构体
typedef struct
{
KeyType key;
}Data;
typedef struct
{
Data a[MAXSIZE + 1];
int length;
}SqList;
int Partition(SqList &L, int low, int high);
void Qsort(SqList &L, int low, int high);
void Quick_Sort(SqList &L);
int main()
{
int i,j;
SqList L;
L.length = 0;
for(i = 1; i < MAXSIZE + 1; i++) //产生20个随机数
{
L.a[i].key = rand() % 100;
L.length++;
}
for(j = 1; j < MAXSIZE + 1; j++) //打印未排序时候的顺序
printf("%d ",L.a[j].key);
printf("\n\n");
Quick_Sort(L);
}
int Partition(SqList &L, int low, int high)
{
int pivotkey;
L.a[0] = L.a[low]; //用表的第一个做枢轴记录
pivotkey = L.a[low].key; //将它的值存起来
while(low < high) //交替扫描
{
while(low < high && L.a[high].key >= pivotkey) --high; //如果右边的值一直比他大,下标一直左移
L.a[low] = L.a[high]; //如果找到比它小的交换
while(low < high && L.a[low].key <= pivotkey) ++low; //左边继续重复扫描
L.a[high] = L.a[low]; //交换
}
L.a[low] = L.a[0]; //将枢轴放入low=high的地方
return low; //返回下标
}
void Qsort(SqList &L, int low, int high)
{
int pivotloc;
if(low < high)
{
pivotloc = Partition(L, low, high); //枢轴位置
for(int j = 1; j < MAXSIZE + 1; j++) //打印每排完一次的顺序
printf("%d ",L.a[j].key);
printf("\n");
Qsort(L, low, pivotloc - 1); //左边递归排序
Qsort(L, pivotloc + 1, high); //右边递归排序
}
}
void Quick_Sort(SqList &L)
{
Qsort(L, 1, L.length);
}
冒泡排序
#include<stdio.h>
#include<stdlib.h>
//冒泡排序
#define MAXSIZE 20
typedef int KeyType;
//定义结构体
typedef struct
{
KeyType key;
}Data;
typedef struct
{
Data a[MAXSIZE + 1];
int length;
}SqList;
SqList Bubble_Sort(SqList L);
int main(){
int i;
SqList L;
for(i = 0; i < MAXSIZE; i++){ //生成20个随机数
L.a[i].key = rand() % 100;
}
L = Bubble_Sort(L);
}
SqList Bubble_Sort(SqList L){
int i,j,c,b;
for(i = 0;i < MAXSIZE;i++){ //一共进行20次排序
for(j = 0;j + 1 < MAXSIZE - i;j++){ //两两进行比较,大的数往后走
if(L.a[j].key > L.a[j + 1].key){
b = L.a[j + 1].key;
L.a[j + 1].key =L.a[j].key;
L.a[j].key = b;
}
}
for(c = 0; c < 20;c++){ //输出每次排序后的结果
printf("%d ",L.a[c].key);
}
printf("\n");
}
return L;
}
桶排序
#include<stdio.h>
#include<stdlib.h>
//桶排序
#define MAXSIZE 20
typedef int KeyType;
//定义结构体
typedef struct
{
KeyType key[MAXSIZE];
int next;
}Data;
typedef struct
{
Data a[MAXSIZE];
}SqList;
void RadixSort(Data &L);
int get_max_digit(int *array, int n); //找最大值位数
void Distribute(Data &L, int n); //进行排序收集
void Bubble_Sort(Data &L); //在桶内进行排序,调用冒泡
int main()
{
int i;
Data L;
for(i = 0; i < MAXSIZE ; i++) //产生20个随机数
{
L.key[i] = rand() % 100;
}
for(int i = 0; i < MAXSIZE; i++) //输出未排序的数
{
printf("%d ", L.key[i]);
}
printf("\n");
RadixSort(L);
for(int j = 0; j < MAXSIZE ; j++) //排序后的数
{
printf("%d ", L.key[j]);
}
printf("\n");
}
int get_max_digit(int *array, int n)
{
int digit, max;
digit = 0;
max = array[0]; //定义一个可以存放最大数位置
for (int i = 0; i < n; i++)
{
if (array[i] > max) //如果大替换
max = array[i];
}
while (max)
{
digit++; //计算几位数
max /= 10;
}
return digit;
}
void RadixSort(Data &L)
{
int j = get_max_digit(L.key, MAXSIZE); //返回最大位数
Distribute(L, j - 1);
}
void Distribute(Data &L, int n)
{
SqList J;
for(int i = 0; i < 10; i++) //先初始化数组
{
for(int j = 0; j < MAXSIZE; j++)
{
J.a[i].key[j] = -1;
J.a[i].next = 0;
}
}
if(n == 0) //最低位数比较
{
for(int i = 0; i < MAXSIZE; i++)
{
int j = L.key[i] % 10;
J.a[j].key[J.a[j].next++] = L.key[i];
}
}
else //其他位数比较
{
for(int i = 0; i < MAXSIZE; i++)
{
int j = L.key[i] / (n * 10);
J.a[j].key[J.a[j].next++] = L.key[i];
}
}
for(int i = 0; i < 10; i++)
Bubble_Sort(J.a[i]);
int k = 0; //收集
for(int i = 0; i < 10; i++)
{
while(1)
{
for(int j = 0; J.a[i].key[j] >= 0; ++j)
{
L.key[k++] = J.a[i].key[j];
}
break;
}
}
}
void Bubble_Sort(Data &L){
int i,j,c,b;
for(i = 0;i < MAXSIZE;i++)
{ //一共进行20次排序
for(j = 0;j + 1 < MAXSIZE - i;j++)
{ //两两进行比较,大的数往后走
if(L.key[j] > L.key[j + 1])
{
if(L.key[j + 1] < 0)
break;
b = L.key[j + 1];
L.key[j + 1] =L.key[j];
L.key[j] = b;
}
}
}
}
希尔排序
#include<stdio.h>
#include<stdlib.h>
//希尔排序
typedef int KeyType;
//定义结构体
typedef struct
{
KeyType key;
}Data;
typedef struct
{
Data a[20];
int length;
}SqList;
SqList Shell_Sort(SqList L,int b[], int MAXSIZE); //按增量序列进行排序
SqList Shell_Insert(SqList L,int b, int MAXSIZE); //进行希尔插入排序
int main()
{
int i = 0,j,b[50], MAXSIZE;
SqList L;
scanf("%d", &MAXSIZE);
for(j = MAXSIZE / 2 + 1;j > 0;j -=2)//设置增量序列
{
b[i] = j;
i++;
}
for(i = 1; i < MAXSIZE + 1; i++) //产生20个随机数
scanf("%d", &L.a[i].key);
L = Shell_Sort(L,b,MAXSIZE);
for(i = 1; i < MAXSIZE + 1; i++)
printf("%d ", L.a[i]);
}
SqList Shell_Sort(SqList L,int b[],int MAXSIZE)
{
int k,c;
SqList J;
for(k = 0;k < 6;k++) //按照增量序列依次排序
{
J = Shell_Insert(L,b[k],MAXSIZE);
}
return J;
}
SqList Shell_Insert(SqList L,int b,int MAXSIZE)
{
int i,j;
for(i = 1 + b;i < MAXSIZE + 1;i++) //按照增量进行排序
{
if(L.a[i].key < L.a[i - b].key) //按照增量进行比较
{
L.a[0].key = L.a[i].key; //如果比后面的数小,将这个数放入哨兵处
for(j = i - b;j >= 0 && L.a[0].key < L.a[j].key;j -= b)
L.a[j + b].key = L.a[j].key; //继续按照增量继续查找比它还大的数,如果发现向后移一位
L.a[j + b].key =L.a[0].key; //最后将哨兵的值放入空值处
}
}
return L;
}
选择排序
#include<stdio.h>
#include<stdlib.h>
//选择排序
#define MAXSIZE 20
typedef int KeyType;
//定义结构体
typedef struct
{
KeyType key;
}Data;
typedef struct
{
Data a[MAXSIZE + 1];
int length;
}SqList;
SqList Selection_Sort(SqList L);
int main(){
int i;
SqList L;
for(i = 0; i < MAXSIZE; i++){ //生成20个随机数
L.a[i].key = rand() % 100;
}
L = Selection_Sort(L);
}
SqList Selection_Sort(SqList L){
int i,j,k,t,c;
for(i = 0;i < MAXSIZE;i++){
k = i; //设置一个暂存数,里面存放下标
for(j = i + 1;j < MAXSIZE;j++){
if(L.a[j].key < L.a[k].key) k = j; //如果这个数比暂存数小,交换下标
}
if(k != i){ //如果暂存数不是原来的那个数交换
t = L.a[i].key;
L.a[i].key = L.a[k].key;
L.a[k].key = t;
}
for(c = 0; c < MAXSIZE;c++){ //输出每次的排序后的结果
printf("%d ",L.a[c].key);
}
printf("\n");
}
return L;
}
各排序算法效率和复杂度: