选择排序和堆排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/IceS2388627880/article/details/60144801
选择排序

基本思想:每一趟在待排序的记录中选出关键字最小的记录,依次存放在已排好序的记录序列的最后,直到全部记录排序完为止。

1.直接选择排序
基本思想:每次从待排序的无序区中选择出关键字值最小的记录,将该记录与该区中的第一个记录交换位置。

/*
直接选择排序
基本思想:每次从待排序的无序区中选择出关键字值最小的记录,将该记录与该区中的第一个记录交换位置。
*/
void SelectSort(RecType R[],int n){
	int i,j,min;
	RecType r;
	for(i=0;i<n-1;i++){//最后一个不用再选择最小的
		min=i;		
		for(j=i+1;j<n;j++){//i后直至n-1为无序区
			if(R[j].key<R[min].key){
				min=j;				
			}
		}

		if(min!=i){
			r=R[i];
			R[i]=R[min];//把最小的赋值给i
			R[min]=r;
		}
	}

}

2.堆排序
基本思想:在排序过程中,将记录数组R[0..n-1]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,
在当前无序区中选择关键字最大(或最小)的记录。
             A|0        
        B|1         C|2
    D|3        E|4
小根堆:k[i]<=K[2*i+1] && k[i]<=K[2*i+2]
大根堆:k[i]>=K[2*i+1] && k[i]>=K[2*i+2]
升序用大根堆,降序用小根堆。

/*
堆排序
基本思想:在排序过程中,将记录数组R[0..n-1]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,
在当前无序区中选择关键字最大(或最小)的记录。
		     A|0		
		B|1		 C|2
	D|3		E|4
小根堆:k[i]<=K[2*i+1] && k[i]<=K[2*i+2]
大根堆:k[i]>=K[2*i+1] && k[i]>=K[2*i+2]
升序用大根堆,降序用小根堆。
*/
void Sift(RecType R[],int i,int h){//i是根堆的堆顶,一定从最大叶子层开始。
	int j;
	RecType x=R[i];
	j=2*i+1;//R[j]是左孩子]
	while(j<=h){//求根结点(i-1)/2
		if(j<h && R[j].key<R[j+1].key)
			j++;//指向大的

		if(x.key>=R[j].key)//父结点大于子结点
			break;

		//父节点小于子结点,交换父结点和子结点
		R[i]=R[j];
		i=j;
		j=2*i+1;
	}
	R[i]=x;

}
void HeapSort(RecType R[],int n){
	//对R[0..n-1]进行堆排序
	int i;
	RecType r;

	//对初始数据建立大根堆
	for(i=(n-1-1)/2;i>=0;i--)
		Sift(R,i,n-1);

	

	for(i=n-1;i>=0;i--){//对R[0..n-1]
		r=R[0];
		R[0]=R[i];
		R[i]=r;
		Sift(R,0,i-1);//0作为存放最大值的索引
	}

}
完整代码:

#if ! defined(SELECTSORT_C)
#define SELECTSORT_C

#include<stdio.h>

#define MAXSIZE 100
typedef int KeyType;//关键字类型用来比较
typedef char InfoType;//其他类型的信息
typedef struct{
	KeyType key;//排序用的关键字
	InfoType other;//其他附属信息
}RecType;//记录类型
typedef RecType SeqList[MAXSIZE+1];//+1用来使[0]作为哨兵,但是在实际使用中往往不能使[0]作为哨兵

/*
选择排序
基本思想:每一趟在待排序的记录中选出关键字最小的记录,依次存放在已排好序的记录序列的最后,直到全部记录排序完为止。
*/
/*
直接选择排序
基本思想:每次从待排序的无序区中选择出关键字值最小的记录,将该记录与该区中的第一个记录交换位置。
*/
void SelectSort(RecType R[],int n){
	int i,j,min;
	RecType r;
	for(i=0;i<n-1;i++){//最后一个不用再选择最小的
		min=i;		
		for(j=i+1;j<n;j++){//i后直至n-1为无序区
			if(R[j].key<R[min].key){
				min=j;				
			}
		}

		if(min!=i){
			r=R[i];
			R[i]=R[min];//把最小的赋值给i
			R[min]=r;
		}
	}

}




