创建动态数组以及sort函数的用法 -- 字符串的漂亮度

题目:

给出一个名字,该名字有26个字符串组成,定义这个字符串的“漂亮度”是其所有字母“漂亮度”的总和。每个字母都有一个“漂亮度”,范围在1到26之间。没有任何两个字母拥有相同的“漂亮度”。字母忽略大小写。
给出多个名字,计算每个名字最大可能的“漂亮度”。


输入:整数N,后续N个名字
           N个字符串,每个表示一个名字

输出:每个名称可能的最大漂亮程度

样例:2 

          zhangsan lisi
          192          101


/********************************************************
解题思路:这个题目题意有点难懂,但是读懂了,就会比较简单。“漂亮度”,
即给每个字母从26-1中赋值。要求最大的“漂亮度”,则先统计出现字母的类型以及其个数,
然后给个数大的字母赋予大的值26,然后递减到25,24....例如:“zhangsan”中,a出现2次,n出现2次,
z,h,g,s各出现1次,则给a、n从26、25中取值,给z、h、g、s从24、23、22、21中取值,
即可实现取最大“漂亮度”。
********************************************************/
#include<iostream>
#include<string>
#include<cctype>
#include<algorithm>
using namespace std;

bool cmpare(int a, int b)
{
    return a>b;//降序排列 
}

//返回一个字符串的漂亮度 
int BeautyDegree(const string &str)
{   
    int i;
    int a[26]={0};
    int score = 0,pos;
    for( i=0;i<str.size();i++)
    {
        if(isupper(str[i]))//判断大写 
            pos=str[i]-65;//A的是65 
        else
            pos=str[i]-97;//a是97 
        a[pos]++;
    }
    sort(a,a+26,cmpare);
    for(int i=0;a[i]!=0;i++)
    {
        score += (26-i)*a[i];//每个分数只能用一次,26-25-24... 
    }
    return score;
}
int main()
{   
    int n,i;
    string str;
    //cout<<"Please enter the number \"N\" and the strings\n";
    cin>>n;
    int *score=new int[n];//运行时确定数组的长度,不是事确定的a[20] 
    for( i=0;i<n;i++)
    {
        cin>>str;
        score[i]=BeautyDegree(str);
    }
    for(i=0;i<n;i++)
        cout<<score[i]<<endl;
    delete []score;//与数组变量不同,动态分配的数组将一直存在,知道程序显示释放它为止 
    return 0;//不人为释放,有可能造成内存泄露 
}


创建动态数组

1)常规数组的问题:

数组类型的变量有三个重要的限制:数组的长度固定不变,在编译时必须知道其长度,数组只能在定义它的语句块内存在。

而实际的程序往往需要在运行时动态的分配数组。虽然数组的长度是固定的,但动态分配的数组不必再编译时知道其长度,可以是运行时才确定其长度。不同的是动态分配的数组将一直存在,直到程序显式释放它为止。


2)动态数组的定义:

int * psa = new int[10];</span>
此new表达式分配了一个含有10个int类型的数组,并且返回指向这个数组第一个元素的指针。

数组变量通过指定类型、数组名和维数来定义,而动态分配数组时,只需指定类型和维数(维数可以是任何复杂的表达式),不必为数组命名(在自由存储区创建的数组是没有名字的,只能通过指针(地址)间接地访问堆中的对象)。


3)初始化动态分配的数组

动态分配数组时,如果数组元素具有类(class)类型,将使用该类的默认构造函数实现初始化;如果数组元素是内置类型,则无需初始化。

string *psb = new string[10];
int * psa = new int[10];</span>

第一个数组时string类型,分配了保存对象的内存空间后,将调用string类型的默认构造函数依次初始化数组的每一个元素。

第二个是内置类型,分配了10个int类型的内存空间,但这些元素没有初始化。也可以在后面加个括号来初始化。

#include<iostream>
#include<string>
int main()
{
   using namespace std;
   int * psa = new int[10]();
   for(i=0;i<10;i++)
      cout<<psa[i]<<endl; 
   delete []psa;
   return 0;//不人为释放,有可能造成内存泄露 
}</span>

 
 

4)const对象的数组

如果是const对象的数组,则必须初始化。

