排序算法的分类:
根据文件记录的存放位置:
- 内部排序:排序过程中将全部记录放在内存中处理
- 外部排序:排序过程中需在内外存之间交换信息
内部排序算法梳理
①插入排序:
直接插入排序(基于顺序查找)
折半插入排序(基于折半查找)
表插入排序(基于链表存储)
希尔排序(基于逐趟缩小增量)
②交换排序:
冒泡排序
快速排序
③选择排序:
简单选择排序
树形选择排序(锦标赛排序)
堆排序
④归并排序:
两路归并排序
⑤基数排序(分配排序):
基数排序
各种内部排序方法的比较
数据存储结构
约定:顺序存储,关键字类型为int型
有两种方式:
1. 数组存数据(这是我的代码版本)
2. 用到结构体(课件ppt上的版本)
#define MaxSize 20
typedef int KeyType
typedef struct
{
KeyType key;//存储关键字
InfoType otherinfo;//其余信息
}RedType;
typedef struct
{
RedType a[MaxSize+1];//a[0]闲置或作哨兵
int length;//关键字数目
}SqList;
各排序算法详解
main函数中初始化数组以及swap函数定义
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 12
void swap(int &a, int &b);
void Insert(int a[], int n);
int main()
{
int array[MAXSIZE+1];//从下标1开始存
int i;
printf("Please input %d numbers.\n", MAXSIZE);
for (i = 1; i < MAXSIZE + 1; i++)//读入MaxSize个关键字
{
scanf_s("%d", &array[i]);
}
printf("Input successfully!\n");
Insert(array, MAXSIZE);//根据不同排序算法调用的函数有所不同
printf("The result is:\n");//排好序了,下面打印
for (i = 1; i < MAXSIZE + 1; i++)
{
printf("%d ", array[i]);
}
system("pause");
return 0;
}
void swap(int &a, int &b)//swap函数定义
{
int temp;
temp = a;
a = b;
b = temp;
}
1.插入排序
- 直接插入排序
思路:
一次比到底,从第二个关键字开始,直到最后一个关键字,首先每个关键字与它前面的关键字比,看是否满足升序或降序,若不满足则swap且j往前挪一个,直到比较到第一个或者满足升序或降序。
需注意的是,插入排序就是一个个跟前面的比较,而其前面的序列已经排好队了。
和冒泡排序的差别是,直接插入一次比到底。
代码实现
void Direct_Insert(int a[], int n)//传入数组首地址(即数组名)和关键字个数即MaxSize
{
int i,j;//存储下标的变量
for(i=2;i<=n;i++)//i控制的是下标
{
j=i;
while(j>1&&a[j]<a[j-1])//如果不是升序 则swap
{
swap(a[j],a[j-1]);
j--;
}
}
}
折半插入排序
即把直接插入排序的顺序查找操作改为折半查找,以减少关键字比较次数,效率更高。2-路插入排序
希尔排序
由于直接插入排序在待排序列基本有序和待排记录数量少时,效率高,故希尔排序就是从宏观上将待排序列调整到基本有序,再使用直接插入排序将其全部排序。
而希尔排序的思路是,采用增量递减的方法,先设一个增量d,然后按增量d进行分组,每组之中采用直接插入排序,排完后减小增量d, 比如将其调整为原来的1/2,再在每组中采用直接插入排序,直到增量d为1,即只有一组,且所有关键词都在这一组中,进行最后的直接插入排序。(增量d的设定是关键)
交换排序
- 冒泡排序
算法思路:从第一位开始,临近的数两两比较,按照升序或降序进行交换,这样一趟过去后,最大或最小的数被放到最后一位,然后再从头开始两两比较,直到倒数第二位时结束,以此类推。
Notes: 冒泡排序和直接插入排序的不同:
直接插入排序是确定待插入的数之前的序列是已经排好的,只需一个个和前面的比,找到合适的位置,插入;而冒泡排序是从头开始向后两两比较,和他比较的是否满足升序或降序的条件,它都要比到最后一个,根据它是第几趟排序来判断,至多进行n-1趟
代码实现:
#define TRUE 1
#define FALSE 0
void BubbleSort(int a[],int n)
{
int Sorted;
int i,j;
for(i=0;i<n-1&&(!Sorted);i++)//因为下面要n-i故i从0开始,且至多进行n-1趟,故i<n-1
{
Sorted=TRUE;
for(j=1;j<n-i;j++)//已排好的后面i个不用比较
{
if(a[j]>a[j+1])//如果不满足升序
{
swap(a[j],a[j+1]);
Sorted=FALSE;
}
}
}
}
//Sorted作用,我认为是,当外循环第i趟时,内部无操作,则后面第i+1直到n-1趟时,内部都无操作,也就是当内部无操作时,这时已经提前排好序了,循环可以跳出了。
- 快速排序
选择排序
- 简单选择排序
算法思路:
从第一个数开始,依次往后遍历到最后一个数,找到最大的数的下标,swap第一个数和最大的数;再从第二个数开始往后遍历,直到到了最后一个数。
代码实现
void Select_Sort(int a[], int n)
{
int i, j, pos;//pos是当前要比较的元素下标
for (i = 1; i <= MAXSIZE; i++)//找当前趟最大的数
{
pos = i;
for (j = i+1; j <= MAXSIZE; j++)
{
if (a[j] > a[pos])
{
pos = j;
}
}//循环跳出后pos存储当前最大元素的下标
swap(a[i], a[pos]);
}
}