以下内容部分参考《王道数据结构2020》
概述
排序算法一般分为两大类,一类是外部排序,这种排序的规模往往比较大,要排序的数据无法同时存放在内存中,必须在排序的过程中不断的在内外存之间移动;另一类是内部排序,规模较小。可以在完全在内存中进行。今天主要实现的是内部排序,常见的内部排序又可以分为五大类:插入排序、交换排序、选择排序、归并排序、基数排序。
一、插入排序
1.1 直接插入排序
主要思想
每次将一个待排序的记录,插入到前面已经有序的子序列中的恰当位置,直到全部记录插入完成
具体步骤:
- 查找L(i)在L(1…i-1)适当的插入位置k
- 从L(k)开始,所有元素向后移动一个位置
- 将L(i)复制到L(k)
算法实现(C语言)
#include <stdio.h>
#define MAX 30
//定义数组
typedef struct {
int r[MAX];
int length;
}List;
int insertsort(List &l)
{
int i,j;
for(i=1;i<=l.length;i++)
{
l.r[0]=l.r[i];//r[0]位置做哨兵
for(j=i-1;j>=0&&l.r[0]<l.r[j];j--)
//在1...i-1之间找到合适的插入位置,同时判断是否需要向后移动元素的位置
{
l.r[j+1]=l.r[j];//向后移动元素的位置
}
l.r[j+1]=l.r[0];//找到合适的位置插入
}
return 1;
}
//初始化数组
void initial(List &l)
{
int i;
printf("please input size:");
scanf("%d",&l.length);
printf("input data:");
for(i=1;i<=l.length;i++)
scanf("%d",&l.r[i]);
}
main()
{
List l;
int i;
initial(l);
insertsort(l);
printf("data output:");
for(i=1;i<=l.length;i++)
printf("%d ",l.r[i]);
}
二、交换排序
2.1 冒泡排序
主要思想
1.简述:从前往后(或从后往前)两两比较相邻元素的值,若为逆序,则交换它们,直到序列比较完毕,这是一趟冒泡排序,结果将最大的元素交换到序列的最后一个位置,确定了一个元素的最终位置。
2.详述:从前往后(或从后往前)从第一个元素开始,与第二个元素比较它们的值大小,若第一个元素的值大于第二个元素,则交换它们的位置,然后从第二个开始和第三个比较…直到第n-1个元素和第n个元素比较完毕,一趟下来,可以确定最大的元素已经在序列的最后一个位置,那么下一次排序就不用再和最后一个元素比较了,因为它的位置已经是正确的了,所以第二次只需要比较n-1次,依次类推,每完成一趟排序,待排序元素便少了一个。
图为冒泡排序的过程,第一趟冒泡时27 < 49 , 不交换; 13 < 27 ,不交换: 76 > 13,交换 : 97 > 13,交换: 65 > 13,交换;38 > 13,交换: 49 > 13,交换。通过第一趟冒泡后,最小元素己交换到第一个位置 ,也是它的最终位置。第二趟冒泡时对剩余子序列采用同样方法进行排序,以此类推,到第六趟结束后没有发生交换,说明表己有序,冒泡排序结束。
算法实现(C语言)
#include <stdio.h>
#define MAX 30
//定义数组
typedef struct
{
int r[MAX];
int length;
}List;
int bubblesort(List &l)
{
int i,j,t;
for(i=0;i<l.length;i++)
for(j=0;j<l.length-i-1;j++)
if(l.r[j]>l.r[j+1])
{
t=l.r[j];
l.r[j]=l.r[j+1];
l.r[j+1]=t;
}
return 1;
}
int initial(List &l)
{
int i;
printf("input size:");
scanf("%d",&l.length);
printf("input data please:");
for(i=0;i<l.length;i++)
{
scanf("%d",&l.r[i]);
}
return 1;
}
main()
{
List l;
int i;
initial(l);
bubblesort(l);
printf("output data:");
for(i=0;i<l.length;i++)
printf("%d ",l.r[i]);
}
2.2快速排序
主要思想
快速排序是基于分治法的:在待排序表 L[l…n ]中任取一个元素 pivot 作为枢轴(或基准,通常取首元素),通过一趟排序,将待排序表划分为独立的两部分 L[l…k-1 ] 和 [k+l…n],使得 L[l…k - 1 ] 中的所有元素小于 pivot,L [k+ l… n ] 中的所有元素大于等于 pivot,则 pivot 放在了其最终位置 L ( k ) 上,这个过程称为 一趟快速排序(或一次划分)。然后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在了其最终位置上 。
一趟快速排序的过程是一个交替搜索和交换的过程,下面通过实例来介绍。
如图所示,假设两个指针 i 和 j,初值分别为 low 和 high ,取第一个元素 49 为枢轴赋值到变量 pivot 。指针 j 从 high 往前搜索找到第一个小于枢轴的元素 27 , 将 27 交换到 i 所指位置 。
算法实现(C语言)
#include <stdio.h>
#define MAX 30
//定义数组
typedef struct {
int r[MAX];
int length;
}List;
void QuickSort(List *l, int low, int high){
if(low<high){ //递归跳出的条件
int pivotpos = Partition(l, low, high); //划分
QuickSort(l, low, pivotpos-1); //依次对两个子表进行递归操作
QuickSort(l, pivotpos+1, high);
}
}
int Partition(List *l, int low, int high){
int pivot = l->r[low];
while(low<high){
while(low<high && l->r[high] >= pivot)
--high;
l->r[low] = l->r[high];
while(low <high && l->r[low] <= pivot)
++low;
l->r[high] = l->r[low];
}
l->r[low] = pivot;
return low;
}
void Print(List l){
for(int i=0;i<l.length;i++){
printf("%d ", l.r[i]);
}
printf("\n");
}
void main(){
List l = {{49,38,65,97,76,13,27,49},8};
Print(l);
QuickSort(&l, 0, 7);
Print(l);
}
稳定性
在划分算法中,若右端区间有两个关键字相同,且均小于基准值的记录,则在交换到左端区间后,它们的相对位置会发生变化,即快速排序是一种不稳定的排序方法。例如 , 表 l = { 3, 2 , 2 },经过一趟排序后 l = { 2, 2, 3 },最终排序序列也是 l = { 2 , 2, 3 },显然 ,2 与 2 的相对次序己发生了变化 。
三、选择排序
3.1 简单选择排序
主要思想
假设要排序的序列是L(1…n),第i趟排序从L(i…n)里面选出最小的元素与L(i)交换,每一趟排序可以确定一个元素的最终位置,待排序元素也就少了一个,经过n-1趟排序后序列有序。
算法实现(C语言)
#include <stdio.h>
#define MAX 30
//定义数组
typedef struct {
int r[MAX];
int length;
}List;
void selectsort(List &l)//mian idear is remmber the number of smallest element after every compare with others
{
int k,i,j,t;
for(i=1;i<l.length;i++)//为了下标与元素序号的统一性,这里设置l.r[0]没有存放数据,从l.r[1]开始存放数据
{
k=i;
for(j=i+1;j<=l.length;j++)
if(l.r[j]<l.r[k])
k=j;
if(k!=i)
{
t=l.r[k];
l.r[k]=l.r[i];
l.r[i]=t;
}
}
}
int initial(List &l)
{
int i;
printf("input size:");
scanf("%d",&l.length);
printf("input data please:");
for(i=1;i<=l.length;i++)
{
scanf("%d",&l.r[i]);
}
return 1;
}
main()
{
List l;
int i;
initial(l);
selectsort(l);
printf("output data:");
for(i=1;i<=l.length;i++)
printf("%d ",l.r[i]);
}
3.2 堆排序
未完待续…