堆排序之小根堆

一、堆

     1.概念:它是一种完全二叉树(即前n-1层是满的,最后一层连续缺失右边的结点)

     2.堆的目的:排序

     3.堆的创建:创建一棵完全二叉树

     4.存储方式:链式存储,按层存储

     5.算法:建立结构体,声明结点类型

                    typedef struct node{

                            int data;     //结点的值

                             struct node *left,*right;// 左、右子女

                     }     

        6.先创建根结点,后创建其他结点;

                  采用队列存储数据元素,动态创建一个队列:Q

                  初始化:root为根结点,左右都赋空,让pa指向根结点

                  遍历数据集合,创建新结点 p,看pa的左右域,先挂左子女,后挂右子女;用p实现挂结点

                  创建完,释放队列

                   

  BTNode* CreatDui(int a[],int n){
   	                        //链式存储
	                        BTNode *root,*pa,*p;
	                       BTNode **Q;
	                          int front=0,rear=0;   //首尾结点都置零
	                     root=(BTNode*)malloc(sizeof(BTNode));   //创建根结点
		                 root->data=a[0];
		                 root->left=root->right=NULL;
		                 pa=root;  //指针pa指向root结点
                                 //遍历数据集合
                              for(int i=0;i<n;i++){
                                        //创建新结点
                             	p=(BTNode*)malloc(sizeof(BTNode));
			                      p->data=a[i];
			                      p->left=p->right=NULL; 
                                 //找双亲,判断左右
                                   if(!pa->left)   
                                     pa->left=p;
                                  else(!pa->right){
                                    pa->right=p;
                                    pa=Q[++front];
                                    } 
          			        Q[++rear]=p;     
                                      }

二、小根堆

      即:根节点小于左右结点

          1. 再次借助于队列,队列存的是结点指针,front和rear两个队列指针,初始front=0;rear=0;

               首先使创建好的完全二叉树的所有结点的入队列,结果是:front在第一个叶子上,rear在最后一个结点元素上

                将end放在队列的尾部,即排序后最小的元素上,使队尾标志不丢失:end=rear;

                然后调整堆:比较双亲和子女的大小

小根堆完整代码:

#include<stdlib.h>
#include<stdio.h>
#define N  20
typedef struct node{
	int data;
	struct node *left;
	struct node *right;
}BTNode; 
  //创建完全二叉树 
 BTNode* CreatDui(int a[],int n){
   	//链式存储
	    BTNode *root,*pa,*p,*pm;
	    int end,tag,k,m,t; 
	    BTNode **Q;
	    Q=(BTNode**)malloc(N*sizeof(BTNode*)); 
	    int front=0,rear=0;
	    root=(BTNode*)malloc(sizeof(BTNode));
		root->data=a[0];
		root->left=root->right=NULL;
		pa=root;
		for(int i=1;i<n;i++){
			p=(BTNode*)malloc(sizeof(BTNode));
			p->data=a[i];
			p->left=p->right=NULL; 
				if(!pa->left)//找双亲,判断左右 	
				  pa->left=p;
				else{
	               pa->right=p;
	               pa=Q[++front];
	        }
	        Q[++rear]=p;
		}
		return root;
		free(Q);
	}

 //堆排序  
 void duiSort(BTNode *root){
 	BTNode **Q,*p,*pm;
	int front=0,rear=0,t,tag,end,k,m;
	Q=(BTNode**)malloc(N*sizeof(BTNode*));
	Q[++rear]=root;   //根节点先入队列 
	while(1)
	{
		p=Q[++front];    // 父节点入队列 
		if(p->left)
		{
			Q[++rear]=p->left;    //当父节点有左孩子时,左孩子入队列 
		}
		if(p->right)
		{
			Q[++rear]=p->right;   //当父节点有右孩子时,右孩子入队列  
		}
		if(!p->left&&!p->right)                      //当父节点无左右子女时,二叉树存入队列结束,跳出循环 
		break;
	}
	//结果:front指第一个叶子,rear在最后一个元素/叶子上 
          end=rear;
	//调整堆
  	while(front>1){
       	while(1){
		     tag=1;
        	for(k=front-1;k>0;k--){
       	 	        p=Q[k];
       	         	pm=p;
       	    	if(p->data>p->left->data)
       		        pm=p->left;
       	    	if(p->right&&p->right->data<pm->data)
       		        pm=p->right;
       	        if(p-pm){
       	         	t=pm->data;
					pm->data=p->data;
					p->data=t;
					tag=0;
			   }
		   }
		   if(tag)
		    break;
	   }  
	 //交换 
	    m=root->data;
	    root->data=Q[rear]->data;
	    Q[rear]->data=m;
	    rear--; 
	     //去叶子 
	    if(Q[front-1]->right)
	      Q[front-1]->right=NULL; 
	    else{
	   	  Q[front-1]->left=NULL; 
	       front--;
	      }
   }
	    //输出 
    for( ;end>0;end--)
	printf("%d ",Q[end]->data);
   }  
     
int main(void){
	int a[12]={3,2,12,7,11,8,6,1,9,13,4,5};
	BTNode* Root;
      Root=CreatDui(a,12);
	 printf("\n输出最小根堆\n");
	 duiSort(Root);
}

猜你喜欢

转载自blog.csdn.net/mm_3_by/article/details/81226125
今日推荐