const string *psb = new const string[10];//ok
const int * psa = new const int[10];//not ok
const int * psa = new const int[10]();// ok</span>



sort函数的用法


************************************************************************************************************************************

对sort函数圈定边界的地方还是有点疑惑的。特地上  http://www.cplusplus.com/  查了一下它的用法。


1)查看网站  http://www.cplusplus.com/reference/algorithm/sort/


function template
<algorithm>

std::sort

default (1)
template <class RandomAccessIterator>
  void sort (RandomAccessIterator first, RandomAccessIterator last);
custom (2)
template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
Sort elements in range
Sorts the elements in the range  [first,last) into ascending order.

The elements are compared using  operator< for the first version, and  comp for the second.

Equivalent elements are not guaranteed to keep their original relative order (see  stable_sort).


Parameters

first, last
Random-access iterators to the initial and final positions of the sequence to be sorted. The range used is [first,last), which contains all the elements between  first and  last, including the element pointed by  first but not the element pointed by  last.
RandomAccessIterator shall point to a type for which  swap is properly defined and which is both  move-constructibleand  move-assignable.
comp
Binary function that accepts two elements in the range as arguments, and returns a value convertible to  bool. The value returned indicates whether the element passed as first argument is considered to go before the second in the specific  strict weak ordering it defines.
The function shall not modify any of its arguments.
This can either be a function pointer or a function object.

Return value

none


// sort algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::sort
#include <vector>       // std::vector

bool myfunction (int i,int j) { return (i<j); }

struct myclass {
  bool operator() (int i,int j) { return (i<j);}
} myobject;

int main () {
  int myints[] = {32,71,12,45,26,80,53,33};
  std::vector<int> myvector (myints, myints+8);               // 32 71 12 45 26 80 53 33

  // using default comparison (operator <):
  std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33

  // using function as comp
  std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)

  // using object as comp
  std::sort (myvector.begin(), myvector.end(), myobject);     //(12 26 32 33 45 53 71 80)

  // print out content:
  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}


Output:

myvector contains: 12 26 32 33 45 53 71 80

Complexity

On average, linearithmic in the  distance between  first and  last: Performs approximately  N*log2(N) (where  N is this distance) comparisons of elements, and up to that many element swaps (or moves).

Data races

The objects in the range  [first,last) are modified.

Exceptions

Throws if any of the element comparisons, the element swaps (or moves) or the operations on iterators throws.
Note that invalid arguments cause  undefined behavior.


********************************************************************************

2)另外一个版本也可参考一下,但是感觉没上面那个英文版的严谨详细。


sort函数

http://bbs.csdn.net/topics/330010101

想起来自己天天排序排序,冒泡啊,二分查找啊,结果在STL中就自带了排序函数sort,qsort,总算把自己解脱了~
所以自己总结了一下,首先看sort函数见下表:

    函数名  功能描述 
sort  对给定区间所有元素进行排序 
stable_sort  对给定区间所有元素进行稳定排序 
partial_sort  对给定区间所有元素部分排序 
partial_sort_copy  对给定区间复制并排序 
nth_element  找出给定区间的某个位置对应的元素 
is_sorted  判断一个区间是否已经排好序 
partition  使得符合某个条件的元素放在前面 
stable_partition  相对稳定的使得符合某个条件的元素放在前面 

要使用此函数只需用#include <algorithm> sort即可使用,语法描述为:
sort(begin,end),表示一个范围,例如:
int _tmain(int argc, _TCHAR* argv[])
{
 int a[20]={2,4,1,23,5,76,0,43,24,65},i;
 for(i=0;i<20;i++)
  cout<<a[i]<<endl;
 sort(a,a+20);
 for(i=0;i<20;i++)
 cout<<a[i]<<endl;
 return 0;
}
输出结果将是把数组a按升序排序,说到这里可能就有人会问怎么样用它降序排列呢?这就是下一个讨论的内容.
一种是自己编写一个比较函数来实现,接着调用三个参数的sort:sort(begin,end,compare)就成了。对于list容器,这个方法也适用,把compare作为sort的参数就可以了,即:sort(compare).