void SelectSortTest(){
	RecType SeqList[]={{5,'A'},{4,'B'},{3,'C'},{2,'D'},{1,'E'},{6,'F'},{7,'G'},{5,'H'},{2,'I'},{8,'J'},
						 {9,'K'},{10,'L'},{11,'M'},{12,'N'},{13,'O'},{14,'P'},{1,'Q'},{2,'R'},{3,'S'},{20,'T'}};
	int i,n=10;
	printf("直接选择排序前:\n");
	for(i=0;i<n;i++){
		printf("%2d,%c ",SeqList[i].key,SeqList[i].other);
		if(i%10 == 9) 
			printf("\n");
	}
	printf("\n");
	
	SelectSort(SeqList,n);

	printf("直接选择排序后:\n");	
	for(i=0;i<n;i++){
		printf("%2d,%c ",SeqList[i].key,SeqList[i].other);
		if(i%10 == 9) 
			printf("\n");
	}
	printf("\n");
}
/*
堆排序
基本思想:在排序过程中,将记录数组R[0..n-1]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,
在当前无序区中选择关键字最大(或最小)的记录。
		     A|0		
		B|1		 C|2
	D|3		E|4
小根堆:k[i]<=K[2*i+1] && k[i]<=K[2*i+2]
大根堆:k[i]>=K[2*i+1] && k[i]>=K[2*i+2]
升序用大根堆,降序用小根堆。
*/
void Sift(RecType R[],int i,int h){//i是根堆的堆顶,一定从最大叶子层开始。
	int j;
	RecType x=R[i];
	j=2*i+1;//R[j]是左孩子]
	while(j<=h){//求根结点(i-1)/2
		if(j<h && R[j].key<R[j+1].key)
			j++;//指向大的

		if(x.key>=R[j].key)//父结点大于子结点
			break;

		//父节点小于子结点,交换父结点和子结点
		R[i]=R[j];
		i=j;
		j=2*i+1;
	}
	R[i]=x;

}
void HeapSort(RecType R[],int n){
	//对R[0..n-1]进行堆排序
	int i;
	RecType r;

	//对初始数据建立大根堆
	for(i=(n-1-1)/2;i>=0;i--)
		Sift(R,i,n-1);

	

	for(i=n-1;i>=0;i--){//对R[0..n-1]
		r=R[0];
		R[0]=R[i];
		R[i]=r;
		Sift(R,0,i-1);//0作为存放最大值的索引
	}

}
void HeapSortTest(){
	RecType SeqList[]={{5,'A'},{4,'B'},{3,'C'},{2,'D'},{1,'E'},{6,'F'},{7,'G'},{5,'H'},{2,'I'},{8,'J'},
						 {9,'K'},{10,'L'},{11,'M'},{12,'N'},{13,'O'},{14,'P'},{1,'Q'},{2,'R'},{3,'S'},{20,'T'}};
	int i,n=10;
	printf("堆排序前:\n");
	for(i=0;i<n;i++){
		printf("%2d,%c ",SeqList[i].key,SeqList[i].other);
		if(i%10 == 9) 
			printf("\n");
	}
	printf("\n");
	
	HeapSort(SeqList,n);

	printf("堆排序后:\n");	
	for(i=0;i<n;i++){
		printf("%2d,%c ",SeqList[i].key,SeqList[i].other);
		if(i%10 == 9) 
			printf("\n");
	}
	printf("\n");
}
int main(){
	SelectSortTest();
	printf("\n\n");
	HeapSortTest();
	return 0;
}


#endif

运行结果:

堆排序过程:

                 下标:        0     1       2       3       4       5       6       7       8       9

                 数值:        5     4       3       2       1       6       7       5       2       8

初始建堆:  i=4         5     4       3       2       8       6       7       5       2       1

                   i=3         5     4       3       5       8       6       7       2       2       1

                   i=2         5     4       7       5       8       6       3       2       2       1                2,5,6

                   i=1         5     8       7       5       4       6       3       2       2       1                1,3,4

                   i=0         8     5       7       5       4       6       3       2       2       1                0,1,2

 

坐标从0开始的二叉树,已知子结点求父结点坐标为:parent=(i-1)/2;已知父结点求子结点的坐标为:left=2*i+1,right=2*i+2。

                   i=9

交换:              1     5       7       5       4       6       3       2       2       [8]             

                          7     5      6       5       4       1       3       2       2       1

                   i=8

交换:              2       5       6       5       4       1       3       2       [7      8]              

                          6       5      3       5       4       1       2       2       [7      8]


 

                   i=7

交换:              2       5       3       5       4       1       2       [6      7       8]              

                          5       5       3       2       4       1       2       [6      7       8]




                   i=6

交换:              2       5       3       2       4       1       [5      6       7       8]              

                          5      4       3       2       2       1       [5      6       7       8]

                   i=5

交换:              1       4       3       2       2       [5      5       6       7       8]              

                          4      2       3       1       2       [5      5       6       7       8]


                   i=4

交换:              2       2       3       1       [4      5       5       6       7       8]              

                          3       2      2       1       [4      5       5       6       7       8]


                   i=3

交换:              1       2       2       [3      4       5       5       6       7       8]              

                          1       2       2       [3      4       5       5       6       7       8]


                   i=2

交换:              1       2       [2      3       4       5       5       6       7       8]              

                          1       2       [2      3       4       5       5       6       7       8]

                   i=1

交换:              1       [2      2       3       4       5       5       6       7       8]              

                          1       [2      2       3       4       5       5       6       7       8]

                   i=0

交换:              [1      2       2       3       4       5       5       6       7       8]              

                          [1      2       2       3       4       5       5       6       7       8]



猜你喜欢

转载自blog.csdn.net/IceS2388627880/article/details/60144801
今日推荐