heapsort

/*
 * szlHeapSort.h
 */
#ifndef SZL_HEAP_SORT_H
#define SZL_HEAP_SORT_H

void heapSort(int a[], int n);
void siftDown(int a[], int root, int n);

#endif

/*
 * szlSwap.h
 */
#ifndef SZL_SWAP_H
#define SZL_SWAP_H

//交换两个数
void swap(int *a, int *b);

#endif
/* szlHeapSort.c
 * 堆是其节点值满足一定约束的完全二叉树;
 * 数组实现的n个节点的完全二叉树满足的性质,如果
 * 1.用A[0..n-1]表示这棵树,那么
 * (1)位置i的父节点为(i-1)/2;
 * (2)位置i的孩子节点为2*i+1及2*i+2;
 * (3)第一个叶子节点是n/2;
 * 2.用A[1..n]表示这棵树,那么
 * (1)位置i的父节点为i/2;
 * (2)位置i的孩子节点为2*i及2*i+1;
 * (3)第一个叶子节点是n/2+1;
 */
#include "szlHeapSort.h"
#include "szlSwap.h"
#include "stdio.h"

/*
 * 将具有n个元素的数组a进行堆排序
 */
void heapSort(int a[], int n){
  int i;
  /*
   * 以数组a为输入,建立一个堆
   */
  for(i=(n/2)-1; i>=0; i--){ // 从最后一个内部节点降序地访问到树根节点
    siftDown(a,i,n); // 将每一个节点下沉,建立以位置i为根节点的子堆,sub heap
  }
  
  /*
   * 将树根节点和最后一个叶子节点交换;
   * 并将堆的大小减少1;
   * 然后调整树根,以保持堆序;
   * 循环,直至访问到第2个元素
   */
  for(i=n-1; i>=1; i--){
    swap(&a[0],&a[i]);
    siftDown(a,0,i);
  }
}

/*
 * 将root位置的节点在大小为n的堆a中调整,以保持堆序
 */
void siftDown(int a[], int root, int n){
  int done, maxChild;

  done = 0;
  while(!done){
    
	if(root*2+2<=n-1){ //如果root存在左孩子和右孩子
	  if(a[root*2+1]>a[root*2+2]){ //max记住较大的孩子
        maxChild=root*2+1;
	  }
	  else{
	    maxChild=root*2+2;
	  } 
	}
	else if(root*2+1==n-1){ // 如果root有左孩子
	  maxChild=root*2+1;
	}
	else{ //没有孩子节点
	  maxChild = root; // 标记root为最大的元素
	}
	
	if(a[root] < a[maxChild] ){ // 将最大的元素和root位置的元素交换
      swap(&a[maxChild],&a[root]);
	  root=maxChild; //以较大的孩子为根节点继续往下访问
    }
	else{
	  done=1;
	}
  }	
}


 

/*
 * szlSwap.c
 */
#include "szlSwap.h"

void swap(int *a, int *b){
	int t=*a;
	*a=*b;
	*b=t;
}


 更为简洁的版本:

/*
 * heapsort.c
 */
#include <stdio.h>
#define N 30

void swap (int * p, int * q){
    if (! (p == q)){
        * p ^= * q;
        * q ^= * p;
        * p ^= * q;
    }
}

void sift_down (int a[], int i, int n){
    int max = i;
    if ( 2*i+2 <= n-1){
        max = a[2*i+1] > a[2*i+2] ? (2*i+1) : (2*i+2);
    }
    else if (2*i+1 == n-1){
        max = 2*i+1;
    }
    if (a[max] > a[i]){
        swap (&a[i], &a[max]);
        sift_down (a, max, n); /* recursion */
    }
}

void build_heap (int a[], int n){
    int i;
    for (i=(n-1)/2; i>=0; i--){
        sift_down (a, i, n);
    }
}

void heapsort (int a[], int n){
    int i;
    build_heap (a, n);
    for (i=n-1; i>0; i--){
        swap (&a[0], &a[i]);
        sift_down (a, 0, i);
    }
}

int main (int argc, char ** argv){
    int n;
    int i;
    int a[N];
#ifdef DEBUG1
    freopen ("in.txt", "r", stdin);
#endif
    scanf ("%d", &n);
    for (i=0; i<n; i++)
        scanf ("%d", &a[i]);

    heapsort (a, n);

    for (i=0; i<n; i++)
        printf ("%d ", a[i]);
    
#ifdef DEBUG1
    fclose (stdin);
#endif
    return 0;
}





 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验十二 排序技术实验 1. 实验目的 1. 掌握各种排序算法的基本思想; 掌握各种排序算法的实现方法; 掌握各种排序算法的时间性能及其花费时间的计算。 掌握各种排序算法所适应的不同场合。 2. 实验内容 1、随机函数产生10000个随机数,用直接插入、希尔、冒泡、直接选择等排序方法 排序,并统计每一种排序所花费的时间。 2、随机函数产生30000个随机数,用快速、堆、归并等排序方法排序,并统计每一种 排序所花费的时间。 3. 设计与编码 #include <iostream> #include <stdlib.h> #include <time.h> using namespace std; void ShuChu(int r[],int n) { cout<<"输出:"; for(int i=0;i<n;i++) cout<<r[i]<<"\t"; cout<<endl; cout<<"*****************************************"<<endl; } void InsertSort(int r[],int n) //插入排序 { int a=r[0]; for(int i=2;i<n;i++) { r[0]=r[i]; for(int j=i-1;r[0]<r[j];j--) r[j+1]=r[j]; r[j+1]=r[0]; } r[0]=a; } void ShellSort(int r[],int n) //希尔排序 { int a=r[0]; for(int d=n/2;d>=1;d=d/2) { for(int i=d+1;i<=n-1;i++) { r[0]=r[i]; for(int j=i-d;j>0 && r[0]<r[j];j=j-d) r[j+d]=r[j]; r[j+d]=r[0]; } } r[0]=a; } void BubbleSort(int r[],int n) //冒泡排序 { int exchange=n-1; while(exchange!=0) { int bound=exchange;exchange=0; for(int j=1;j<bound;j++) if(r[j]>r[j+1]) { int s=r[j+1]; r[j+1]=r[j]; r[j]=s; exchange=j; } } } void SelectSort(int r[],int n) //选择排序 { for(int i=0;i<n-1;i++) { int index=i; for(int j=i+1;j<=n-1;j++) if(r[j]<r[index]) index=j; if(index!=i) { int a=r[index]; r[index]=r[i]; r[i]=a; } } ShuChu(r,n); } int Partition(int r[],int first,int end) //快速排序一次划分算法 { int i=first; int j=end; r[0]=r[i]; int p=r[i]; while(i<j) { while(i<j&&r[i]<=r[j])j--; if(i<j) { int a=r[j]; r[j]=r[i]; r[i]=a; i++; } while(i<j&&r[i]<=r[j])i++; if(i<j) { int b=r[j]; r[j]=r[i]; r[i]=b; j--; } } return i; } void QuickSort(int r[],int first,int end) //快速排序算法 { int a=r[0]; if(first<end) { int pivot=Partition(r,first,end); QuickSort(r,first,pivot-1); QuickSort(r,pivot+1,end); } r[0]=a; } void Sift(int r[],int k,int m) //筛选法调整堆的算法 { int i=k; int j=2*i; while(j<=m) { if(j<m&&r[j]<r[j+1])j++; if(r[i]>=r[j])break; else { int a=r[j]; r[j]=r[i]; r[i]=a; i=j; j=2*i; } } } void HeapSort(int r[],int n) //堆排序算法 { for(int i=n/2;i>=1;i--) Sift(r,i,n-1); for(i=2;i<n-1;i++) { int a=r[n-i+1]; r[n-i+1]=r[1]; r[1]=a; Sift(r,1

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值