1)自己编写compare函数:
bool compare(int a,int b)
{
      return a<b;   //升序排列,如果改为return a>b,则为降序
}
int _tmain(int argc, _TCHAR* argv[])
{
     int a[20]={2,4,1,23,5,76,0,43,24,65},i;
     for(i=0;i<20;i++)
       cout<<a[i]<<endl;
     sort(a,a+20,compare);
     for(i=0;i<20;i++)
       cout<<a[i]<<endl;
     return 0;
}

2)更进一步,让这种操作更加能适应变化。也就是说,能给比较函数一个参数,用来指示是按升序还是按降序排,这回轮到函数对象出场了。
为了描述方便,我先定义一个枚举类型EnumComp用来表示升序和降序。很简单:
enum Enumcomp{ASC,DESC};
然后开始用一个类来描述这个函数对象。它会根据它的参数来决定是采用“<”还是“>”。

class compare
{
      private:
            Enumcomp comp;
      public:
            compare(Enumcomp c):comp(c) {};
      bool operator () (int num1,int num2)
         {
            switch(comp)
              {
                 case ASC:
                        return num1<num2;
                 case DESC:
                        return num1>num2;
              }
          }
};

接下来使用 sort(begin,end,compare(ASC)实现升序,sort(begin,end,compare(DESC)实现降序。
主函数为:
int main()
{
     int a[20]={2,4,1,23,5,76,0,43,24,65},i;
     for(i=0;i<20;i++)
         cout<<a[i]<<endl;
     sort(a,a+20,compare(DESC));
     for(i=0;i<20;i++)
         cout<<a[i]<<endl;
     return 0;
}
3)其实对于这么简单的任务(类型支持“<”、“>”等比较运算符),完全没必要自己写一个类出来。标准库里已经有现成的了,就在functional里,include进来就行了。functional提供了一堆基于模板的比较函数对象。它们是(看名字就知道意思了):equal_to<Type>、not_equal_to<Type>、greater<Type>、greater_equal<Type>、less<Type>、less_equal<Type>。对于这个问题来说,greater和less就足够了,直接拿过来用:

升序:sort(begin,end,less<data-type>());
降序:sort(begin,end,greater<data-type>()).
int _tmain(int argc, _TCHAR* argv[])
{
      int a[20]={2,4,1,23,5,76,0,43,24,65},i;
      for(i=0;i<20;i++)
          cout<<a[i]<<endl;
      sort(a,a+20,greater<int>());
      for(i=0;i<20;i++)
          cout<<a[i]<<endl;
      return 0;
}
4)既然有迭代器,如果是string 就可以使用反向迭代器来完成逆序排列,程序如下:
int main()
{
     string str("cvicses");
     string s(str.rbegin(),str.rend());
     cout << s <<endl;
     return 0;
}
qsort():
原型:
_CRTIMP void __cdecl qsort (void*, size_t, size_t,int (*)(const void*, const void*));
解释:    qsort ( 数组名 ,元素个数,元素占用的空间(sizeof),比较函数)
比较函数是一个自己写的函数  遵循 int com(const void *a,const void *b) 的格式。
当a b关系为 >  <  = 时,分别返回正值 负值 零 (或者相反)。
使用a b 时要强制转换类型,从void * 转换回应有的类型后,进行操作。
数组下标从零开始,个数为N, 下标0-(n-1)。
实例:
int compare(const void *a,const void *b)
{
     return *(int*)b-*(int*)a;  
}
int main()
{
     int a[20]={2,4,1,23,5,76,0,43,24,65},i;
     for(i=0;i<20;i++)
        cout<<a[i]<<endl;
     qsort((void *)a,20,sizeof(int),compare);
     for(i=0;i<20;i++)
        cout<<a[i]<<endl;
     return 0;
}
相关:
1)why你必须给予元素个数?
因为阵列不知道它自己有多少个元素
2)why你必须给予大小?
因为 qsort 不知道它要排序的单位.
3)why你必须写那个丑陋的、用来比较俩数值的函式?
因为 qsort 需要一个指标指向某个函式,因为它不知道它所要排序的元素型别.
4)why qsort 所使用的比较函式接受的是 const void* 引数而不是 char* 引数?
因为 qsort 可以对非字串的数值排序.
当然对于排序函数还有其他的用法,今天就只说这些,我也正在学习中,上述只是发表了一点自己的拙见,最后声明上诉实例是基于VC++2008。



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值