Bootstrap

数据结构实验报告:排序

一、实验目的

1. 熟练掌插入类排序、交换类排序的实现

2. 掌握选择类排序、非配类的实现

二、实验环境

windows 10、Visual C++6.0

三、实验内容

1. 编写程序,实现直接插入排序算法

#include <stdio.h>
#include <stdlib.h>
typedef int KeyType;
typedef int OtherType;
typedef struct
{
	KeyType key;
	OtherType other_data;
}RecordType;

void   InsSort(RecordType  r[],  int length)
{ 
	int i,j;
	for (i=2;  i<=length;  i++) 
	{
		r[0]=r[i];     
		j=i-1;	         
		while (r[0].key< r[j].key ) 
		{
			r[j+1]= r[j]; 
			j=j-1;
		}
		r[j+1]=r[0];		         
	}
} /*  InsSort  */ 

void main()
{
	int i,j;
	RecordType r[20];
	int len;
	printf("请输入待排序记录的长度:");
	scanf("%d",&len);
	for(i=1;i<=len;i++)
	{
		printf("请输入第%d个记录元素:",i);
		fflush(stdin);
		scanf("%d",&j);
		r[i].key = j;
	}
	for(i=1;i<=len;i++)
		printf("%d  ",r[i].key);
	printf("\n");

	InsSort(r,len);
	for(i=1;i<=len;i++)
		printf("%d  ",r[i].key);
	printf("\n");

}
//----------------------------------直接插入排序

2. 编写程序,实现快速排序算法

#include <stdio.h>
#include <stdlib.h>

typedef int KeyType;
typedef int OtherType;

typedef struct
{
	KeyType key;
	OtherType other_data;
}RecordType;
int   QKPass(RecordType r[],int left,int right)
{ 
	RecordType x;
	int low,high;
	x= r[left];             /* 选择基准记录*/ 
	low=left;  
	high=right;
	while ( low<high )
	{
		while (low< high && r[high].key>=x.key ) 
			/* high从右到左找小于x.key的记录 */
			high--;
		if ( low <high ) 
		{ 
			r[low]= r[high];
			low++;
		}  
		/* 找到小于x.key的记录,则进行交换*/
		while (low<high && r[low].key<x.key  )    
			low++; 
		if (  low<high  )
		{ 
			r[high]= r[low];
			high--; 
		} /* 找到大于x.key的记录,则交换*/
	}
	r[low]=x;                     /*将基准记录保存到low=high的位置*/
	return low;                     /*返回基准记录的位置*/
} /* QKPass */ 


void QKSort(RecordType r[],int low, int high )
/*对记录数组r[low..high]用快速排序算法进行排序*/
{
	int pos;
	if(low<high)
	{
		pos=QKPass(r, low, high);  /*调用一趟快速排序,将枢轴元素为界划分两个子表*/
		QKSort(r, low, pos-1);     /*对左部子表快速排序*/
		QKSort(r, pos+1, high); /*对右部子表快速排序*/
		
	}
}


void main()
{
	int i,j;
	RecordType r[20];
	int len;
	printf("请输入待排序记录的长度:");
	scanf("%d",&len);
	for(i=1;i<=len;i++)
	{
		printf("请输入第%d个记录元素:",i);
		fflush(stdin);
		scanf("%d",&j);
		r[i].key = j;
	}
	for(i=1;i<=len;i++)
		printf("%d  ",r[i].key);
	printf("\n");
	QKSort(r,1,len);
	for(i=1;i<=len;i++)
		printf("%d  ",r[i].key);
	printf("\n");
	
}
//----------------------------------快速排序

3. 编写程序,实现归并排序算法

#include <stdio.h>
#include <stdlib.h>

typedef int KeyType;
typedef int OtherType;

typedef struct
{
	KeyType key;
	OtherType other_data;
}RecordType;

void Merge(RecordType r1[],  int low,   int mid,   int high,  RecordType  r2[])
/* 已知r1[low..mid]和r1[mid+1..high]分别按关键字有序排列,将它们合并成一个有序序列,存放在r2[low..high] */
{ 
	int i,j,k;
	i=low;
	j=mid+1;
	k=low;
	while ( (i<=mid)&&(j<=high)  )
	{
		if ( r1[i].key<=r1[j].key )
		{
			r2[k]=r1[i];
			++i;
		}
		else 
		{
			r2[k]=r1[j];
			++j;
		}
		++k;
	}
	while( i<=mid )
	{
		r2[k]=r1[i];
		k++;
		i++;
	}
	while( j<=high)
	{
		r2[k]=r1[j];
		k++;
		j++;
	}
} /* Merge */ 
void   MSort(RecordType  r1[],  int  low,  int  high,  RecordType  r3[])
/* r1[low..high]经过排序后放在r3[low..high]中,r2[low..high]为辅助空间 */ 
{
	int mid;
	RecordType  r2[20];
	if ( low==high ) 
		r3[low]=r1[low];
	else
	{
		mid=(low+high)/2;
        MSort(r1,low, mid, r2);
        MSort(r1,mid+1,high, r2);
        Merge (r2,low,mid,high, r3);
}
} /*   MSort  */ 

void   MergeSort ( RecordType  r[],  int  n )
/* 对记录数组r[1..n]做归并排序 */ 
{
	MSort ( r,  1,  n,  r );
}

void main()
{
	int i,j;
	RecordType r[20];
	int len;
	printf("请输入待排序记录的长度:");
	scanf("%d",&len);
	for(i=1;i<=len;i++)
	{
		printf("请输入第%d个记录元素:",i);
		fflush(stdin);
		scanf("%d",&j);
		r[i].key = j;
	}
	for(i=1;i<=len;i++)
		printf("%d  ",r[i].key);
	printf("\n");
	MergeSort(r,len);
	for(i=1;i<=len;i++)
		printf("%d  ",r[i].key);
	printf("\n");
	
}
//----------------------------------归并排序

四、实验结果与分析

  1.  

3e42ef31cb6c4a559760b3a705245d47.png

图1  第1题运行结果图

分析:直接插入排序(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表,同样的O(n^2)时间复杂度,直接插入排序比选择排序和冒泡排序性能要要一些。直接插入排序对数组基本有序和数组元素比较少的时候,速度比较快。

2.

d5fe1ad9ebdf408fb2585becb4247b8d.png

图2  第2题运行结果图

分析:快速排序算法的时间复杂度和各次标准数据元素的值关系很大。如果每次选取的标准元素都能均分两个子数组的长度,这样的快速排序过程是一个完全二叉树结构。(即每个结点都把当前数组分成两个大小相等的数组结点,n个元素数组的根结点的分解次数就构成一棵完全二叉树)。这时分解次数等于完全二叉树的深度log2n;每次快速排序过程无论把数组怎样划分、全部的比较次数都接近于n-1次,所以最好情况下快速排序算法的时间复杂度为O(nlog2n)。

3.

8d3b74faf2ad4f398be0edfd3ec159c9.png

图3  第3题运行结果图

分析:归并排序的过程中,需要对当前区间进行对半划分,直到区间的长度为1。也就是说,每一层的子区间,长度都是上一层的1/2。这也就意味着,当划分到第logn层的时候,子区间的长度就是1了。而归并排序的merge操作,则是从最底层开始(子区间为1的层),对相邻的两个子区间进行合并,过程如下:在logn层(最底层),每个子区间的长度为1,共n个子区间,每相邻两个子区间进行合并,总共合并n/2次。n个数字都会被遍历一次,所有这一层的总时间复杂度为o(n).

 

;