2021-03-22

数据结构——排序算法

一,插入算法

1,直接插入

void InsertSort(ElemType A[],int n)
{
  int i,j;
  for(i=2;i<n;i++)
  {
    if(A[i]<A[i-1])
    {
      A[0]=A[i];//A[0]为哨兵
      for(j=i-1;A[0]<A[j];--j)//从后向前查找待插入的位置
      	A[j+1]=A[j];
      A[j+1]=A[0];
    }
  }
}

空间复杂度为 O(1)
在最好的情况下,元素已基本有序,此时插入时只需要比较一次,而不用移动元素,此时时间复杂度为O(n)平均情况下,时间复杂度为O(n2)
稳定的
适用于顺序存储和链式存储的线性表

2,折半插入算法

void InsertSort(ElemType A[], int n)
{
  int i,j,low high,mid;
  for(i=2;i<n;i++)//依次将A[2]~A[n]插入到前面已排序序列
  {
  	A[0]=A[i];
  	low=1;high=i-1;
  	while(low<=high){
  	  mid=(high+low)/2;
  	  if(A[mid]>A[0]) high=mid-1;
  	  else low=mid+1;
  	  }
  	for(j=i-1;j>=high+1;--j)
  	  A[j+1]=A[j];
  	A[high+1]=A[0];
  }

}

折半查找仅仅减少了元素的比较次数,该比较次数与待排续表的初始状态无关,仅取决于表中元素的个数n,而移动次数并为改变,它依赖于表的初始序列,因此时间复杂度仍未O(n2),是稳定的。

3,希尔排序

void ShellSort(ElemType A[], int n)
{
//A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到

  for(dk=n/2;dk>=1;dk=dk/2)
  {
  	for(i=dk+1;i<=n;++i)
  	  if(A[i]<A[i-dk]){
  	  A[0]=A[i];
  	  for(j=i-dk;j>0&&A[0]<A[j];j-=dk)
  	  	A[j+dk]=A[0];

  }

}

空间复杂度为O(1)
最坏的情况下,时间复杂度为O(n2)
是一种不稳定的算法,仅适用于线性表尾顺序存储的情况。

二,交换排序

1,冒泡排序

void BubbleSort(ElemType A[],int n)
{
  for(i=0;i<n-1;i++)
  {
  	flag=false;
  	for(j=n-1;j>i;j--)
  	  if(A[j-1]>A[j]){
  	    swap(A[j-1],A[j]);
  	    flag=true;
  	  }
  	 if(flag==false)//本趟遍历没有发生交换,说明表已经有序。
  	   return;

  }
}

空间复杂度为O(1)
最坏情况下时间复杂度为O(n2),平均情况下时间复杂度也为O(n2)
稳定
每趟都会将一个元素放在其最终位置上

2,快速排序
递归的调用快速排序算法进行排序

void QuickSort(EleType A[], int low, int high){
  if(low<high){
    int pivotpos=partition(A,low,high);
    QuickSort(A,low,pivotpos-1);
    QuickSort(A,pivotpos+1,high);
  }
}

非递归方法,假设每次总以当前表中第一个元素作为枢轴来对表进行划分。

int Partition(ElemType A[], int low, int high)
{
  ElemType pivot=A[low];
  while(low<high){
    while(low<high&&A[high]>=pivot) --high;
    A[low]=A[high];
    while(low<high&&A[low]<=pivot) ++low;
    A[high]=A[low];//将比枢轴大的元素移动到右端

}
A[low]=pivot;//枢轴元素存放到最终位置
return low;
}

每趟排序后会将枢轴元素放到其最终位置上。
不稳定
最好的情况下,空间效率为O(log2n),最坏的情况下,栈的深度为O(n),平均情况下,栈的深度为O(log2n)
时间效率:快速排序的运行时间与划分是否对称有关,初始排序表基本有序或基本逆序时,情况最坏,时间复杂度为O(n2),理想情况下,时间复杂度为O(nlog2n)
快速排序算法是所有内部排序算法中平均性能最优的排序算法

三,选择排序

1,简单选择排序

void SelectSort(ElemType A[], int n){
  for(i=0;i<n-1;i++){
    min=i;
    for(j=i+1;j<n;j++)
       if(A[j]<A[min]) min=j;
    if(min!=i) swap(A[i],A[min]);
    }
    }

空间效率为O(1)
时间复杂度为O(n2)
不稳定
元素之间的比较次数和初始序列无关

2,堆排序
空间复杂度为O(1)
建堆时间为O(n),每次调整时间复杂度为O(h)
在最好,最坏和平均情况下,堆排序的时间复杂度为O(nlog2n)

四,归并排序和基数排序

归并排序的空间复杂度为O(n)
时间复杂度为O(nlog2n)
稳定
基数排序不基于比较和移动进行排序
空间复杂度为O®
一趟分配需要O(n),一趟收集需要O®,所以时间复杂度为O(d(n+r)),它与序列的初始状态无关

你可能感兴趣的:(小白C语言学习笔记)