数据结构之排序

第十章   排序

1. 直接插入排序

排序过程

     整个排序过程为n-1 趟插入,即先将序列中第1 个记录看成是一个有序子序列,然后从第2个记录开始,逐个进行插入,直至整个序列有序。
   

 

2. 冒泡排序

排序过程

  1  将第一个记录的关键字与第二个记录的关键字进行比较,若为逆序 序r[1].key>r[2].key ,则交换;然后比较第二个记录与第三个记录;依次类推,直至第n-1 个记录和第n 个记录       比较为止—— 第一趟冒泡排序 ,结果关键字最大的记录被安置在最后一个记录上
  2  对前n-1 个记录进行第二趟冒泡排序,结果使关键字次大的记录被安置在第n-1 个记录位置
  3  重复上述过程,直到 “ 在一趟排序过程中没有进行过交换记录的操作 ” 为止
     

3. 简单选择排序

排序过程

   1  首先通过n-1 次关键字比较,从n 个记录中找出关键字最小的记录,将它与第一个记录交换
   2  再通过n-2 次比较,从剩余的n-1 个记录中找出关键字次小的记录,将它与第二个记录交换
   3  重复上述操作,共进行n-1

 

4. 快速排序

基本思想

通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录进行排序,以达到整个序列有序

排序过程

1   对r[s……t] 中记录进行一趟快速排序,附设两个指针i 和j ,设枢轴记录rp=r[s] ,x=rp.key
2   初始时令i=s,j=t
3   首先从j 所指位置向前搜索第一个关键字小于x 的记录,并和rp交换
4   再从i 所指位置起向后搜索,找到第一个关键字大于x 的记录,和rp 交换
5   重复上述两步,直至i==j 为止
6   再分别对两个子序列进行快速排序,直到每个子序列只含有一个记录为止

5. 希尔排序

排序过程

  先取一个正整数d1<n ,把所有相隔d1的记录放一组,组内进行直接插入排序;然后取d2<d1 ,重复上述分组和排序操作;直至di=1 ,即所有记录放进一个组中排序为止。

    

   

6. 堆排序

将无序序列建成一个堆,得到关键字最小(或最大)的记录;输出堆顶的最小(大)值后,使剩余的n-1个元素重又建成一个堆,则可得到n 个元素的次小值;重复执行,得到一个有序序列,这个过程叫堆排序。

建立大头堆:

堆排序过程:

 

7. 实践

实验内容:

                (1) 实现直接插入排序

                (2) 实现冒泡排序

                (3) 实现简单选择排序

                (4) 实现快速排序

                (5) 实现希尔排序

                (6) 实现堆排序

代码展示:

int main()
{
    int a[101],n,m;
    int p[]={9,7,5,3,1};
    while(1)
    {
                        char w;
			n=Readinfo(a);    //读取文件
                        printf("  读取的数据为:\n");
		        output(a,n);
			printMenu();
			printf("  请输入你要选择的操作:");
			scanf("%d",&m);
			switch (m)
			{
				case 1:printf("\n  选择排序:\n");
				       Select_sort(a,n);  
				       break;
				case 2:printf("\n  冒泡排序:\n");
				       Bubll_sort(a,n);    
	                               break;
				case 3:printf("\n  快速排序:\n");
				       quick_sort(a,0,n-1);
				       output(a,n);
				       break;
				case 4:printf("\n  直接插入排序:\n");
				       insert_sort(a,n);
				       break;
				case 5:printf("\n  希尔排序:\n");
				       shell_sort(a,n,p,5);
				       break;
				case 6:printf("\n  堆排序:\n");
				       heop_sort(a,n);
				       break;
				case 0:return 0;     
			}
                        printf("  是否继续操作?'Y'or'N'\n");
			scanf(" %c",&w);
			if('n'==w||'N'==w)
			  break;
    }
    return 0;
}
void printMenu(void)
{
    printf("  *****       1.  选择排序               *****\n");
    printf("  *****       2.  冒泡排序               *****\n");
    printf("  *****       3.  快速排序               *****\n");
    printf("  *****       4.  直接插入排序            *****\n");
    printf("  *****       5.  希尔排序               *****\n");
    printf("  *****       6.  堆排序                 *****\n");
    printf("  *****       0.  退出系统!             *****\n");
}
void Bubll_sort(int a[],int n)  //冒泡排序(改进)
{
	  int i,j,flag=0,temp;  //标志位初始化
	  for(i=0;i<n&&flag==0;i++)
	  {
			        flag=1;//标志位置1
			        for(j=1;j<n-i;j++)
				{

					 if(a[j]>a[j+1])   //前后比较,交换位置
					 {
					 	   temp=a[j];
					 	   a[j]=a[j+1];
					 	   a[j+1]=temp;
					 	   flag=0;      //标志位置0
					 }
				}
				//if(flag==1)
					//break;
	}
	output(a,n);
}
void Select_sort(int a[],int n)  //选择排序
{
	  int i,j,k,temp;
	  for(i=1;i<n;i++)
	  {
			  k=i;              //标记
			  for(j=i+1;j<n;j++)
			  {
				if(a[k]<a[j])
				  k=j;
			  }
			  if(i!=k)           //交换
			  {
			       temp=a[i];
			       a[i]=a[k];
			       a[k]=temp;
			  }
	  }
	  output(a,n);        
}
int Readinfo(int a[])//读取文件
{
	   FILE *fp;
	   int i=1;
	   a[0]=0;
	   if((fp=fopen("number.txt","r"))==NULL)   
	  {
		     printf("打开文件失败!");
		     return 0;
	  }
	  while(fscanf(fp,"%3d",&a[i])!=EOF)    //从a[1]开始写入
		  i++;
	  fclose(fp);       //释放结点
	  return i;         //返回读了i个数
}
void output(int a[],int n)//输出
{
	  int i;
	  for(i=1;i<n;i++)
	  {
			printf("%5d",a[i]);
			if(i%10==0)
				printf("\n");
	  }
}
void quick_sort(int a[],int low,int hight)  //快速排序
{
	  int i=low,j=hight;
	  int temp=a[i];   //第一个元素作为轴
	  if(i<j)  //长度大于1
	  {
			 while(i<j) //从数组的两端交替向中间扫描
			 {
			 	  while(a[j]>temp&&i<j) //从后往前,找比轴小的数
					  j--;                //没找到,继续向前找
				  if(i<j)
				  {
					   a[i]=a[j];  //找到了,比轴记录小的,移到低端
					   i++;        //低端向前移动
				  }
				  while(a[i]<temp&&i<j)//从前往后,找比轴大的数
					  i++;          //没找到,继续向后找
				  if(i<j)
				  {
					   a[j]=a[i];  //找到了,比轴记录大的,移到高端
					   j--;        //高端向前移动
				  }
			  }
			  a[i]=temp;   //把轴移到中间
			  quick_sort(a,low,i-1);   //对低子表递归调用
			  quick_sort(a,i+1,hight); //对高子表递归调用
	  }
}
void insert_sort(int r[],int n)//直接插入排序
{
	 int i,j,x;
	 for(i=2;i<=n;i++)   //从第二个数开始插入,间隔为1,逐一比较
	 {
	 	  if(r[i]<r[i-1])   //如果第i个数比排好序最大的还大,就不用执行下面的程序
		  {
				  x=r[i];        //将第i个数存入辅助空间
				  for(j=i-1;j>0;j--)    //第i个数和前面的数比较
				  {
					 if(x<r[j])       //如果前面的数大
						r[j+1]=r[j];    //前面的排好序的数向后移动
					 else               //否则,跳出
						break;
				  }
				  r[j+1]=x;    //找到位置,插入
			}
	 }
	 output(r,n);    //输出
}
void shell_sort(int r[],int n,int p[],int m)//希尔排序
{
	  int i,j,k,d,x;
	  for(k=1;k<=m;k++)    //从第一个数开始
	  {
			 d=p[k];             //间隔为数组里的数(一般为奇数,质数)
			 for(i=1+d;i<=n;i++)  //从第1个数开始,间隔为d,逐一比较
			 {
			 	  if(r[i]<r[i-d])  //如果第i个数比第i-d个数还大,就不用执行下面的程序
				  {
						 x=r[i];      //将第i个数存入辅助空间
						 for(j=i-d;j>0;j=j-d) //第i个数和前面的第i-d个数比较
						 {
						 	  if(x<r[j])     //如果前面的数大
								r[j+d]=r[j]; //前面的数向后移动
							  else            //否则,跳出
								break;
						 }//for
						 r[j+d]=x;      找到位置,插入
				  } //if
			 } //for
	  }
	  output(r,n);    
}
void shif(int r[],int i,int n)//堆排序
{
	  int t=i,j=2*i;     //t表示开始调整的树根;j表示t的左孩子
	  while(j<=n)         //判断有没有左孩子
	  {
		   if(2*t+1<=n)     //判断有没有右孩子***注意不能为2*i+1///i没有变化
			  if(r[j]<r[j+1])     //比较左右孩子的大小
				  j=j+1;             //指向左右孩子较大的那一个
		   if(r[j]>r[t])        //左右孩子中大的和根节点比较
		   {
			    int temp;              //交换
			    temp=r[j];
			    r[j]=r[t];
			    r[t]=temp;
		   }
		   else
		       break;           //没有交换则跳出循环
		   t=j;               //指向下一个根节点
		   j=2*t;             //根节点的左孩子
		}

}
void heop_sort(int r[],int n)//堆排序
{
	  int i;
	  for(i=n/2;i>=1;i--)
		  shif(r,i,n);     //构建大头堆
		for(i=n;i>1;i--)
		{
			 int temp;         //交换
			 temp=r[1];
			 r[1]=r[i];
			 r[i]=temp;
			 shif(r,1,i-1);//调整大头堆
		}
		output(r,n);      //输出
}

  注:程序中需要一个文件名为number.txt的文本,来读取文本里的100个数据。

 

转载于:https://www.cnblogs.com/huan0919/p/8429041.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值