排序算法:
排序方法 | 平均时间 | 最坏情况 | 辅助空间 |
简单排序 | O(n^2) | O(n^2) | O(1) |
快速排序 | O(n*log2n) | O(n^2) | O(log2n) |
堆排序 | O(n*log2n) | O(n*log2n) | O(1) |
归并排序 | O(n*log2n) | O(n*log2n) | O(n) |
基数排序 | O(d(n+Radix)) | O(d(n+Radix)) | O(Radix) |
1) 在平均情况下,快速排序、堆排序以及归并排序有较好的时间性能,其中以快速排序最佳,它所需要时间最少,但在最坏情况下,快速排序不如堆排序和归并排序。而堆排序与归并排序之间的比较结果是,当元素较多时,归并排序的时间性能好于堆排序,但它需要辅助空间较多,而堆排序只需要一个辅助空间。
2) 直接插入排序、冒泡排序和简单选择排序等简单排序方法的时间复杂度都为O(n^2)。在这些方法中,以直接插入排序最简单,且当待排序的元素很少,或者待排序的元素序列基本有序时,直接插入排序是很好的排序方法,因此,常将直接插入排序与其他排序方法结合在一起使用。
3)希尔排序的时间性能较难分析,但大量实验结果和实例证明他是一种很好的内部排序方法。
4) 基数排序的时间复杂度为O(d(n+Radix))也可以表示为O(d*n)。当d很小时趋向于O(n),因此,基数排序适用于元素量大,但关键字的位数较少的元素序列。
5) 由于基数排序不进行关键字比较,因此他是最稳定的排序方法。简单排序方法也是稳定的,然而,快速排序、希尔排序、堆排序等时间性能较好的排序方法都是不稳定的。因此,若按照次关键字进行排序,则需要慎重选择排序方法,但若按照主关键字进行排序,则排序方法是否稳定无关紧要。
6) 可以证明,借助于“比较”进行排序的方法在最坏情况下能够达到的最好时间复杂度是O(n*log2n).
由以上讨论可知,以上介绍的排序方法,没有哪一种是绝对最有的,每一种排序方法都有它的适用范围,在实际应用中应根据实际情况合理选择排序方法。
以下代码实现中缺少希尔排序、基数排序,待补充。。。。。。
C++
#include
using namespace std;
template struct ElementType
{
Type Key;//数据元素的关键字
//数据元素的其他数据项
};
template struct SqList
{
ElementType *elem;//数组elem存放数据元素,其中elem[0]闲置
int length;//顺序表中的元素个数
// int listsize;//顺序表的长度
};
/* 直接插入排序*/
template void InsertSort(SqList &List)
{//O(n^2)
ElementType temp;
for(int i=1;i void BinInsertSort(SqList &List)
{//O(n^2)
ElementType temp;
for(int i=1;ilow;j--) List.elem[j]=List.elem[j-1];//元素后移
List.elem[low]=temp;//插入元素
}
}
//交换排序之冒泡排序
#define SWAP(a,b) {int temp=a;a=b;b=temp;}
template void BubbleSort(SqList &List)
{
int i,j;
for(i=0;ii;j--)
{
if(List.elem[j].Key int Partition(SqList &List,int low,int high)
{
ElementType elem=List.elem[low];//将字表的第一个元素作为基准元素
Type pivotkey=elem.Key;
int i=low,j=high;
while(i=pivotkey) j--;
if(i void QuickSort(SqList &List,int low,int high)
{
if(low void MergeSort(SqList &List ,int left,int right)
{
if(left void Merge(SqList &List,int left,int mid,int right)
{
ElementType *temp=new ElementType[right-left+1];
int i=left,j=mid+1,k=0;
while(i<=mid && j<=right)
{
if(List.elem[i].Key<=List.elem[j].Key) temp[k++]=List.elem[i++];
else temp[k++]=List.elem[j++];
}
while(i<=mid) temp[k++]=List.elem[i++];
while(j<=right) temp[k++]=List.elem[j++];
for(i=0,k=left;k<=right;) List.elem[k++]=temp[i++];
}
//简单选择排序
template void SelectSort(SqList &List)
{
for(int i=0;i element=List.elem[i];
List.elem[i]=List.elem[small_loc];
List.elem[small_loc]=element;
}
}
}
//堆排序
template void HeapAdjust(SqList &List, int i, int j)
{//除了第一个元素外,顺序表List[i...j]中元素都满足堆的定义,本函数将List中的所有元素调整为一个最大堆
int child=2*i;
ElementType temp=List.elem[i];//临时存放根节点
while(child<=j) //沿大儿子向下调整
{
if(childList.elem[child].Key) child++;
if(temp.Key>=List.elem[child].Key) break;
List.elem[(child/2)]=List.elem[child];
child=2*child;
}
List.elem[child/2]=temp;
}
template void HeapSort(SqList &List)
{
int i;
for(i=List.length/2;i>=0;i--)
HeapAdjust(List,i,List.length-1);//初始建堆
for(i=List.length-1;i>=0;i--)
{
ElementType temp=List.elem[0];//将当前堆顶元素与堆尾元素互换
List.elem[0]=List.elem[i];
List.elem[i]=temp;
HeapAdjust(List,0,i-1);//将剩下的元素重新调整成堆
}
}
int main()
{
SqList list;
ElementType p[]={{1},{2},{33},{3},{4},{5},{6},{10},{9},{7},{8},{20},{44}};
// int a[]={2,1,3,5,4,9,6,7,8,10};
list.length=sizeof(p)/sizeof(p[0]);
list.elem=p;
// InsertSort(list);
// BinInsertSort(list);
// BubbleSort(list);
// QuickSort(list,1,list.length-1);
// MergeSort(list,0,list.length-1);
// SelectSort(list);
HeapSort(list);
cout<<"排序后:";
for(int j=0;j
java版
package HelpAlgri;
import java.util.Arrays;
import java.util.Random;
public class SortAll {
/*
* 折半插入排序O(n^2)
*/
private static int[] Sort(int[] arr) {
int i, j;
//保存中间插入的值
int insertNote = 0;
//将待排序的数列保存起来
int[] array = arr;
System.out.println("开始排序:");
for (i = 1; i < array.length; i++) {
int low = 0;
int high = i - 1;
insertNote = array[i];
//不断的折半
while (low <= high) {
//找出中间值
int mid = (low + high) / 2;
//如果大于中间值
if (array[i] > array[mid]) {
//在大于中间值的那部分查找
low = mid+1;
} else
//在小于中间值的那部分查找
high = mid-1;
}
//将整体数组向后移
for ( j=i; j > low; j--) {
array[j] = array[j - 1];
}
//插入到指定的位置
array[low] = insertNote;
System.out.println(Arrays.toString(array));
}
System.out.println("排序之后:");
System.out.println(Arrays.toString(array));
return array;
}
/*
* 直接插入排序O(n^2)
*/
public static int[] InsertSort(int[] arr){
int[] array=arr;
int i,j,temp;
for(i=1;i=0 && tempi;j--){
if(array[j]=elem) j--;
if(i=0;i--){//初始建堆
HeapAdjust(arr,i,arr.length-1);
}
for(i=arr.length-1;i>=0;i--){//将当前堆顶元素与堆尾元素互换
int temp=arr[0];
arr[0]=arr[i];
arr[i]=temp;
HeapAdjust(arr,0,i-1);//将剩下的元素重新调整成堆
}
}
public static void HeapAdjust(int[] arr,int i,int j){
int child=2*i;
int temp=arr[i];//临时存放根节点
while(child<+j){ //沿大儿子向下调整
if(childarr[child]) child++;
if(temp>=arr[child]) break;
arr[child/2]=arr[child];
child=2*child;
}
arr[child/2]=temp;
}
public static void main(String[] args) {
Random random = new Random();
int[] array = new int[10];
for (int i = 0; i < 10; i++) {
array[i] = Math.abs(random.nextInt() % 100);
}
System.out.println("排序之前:");
System.out.println(Arrays.toString(array));
// SortAll.Sort(array);//折半插入排序
// SortAll.InsertSort(array); //直接插入排序
// SortAll.BubbleSort(array); //冒泡排序
// SortAll.BubbleSort(array);//选择排序
SortAll.HeapSort(array);//堆排序
System.out.println(Arrays.toString(array));
// System.out.println(Arrays.toString(SortAll.QuickSort(array,0,array.length-1)));//快速排序
// System.out.println(Arrays.toString(SortAll.MergeSort(array,0,array.length-1)));//归并排序
}
}