数据结构——内排序

一、排序的基本概念

排序,是整理表中的记录,使之按关键字递增(或递减)。
排序过程中,若整个表都在内存中处理,不涉及数据的内、外存交换,则称之为内排序;反之,则称之为外排序

1.内排序的分类

在这里插入图片描述

2.内排序算法的稳定性

表中,存在有多个关键字相同的记录,排序后相同关键字的记录之间的相对次序保持不变,则这种排序方法是稳定的。反之,则不稳定。

3.正反序

表中元素已按关键字排好序,称此表中元素为正序;
表中元素的关键字顺序正好和排好序的顺序相反,反序。

4.内排序数据结构定义

typedef int KeyType;    	//定义关键字类型
typedef struct          	//记录类型
{  KeyType key;         	//关键字项
   InfoType data;       	//其他数据项,类型为InfoType
}  RecType;	            	//排序的记录类型定义 

二、插入排序

在这里插入图片描述

1.直接插入排序

void InsertSort(RecType R[]int n) 
{  int i, j;   RecType tmp;
   for (i=1;i<n;i++) 
   {  if (R[i].key<R[i-1].key]) //反序时,不反序不用排,直接看for循环后面的
      {  tmp=R[i];
	  j=i-1; 
         do			//找R[i]的插入位置
         {  R[j+1]=R[j];   	//关键字大于R[i].key的记录,则后移
            j--;
         }  while  (j>=0 && R[j].key>tmp.key)
         R[j+1]=tmp;      	//在j+1处插入R[i]
      }
   }
}

最好(正序):O(n)
最坏(反序):O(n2)
平均情况:比较次数+移动次数,平均:O(n2)

2.折半插入排序

查找采用折半查找方法,称为二分插入排序或折半插入排序。

void BinInsertSort(RecType R[]int n)
{  int i,j,low,high,mid;
   RecType tmp;
   for (i=1;i<n;i++) 
   {  if (R[i].key<R[i-1].key])	//反序时
      {  tmp=R[i];		  	//将R[i]保存到tmp中
	  low=0; high=i-1;
	  while (low<=high)	  	//在R[low..high]中查找插入的位置
	  {  mid=(low+high)/2;	//取中间位置
	     if (tmp.key<R[mid].key)
	        high=mid-1;		//插入点在左半区
	     else
	        low=mid+1;		//插入点在右半区
	  }                          //找位置high+1
	  for (j=i-1;j>=high+1;j--)	//记录后移
	     R[j+1]=R[j];
	  R[high+1]=tmp;		//插入tmp
      }
   }
}

在R[0…i-1]中查找插入R[i]的位置,折半查找的平均关键字比较次数为log2(i+1)-1。
平均移动元素的次数为i/2+2。
折半插入排序采用折半查找,查找效率提高,即关键字比较次数减少了。
但元素移动次数不变

3.希尔排序

希尔排序的时间复杂度约为O(n1.3)。
即先按间距分组,先将一组组内拍好,再将另一组数据依次插入。
在这里插入图片描述
如d=5,则是分5组,依次类推直到d=1为止。

void ShellSort(RecType R[]int n)
{  int i, j, d;
   RecType tmp;
   d=n/2;	  	//增量置初值
   while (d>0)
   {  for (i=d;i<n;i++)
      {   //对相隔d位置的元素组直接插入排序
         tmp=R[i];
         j=i-d;
	  while (j>=0 && tmp.key<R[j].key)
	  {  R[j+d]=R[j];
	     j=j-d;
	  }
	  R[j+d]=tmp;
      }
      d=d/2;	 	//减小增量
   }
}

希尔排序法是一种不稳定的排序算法。对于排序算法,所谓的不稳定指的就是相同元素在排序过程中被移动。

三、交换排序

两个元素反序时进行交换

1.冒泡排序(或起泡排序)

void BubbleSort(RecType R[]int n)
{  int i,j;  RecType temp;
   for (i=0;i<n-1;i++) 
   {
      for (j=n-1;j>i;j--)  		//比较找本趟最小关键字的记录
         if (R[j].key<R[j-1].key)	//反序   
	     swap(R[j],R[j-1]);    	//R[j]与R[j-1]交换
   }
} 
//改进
void BubbleSort(RecType R[]int n)
{  int i,j;  bool exchange;  RecType temp;
   for (i=0;i<n-1;i++) 
   {
       exchange=false;
       for (j=n-1;j>i;j--)  	//比较,找出最小关键字的记录
          if (R[j].key<R[j-1].key) 	//反序,交换 	
          {  swap(R[j],R[j-1]);
             exchange=true;
	   }
       if (exchange==false) return;  //中途结束算法
   }
}

一旦某一趟比较时不出现记录交换,说明已排好序了,就可以结束本算法。
冒泡排序最好时间复杂度为O(n),最坏和平均为O(n2)。

2.快速排序

  • 每趟使表的第1个记录(基准)放入适当位置(归位),将表一分为二,对子表按递归方式继续这种划分.
  • 直至划分的子表长为0或1(递归出口)。
    在这里插入图片描述
    在这里插入图片描述
int partition(RecType R[],int s,int t)  //一趟划分
{  int i=s,j=t;
   RecType tmp=R[i];	//以R[i]为基准
   while (i<j)  	//从两端交替向中间扫描,直至i=j为止
   {  while (j>i && R[j].key>=tmp.key)
         j--;		//从右向左扫描,找一个小于tmp.key的R[j]
      R[i]=R[j];	//找到这样的R[j],放入R[i]处
      while (i<j && R[i].key<=tmp.key)
         i++;		//从左向右扫描,找一个大于tmp.key的R[i]
      R[j]=R[i];	//找到这样的R[i],放入R[j]处
   }
   R[i]=tmp;
   return i;
}

快速排序的平均时间复杂度为O(nlog2n)。平均所需栈空间为O(log2n)。

(未完待续…)

四、选择排序

五、归并排序

六、基数排序

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值