1. 引言
本文主要讲解一些常见的排序算法。
2. 归并排序
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。
复杂度:时间O(nlogn)
归并排序是稳定的排序.即相等的元素的顺序不会改变.如输入记录 1(1) 3(2) 2(3) 2(4) 5(5) (括号中是记录的关键字)时输出的 1(1) 2(3) 2(4) 3(2) 5(5) 中的2 和 2 是按输入的顺序.这对要排序数据包含多个信息而要按其中的某一个信息排序,要求其它信息尽量按输入的顺序排列时很重要.这也是它比快速排序优势的地方.
#include "ds.h"
#define MAX_SIZE 20 // 一个用作示例的小顺序表的最大长度
typedef int KeyType; // 定义关键字类型为整型
typedef int InfoType; // 定义其它数据项的类型
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)<=(b))
struct RedType // 记录类型
{
KeyType key; // 关键字项
InfoType otherinfo; // 其它数据项,具体类型在主程中定义
};
struct SqList // 顺序表类型
{
RedType r[MAX_SIZE+1]; // r[0]闲置或用作哨兵单元
int length; // 顺序表长度
};
void Merge(RedType SR[],RedType TR[],int i,int m,int n)
{ // 将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n] 算法10.12
int j,k,l;
for(j=m+1,k=i;i<=m&&j<=n;++k) // 将SR中记录由小到大地并入TR
if LQ(SR[i].key,SR[j].key)
TR[k]=SR[i++];
else
TR[k]=SR[j++];
if(i<=m)
for(l=0;l<=m-i;l++)
TR[k+l]=SR[i+l]; // 将剩余的SR[i..m]复制到TR
if(j<=n)
for(l=0;l<=n-j;l++)
TR[k+l]=SR[j+l]; // 将剩余的SR[j..n]复制到TR
}
void MSort(RedType SR[],RedType TR1[],int s, int t)
{ // 将SR[s..t]归并排序为TR1[s..t]。算法10.13
int m;
RedType TR2[MAX_SIZE+1];
if(s==t)
TR1[s]=SR[s];
else
{
m=(s+t)/2; // 将SR[s..t]平分为SR[s..m]和SR[m+1..t]
MSort(SR,TR2,s,m); // 递归地将SR[s..m]归并为有序的TR2[s..m]
MSort(SR,TR2,m+1,t); // 递归地将SR[m+1..t]归并为有序的TR2[m+1..t]
Merge(TR2,TR1,s,m,t); // 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t]
}
}
void MergeSort(SqList &L)
{ // 对顺序表L作归并排序。算法10.14
MSort(L.r,L.r,1,L.length);
}
void print(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
printf("(%d,%d)",L.r[i].key,L.r[i].otherinfo);
printf("\n");
}
#define N 7
int main()
{
RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7}};
SqList l;
int i;
for(i=0;i<N;i++)
l.r[i+1]=d[i];
l.length=N;
printf("排序前:\n");
print(l);
MergeSort(l);
printf("排序后:\n");
print(l);
}
求逆序数
#include <stdio.h>
#include <stdlib.h>
//
//求逆序数
//最快的算法是归并排序时计算逆序个数,时间复杂度是nlog2n, 空间复杂度是2n
//a为字符数组,len为字符数组的长度
int number = 0; //number表示逆序对的个数
void mergePass(char *, char *, int, int);
void merge(char*, char*, int, int, int);
void copy(char *dest, char *src, int l, int r)
{
while(l <= r)
{
dest[l] = src[l];
l++;
}
}
void mergeSort(char *a, int size)
{
char *b = (char*)malloc(sizeof(char) * size);
mergePass(a, b, 0, size - 1);
free(b);
}
void mergePass(char *a, char *b, int l, int r)
{
int m;
if(l < r)
{
m = (l + r) / 2;
mergePass(a,b,l,m);
mergePass(a,b,m+1,r);
merge(a,b,l,m,r);
copy(a,b,l,r);
}
}
void merge(char *a, char *b, int l, int m, int r)
{
int i = l, j = m + 1;
while( i <= m && j <= r)
{
if(a[i] <= a[j])
b[l++] = a[i++];
else
{
b[l++] = a[j++];
//a[i] > a[j], 表示出现了逆序对,此时由于
//a[i..m]是已经有序了,那么a[i+1], a[i+2], ... a[m]都是大于a[j]的,
//都可以和a[j]组成逆序对,因此number += m - i + 1
number += m-i+1;
}
}
while(i <= m)
b[l++] = a[i++];
while(j <= r)
b[l++] = a[j++];
}
int main()
{
char a[10] = {'A','A','C','A','T','G','A','A','G','G'};
char b[5] = {'A', 'B', 'A', 'A','A'};
mergeSort(b, 5);
for(int i = 0; i < 10; i++)
printf("%c ",a[i]);
printf("%d ", number);
system("pause");
return 0;
}