堆排序 之 c 和 c++函数模板(初谈模板类)

来源:互联网 发布:淘宝网画眉鸟笼笼衣 编辑:程序博客网 时间:2024/05/16 07:52


#include <iostream>using namespace std;const int maxn = 100;void my_swap(int &a, int &b){    int tmp;    tmp = a;    a = b;    b = tmp;}void heap_sort(int arr[],const int &len);void heap_adjust(int arr[],int i,const int &len);int main(){    int i,len;// 数组的有效长度    int arr[maxn],tmp;    len = 0;    cout << "请输入一个序列(-1结束):" << endl;    while(cin >> tmp)    {        if(tmp == -1)            break;        arr[len] = tmp;        len++;    }    heap_sort(arr,len);//条用堆排序    //    cout << "堆排序之后的结果:" << endl;    for(i=0; i<len; i++)        cout << arr[i] << " ";// 多一个空格    cout << endl;    return 0;}void heap_sort(int arr[],const int &len){    int i;    for(i=len/2-1; i>=0; --i)// 至于为什么是从i = len/2 -1开始,自己建立一个完全二叉树的数组即可发现规律。    {        heap_adjust(arr,i,len);    }// 建立一个初试堆    //以0 和 len-1为下标的元素交换,之后从0下标开始调整堆,直到剩下一个元素    for(i=len-1; i>0; --i)    {        my_swap(arr[0],arr[i]);        heap_adjust(arr,0,i);// i 代表当前的数组长度    }}void heap_adjust(int arr[],int i,const int &len){    int lc;// 左孩子    for(; i*2+1<len; i=lc)    {        lc = i*2+1;// 从左孩子开始        if(lc+1<len && arr[lc+1]>arr[lc])//如果右侧孩子大,加一            lc++;        if(arr[lc]>arr[i])//较大的孩子节点大于父节点            my_swap(arr[lc],arr[i]);        else            break;//父节点是最大的无需向下调整    }}


/*
    学习心得:
  1 参数 const int &len 在子函数体内不可改变的量;
    参数int &a,在子函数中是可以改变的,而且改变的正是主函数中的数值
  2 堆排序的定义:若将此序列所存储的向量arr[1..n]看做是一棵完全二叉树
    的存储结构,则堆实质上是满足如下性质的完全二叉树:
    中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)
    结点的关键字。
  3 堆排序其实也是一种选择排序,是一种树形选择排序;
    因此其最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序。
*/

#include <iostream>using namespace std;const int maxn = 100;typedef double TT;template<typename T>void my_swap(T &a, T &b){    T tmp;    tmp = a;    a = b;    b = tmp;}template<typename T>void heap_sort(T arr[],const int &len);template<typename T>void heap_adjust(T arr[],int i,const int &len);int main(){    int i,len;// 数组的有效长度    TT arr[maxn],tmp;    len = 0;    cout << "请输入一个序列(0结束):" << endl;    while(cin >> tmp)    {        if(tmp == '0' || tmp == 0)// 回车是10            break;        arr[len] = tmp;        len++;    }    heap_sort(arr,len);//条用堆排序    //    cout << "堆排序之后的结果:" << endl;    for(i=0; i<len; i++)        cout << arr[i] << " ";// 多一个空格    cout << endl;    return 0;}template<typename T>void heap_sort(T arr[],const int &len){    int i;    for(i=len/2-1; i>=0; --i)// 至于为什么是从i = len/2 -1开始,自己建立一个完全二叉树的数组即可发现规律。    {        heap_adjust(arr,i,len);    }// 建立一个初试堆    //以0 和 len-1为下标的元素交换,之后从0下标开始调整堆,直到剩下一个元素    for(i=len-1; i>0; --i)    {        my_swap(arr[0],arr[i]);        heap_adjust(arr,0,i);// i 代表当前的数组长度    }}template<typename T>void heap_adjust(T arr[],int i,const int &len){    int lc;// 左孩子    for(; i*2+1<len; i=lc)    {        lc = i*2+1;// 从左孩子开始        if(lc+1<len && arr[lc+1]>arr[lc])//如果右侧孩子大,加一            lc++;        if(arr[lc]>arr[i])//较大的孩子节点大于父节点            my_swap(arr[lc],arr[i]);        else            break;//父节点是最大的无需向下调整    }}




/*
  学习心得:
  1 模板类型参数由关键字class或typename后加一个标识符构成。
  在函数的模板参数表中,这两个关键字的意义相同。它们表示后面的
  参数名代表一个潜在的内置或用户定义的类型。
  2 函数模板的实例化是通过实参来决定的,如果没有参数,必须采用其他方法,
  使得编译器能够确认采取哪一个函数(通常是显示模板实参)
  3 函数模板的格式如下:
  template<参数说明>
  函数头
  函数体
  4 当然,貌似main函数里面不能够建立模板,本例可以通过用户选择,来实现
  char long int double等数值型类型的排序,这是由于排序中用到的是 > 造成的。
*/
0 0
原创粉丝点击