您的位置:首页 > 编程语言 > C语言/C++

C++排序:冒泡排序,简单选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序

2015-10-07 10:21 886 查看
1、排序的稳定性:

假设 Ki=Kj (1≤i≤n,1≤j≤n,i≠j),在排序前的序列中 i<j,如果排序后 i 仍然领先于 j ,则所用排序方法稳定;反之若可能使排序后序列 j 领先 i,则所用排序方法不稳 定。

2、内排序与外排序

内排序是在排序整个过程中,待排序的所有记录全部被放置在内存中;外排序是由于排序的记录个数太多,不能同时放置在内存,整个排序过程需要在内外村之间多次交换 数据才行。

1)对于内排序,排序算法的性能主要受3个方面影响:1.时间性能;2.辅助空间(辅助存储空间);3)算法的复杂性(算法本身的复杂度)。

2)根据排序过程中借助的主要操作,内排序分为:插入排序、交换排序、选择排序、归并排序。

3)根据算法的复杂度分为两大类:1.简单算法:冒泡排序、简单选择排序、直接插入排序;2.改进算法:希尔排序、堆排序、归并排序、快速排序。



//按顺序输出数组
void print(int a[], int n)
{
for(int i=0;i<n;i++)
{
cout<< a[i] <<" ";
}
cout<<endl;
}

//数组两元素的交换
void swap(int a[], int i, int j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}


1.冒泡排序:

//对数组a[]作交换排序(冒泡排序初级版)
void BubbleSort0(int a[], int n)
{
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
if(a[i]>a[j])
swap(a,i,j);
}
}
}

//冒泡排序
void BubbleSort(int a[], int n)
{
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-i-1;j++)
{
if(a[j]>a[j+1])
swap(a,j,j+1);
}
}
}

//改进冒泡算法
void BubbleSort2(int a[], int n)
{
int flag = 1;//flag做为标记
for(int i=0;i<n-1&&flag==1;i++)
{
flag = 0;
for(int j=0;j<n-i-1;j++)
{
if(a[j]>a[j+1])
{
swap(a,j,j+1);
flag = 1;//有数据交换则flag为1
}
}
}
}


2.简单选择排序:

//简单选择排序
void SelectSort(int a[], int n)
{
int min;
for(int i=0;i<n-1;i++)
{
min = i;
for(int j=i+1;j<n;j++)
{
if(a[min]>a[j])
min = j;
}
if(i != min)
swap(a,i,min);
}
}


3.直接插入排序:

//直接插入排序
void InsertSort(int a[],int n)
{
for(int i=1;i<n;i++)
{
if(a[i]<a[i-1])
{
int x = a[i];
int j = i-1;
for(;a[j]>x;j--)
{
a[j+1] = a[j];
}
a[j+1] = x;
}
}
}


4.希尔排序:

//希尔排序
void ShellSort(int a[], int n)
{
int num = n;
int x;
do
{
num = num/3 +1;
for(int i=num;i<n;i++)
{
if(a[i]<a[i-num])
{
x = a[i];
int j=i-num;
for(;j>=0&&x<a[j];j-=num)
a[j+num] = a[j];
a[j+num] = x;
}
}
}
while(num>1);
}


5.堆排序:

//堆排序
//使a[i,n]成为一个大顶堆
void HeapAdjust(int a[],int s, int m)
{
int temp = a[s];
for(int j=2*s;j<=m;j*=2)
{
if(j<m && a[j]<a[j+1])
j++;
if(temp>=a[j])
break;
a[s] = a[j];
s = j;
}
a[s] = temp;
}
//对数组a进行堆排序
void HeapSort(int a[], int n)
{
for(int i=n/2;i>=0;i--)
HeapAdjust(a,i,n);
for(int i=n-1;i>0;i--)
{
swap(a,0,i);
HeapAdjust(a,0,i-1);
}
}


6.归并排序:

1)递归实现:

//归并排序
//将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]
void Merge(int SR[], int TR[], int i, int m, int n)
{
int j,k,x;
for(j=m+1,k=i; i<=m && j<=n; k++)
{
if(SR[i] < SR[j])
TR[k] = SR[i++];
else
TR[k] = SR[j++];
}
while(i<=m)
{
TR[k++] = SR[i++];
}
while(j<=n)
{
TR[k++] = SR[j++];
}
}
//将SR[s..t]归并排序为TR1[s..t]
void MSort(int SR[], int TR1[], int s, int t)
{
int m;
int TR2[20];
if(s==t)
TR1[s]=SR[s];
else
{
m = (s+t)/2;
MSort(SR,TR2,s,m);
MSort(SR,TR2,m+1,t);
Merge(TR2,TR1,s,m,t);
}
}
//对数组a[]进行归并排序
void MergeSort(int a[], int b[], int n)
{
MSort(a,b,0,n-1);
}


2)非递归实现:

7.快速排序:

1)

//交换数组a[]中子集的记录,使枢轴记录到位,并返回其所在位置
//此时在它之前(后)的记录均不大(小)于它
int Partition(int a[], int low, int high)
{
int pivotkey = a[low];
while(low<high)
{
while(low<high && a[high]>=pivotkey)
high--;
swap(a,low,high);
while(low<high && a[low]<=pivotkey)
low++;
swap(a,low,high);
}
return low;
}
//对数组a[]在子集a[low..high]作快速排序
void QSort(int a[], int low, int high)
{
if(low<high)
{
int pivot = Partition(a,low,high);
QSort(a,low,pivot-1);
QSort(a,pivot+1,high);
}
}
//对数组a[]作快速排序
void QuickSort(int a[], int n)
{
QSort(a,0,n-1);
}


2)优化小数组时的排序方案(如果数组非常小时,快速排序反而不如直接插入排序来的更好):

//优化小数组时的排序方案
const int MAX_LENGTH_INSERT_SORT = 7;
void QSort1(int a[], int low, int high)
{
if((high-low)>MAX_LENGTH_INSERT_SORT)
{
int pivot = Partition(a,low,high);
QSort(a,low,pivot-1);
QSort(a,pivot+1,high);
}
else
InsertSort(a,high-low+1);
}


3)优化递归操作:

//优化递归操作
void QSort2(int a[], int low, int high)
{
if((high-low)>MAX_LENGTH_INSERT_SORT)
{
while(low<high)
{
int pivot = Partition(a,low,high);
QSort2(a,low,pivot-1);
low = pivot+1;
}
}
else
InsertSort(a,high-low+1);
}


3)优化选取枢轴和不必要交换:

//优化选取枢轴和不必要交换
int Partition1(int a[], int low, int high)
{
//优化选取枢轴
int m = low+(high-low)/2;
if(a[low]>a[high])
swap(a,low,high);
if(a[m]>a[high])
swap(a,high,m);
if(a[m]>a[low])
swap(a,m,low);

int pivotkey = a[low];
int flag = pivotkey;//枢轴备份到flag
while(low<high)
{
while(low<high && a[high]>=pivotkey)
high--;
a[low] = a[high];//采用替换而不是交换的方式
while(low<high && a[low]<=pivotkey)
low++;
a[high] = a[low];//采用替换而不是交换的方式
}
a[low] = flag;//将枢轴数值替换回a[low]
return low;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: