选择排序(简单选择排序和堆排序)

选择排序的基本思想:每一趟(例如第i趟)在后面n-i+1(i=1,2,…n-1)个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到第n-1趟做完,待排序元素只剩下了1个,就不用再选了。

1.简单选择排序
简单排序算法思想:假设排序表为L[1…n],第i趟排序即从L[i…n]中选择关键字最小的元素与L(i)交换,每一趟排序可以确定一个元素的最终位置,这样经过n-1趟排序就可以使得整个排序表有序。代码如下:

#include<cstdio>
#include<iostream>
using namespace std;
void Swap(int *a, int *b);
void SelectSort(int a[], int n);


int main(){
 int n;
 printf("请输入元素的个数:\n"); 
 scanf("%d",&n);
 int a[n];
 printf("请输入数组中的元素:\n");
 for(int i=0; i<n; i++){
 scanf("%d", &a[i]);
 } 
 SelectSort(a, n);
 
 printf("请输出排序好的数组:\n");
 printf("请输出排序好的数组:\n");
 for(int i=0; i<n; i++){
  printf("%d ",a[i]);
 } 
  
  return 0;
}

void Swap(int *a, int *b){
 int temp;
 temp = *b;
 *b = *a;
 *a = temp;
 
}
 SelectSort(int a[], int n){
 for(int i=0; i<n-1; i++){  //n-1趟 
 int min = i;    //记录最小元素的位置 
 for(int j= i+1; j<n; j++)  //在a[i...n]中选择最小的元素 
  {
   if (a[j]< a[min])  min = j;  //更新最小元素的位置 
   if(min != i)      Swap( &a[i],&a[min]);
  }
 }
 
}

编译运行结果如下:
在这里插入图片描述

2.堆排序

堆排序思路:首先将存放在L[1…n]中的n个元素建成初始堆,由于堆本身的特点,堆顶元素就是最大值,输出堆顶元素后,通常将堆底元素送入堆顶,此时根结点已不满足大根堆的性质,堆被破坏,将堆顶元素向下调整使其继续保持大根堆的性质,再输出堆顶元素,如此反复,直到堆中仅剩下一个元素为止。

堆排序是一种树形选择排序方法,特点:在排序过程中,将L[1…n]看成是一棵完全二叉树的顺序结构,利用完全二叉树中双亲结点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或最小)的元素。
堆的定义如下:n个关键字序列L[1…n]称为堆,当且仅当该序列满足:
1.L(i)>=L(2i) 且 L(i)>=L(2i+1) 【大根堆】 2.L(i)<=L(2i) 且 L(i)<=L(2i+1) 【小根堆】

堆排序的关键是构造初始堆,对初始序列建堆,就是一个反复筛选的过程。n个结点的完全二叉树,最后一个结点是第[n/2]个结点的孩子。对第[n/2]个结点为根的子树筛选(对于大根堆:若根结点的关键字小于左右子女中关键字较大者,则交换),使该子树成为堆。之后向前依次对各节点([n/2]-1 ~1)为根的子树进行筛选,看该结点值是否大于其左右子树结点的值,若不是,将左右子结点中较大值与之交换,交换后可能会破坏下一级的堆,于是继续采用上述方法构造下一级的堆,直到以该结点为根的子树构造成堆为止。反复利用上述调整堆的方法建堆,直到根结点。
代码如下:

#include<cstdio>
#include<iostream>
using namespace std;
void HeapSort(int a[], int len);
void BuildMaxHeap(int a[], int len );
void AdjustDown(int a[],int k, int len );

int main(){
 int n;
 int maxn = 110;
 printf("请输入元素的个数:\n"); 
 scanf("%d",&n);
 int a[maxn];
printf("请输入数组中的元素:\n");
 for(int i=1; i<=n; i++){
  scanf("%d", &a[i]);
 } 

HeapSort(a, n);
 
 printf("请输出排序好的数组:\n");
 for(int i=1; i<=n; i++){
  printf("%d ",a[i]);
 }
   return 0;
}
void BuildMaxHeap(int a[], int len){
for(int i = len/2;i>0; i--){
  
  AdjustDown(a, i, len);
 }
}

void AdjustDown(int a[], int k, int len){
 a[0] = a[k];  //a[0]为哨兵 
 for(int i= 2*k; i<=len; i=i*2){
  if(a[i]<a[i+1] &&i<len){
   i++;
  }
  if(a[i] <a[0])  break;
  else{
   a[k] = a[i];
    k = i;   //修改K值,继续向下调整 
  }
   }
 a[k] = a[0];   //被筛选节点最终位置 
}

void HeapSort(int a[], int len){
 BuildMaxHeap(a, len);   //建造初始堆 
 
 for(int i = len; i>1; i--){
  
  swap(a[i], a[1]);  //和堆底元素交换 
  
  AdjustDown(a, 1, i-1);
 } 
 
}

swap()函数链接:swap详解

猜你喜欢

转载自blog.csdn.net/xiaoyong5854/article/details/106298883
今日推荐