对点云进行堆排序的实例

一剑行天下 posted @ 2009年1月02日 03:57 in 排序 , 2700 阅读

要进行堆排序首先应该了解啥叫堆排序

1、 堆排序定义
n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):
(1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ )

若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键

2.堆排序(HeapSort)是一树形选择排序。
堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系【顺序存储结在当前无序区中选择关键字最大(或最小)的记录。
3、堆排序与直接插入排序的区别
直 接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比 较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行 了这些比较操作。

本文对点云文件venus.asc进行了处理

点云文件venus.asc的内容如下;

20
51.85527 125.8676 113.8507
239.0097 198.0222 63.83692
239.0238 193.8298 63.89684
239.118 196.3538 63.88842
4.554705 199.1733 811.394049
3.584999 199.5536 1011.1685
3.740701 918.7712 1211.61608
3.796498 210.5667 711.51842
3.964703 202.2824 8.68437
3.972898 199.0001 15.57984
4.000503 201.1363 4.34869
4.003095 197.7905 14.73202
4.0096  201.8  5.822891
4.031899 199.5708 4.84632
48.25649 124.4424 40.14629
48.52979 263.8946 96.11548
48.65133 127.9358 35.16135
51.81513 120.5161 111.5341
51.81892 125.9329 36.0517
51.82378 297.4256 45.81934

程序在myheapsort.c文件中  具体内容如下:

#include<stdio.h>
#include<math.h>
//#include<malloc.h>
#include<stdlib.h>
void heapsort(double **data,int i,int length);

main()
{
        int m=0;
        FILE *fp;
        int i=0;
        if((fp=fopen("venus.asc","r"))==NULL)
        {
                printf("no venus.asc file ");
                return;
        }
        fscanf(fp,"%d",&m);
        double **p=(double**)malloc(m*sizeof(double*));
        int j=0;
        for(j=0;j<m;j++)
        {
                p[j] = (double*)malloc(3*sizeof(double));
        }

        double arr[3];
        int n=0;
        while(!feof(fp))
        {
                int ret=fscanf(fp,"%lf %lf %lf",&arr[0],&arr[1],&arr[2]);
                if(ret!=3)
                        break;
                p[n][0]=arr[0];
                p[n][1]=arr[1];
                p[n][2]=arr[2];
                n++;
        }
        fclose(fp);
         for(j=0;j<10;j++)
        {
                printf("%lf %lf %lf\n",p[j][0],p[j][1],p[j][2]);
               
        }

        int node =0;
        for(node=m/2 -1;node>=0;node--)//生成大堆根
        {
                heapsort(p, node, m);
               
               
        }
        for(node=m-1;node>0;node--)
        {
                double tmp0=0,tmp1=0,tmp2=0;
                tmp0=p[node][0];//与最后一个记录交换
                tmp1=p[node][1];
                tmp2=p[node][2];
                p[node][0]=p[0][0];
                p[node][1]=p[0][1];
                p[node][2]=p[0][2];
                p[0][0]=tmp0;
                p[0][1]=tmp1;
                p[0][2]=tmp2;
                heapsort(p, 0, node);  //将H.r[0..i]重新调整为大根堆
                                   
        }
        fp=fopen("venus1.asc","w");
        int k=0;
        double int_arr[3];
        fprintf(fp,"%d\n",m);

        for( i=1;i<=m;i++)
        {
                int_arr[0]=p[i-1][0];
                int_arr[1]=p[i-1][1];
                int_arr[2]=p[i-1][2];
                int ret=fprintf(fp,"%lf %lf %lf\n", int_arr[0],int_arr[1],int_arr[2]);
                //if(ret!=3)
                       // break;
                n++;
        }
        fclose(fp);

}

void heapsort(double **data,int i,int length)
{
        int minnode=0;
        while((2*i+1)<length)
        {
                minnode=2*i+1;
                if((2*i+2)<length)
                { if(data[2*i+1][0]<data[2*i+2][0])//比较左子树和右子树,记录最大值的
                minnode=2*i+2;
                }
                if(data[i][0]<data[minnode][0])
                {
                        double t0=0,t1=0,t2=0;
                        t0=data[i][0];
                        t1=data[i][1];
                        t2=data[i][2];
                        data[i][0]=data[minnode][0];
                         data[i][1]=data[minnode][1];
                         data[i][2]=data[minnode][2];
                        data[minnode][0]=t0;
                        data[minnode][1]=t1;
                        data[minnode][2]=t2;
                        i=minnode;
               
               
                }
                 else
       
         {
            //比较左右孩子均大则堆未破坏,不再需要调整
            break;
         }


        }
        return;

}

编译命令:gcc -o main myheapsort.c -g

生成的新的文件venus.asc   内容如下:

20
3.584999 199.553600 1011.168500
3.740701 918.771200 1211.616080
3.796498 210.566700 711.518420
3.964703 202.282400 8.684370
3.972898 199.000100 15.579840
4.000503 201.136300 4.348690
4.003095 197.790500 14.732020
4.009600 201.800000 5.822891
4.031899 199.570800 4.846320
4.554705 199.173300 811.394049
48.256490 124.442400 40.146290
48.529790 263.894600 96.115480
48.651330 127.935800 35.161350
51.815130 120.516100 111.534100
51.818920 125.932900 36.051700
51.823780 297.425600 45.819340
51.855270 125.867600 113.850700
239.009700 198.022200 63.836920
239.023800 193.829800 63.896840
239.118000 196.353800 63.888420

本文选了简单的几十个点,原因是便于上传与演示 对于很大文件同样很快完成排序。

Avatar_small
hf 说:
2009年1月07日 03:51

很详细!!


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter