您的位置:首页 > 其它

选择排序和堆排序

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

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

<
b62e
p> 
坐标从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]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: