写一段程序,找出数组中第k大小的数,输出数所在的位置。

写一段程序,找出数组中第k大小的数,输出数所在的位置。例如{2,4,3,4,7}中,第一大的数是7,位置在4。第二大、第三大的数都是4,位置在1、3随便输出哪一个均可。函数接口为:int   find_orderk(const int * narry,  const int n,  const int k)    
要求算法复杂度不能是O(n^2)  

参考答案:

1

#include   <stdio.h>
#include   <stdlib.h>
#include   <time.h>
/***************************************
  输入:   n:数组元素的个数   k:第几大的数
              a:待查找的数组元素
  ****************************************/
#define   N   100
void Rand_select(int*, int, int);
int partition(int*, int, int);
int swap(int&, int&);
int k, ans;
int main()
{
 int n, a[N], i;
 while (scanf("%d%d", &n, &k) != EOF)
 {
  srand(time(NULL));
  k--;
  for (i = 0; i < n; i++)
   scanf("%d", a + i);
  Rand_select(a, 0, n - 1);
  printf("%d/n", ans);
 }
 return 0;
}

void Rand_select(int a[], int p, int q)
{
 int m;
 if (p <= q)
 {
  m = partition(a, p, q);
  if (k == m)
  {
   ans = a[m];
   return;
  }
  else if (k > m)
   Rand_select(a, m + 1, q);
  else
   Rand_select(a, p, m - 1);
 }
}

int partition(int a[], int p, int q)
{
 int last, i;
 if (q != p)
  swap(a[rand() % (q - p) + p], a[p]);
 for (i = p + 1, last = p; i <= q; i++)
  if (a[i] >= a[p])
   swap(a[i], a[++last]);
 swap(a[last], a[p]);
 return last;
}

int swap(int &p, int &q)
{
 int temp = p;
 p = q;
 q = temp;
 return 0;
}

2可以先用快速排序进行排序,其中用另外一个进行地址查找 代码如下,在VC++6.0运行通过。   
  //快速排序  

  #include <iostream>      
  using namespace std;  
   
  int Partition (int *L,int low,int   high)  
  {  
  int temp = L[low];  
  int pt =  L[low];  
   
  while (low  <  high)  
  {  
  while (low < high && L[high] >= pt)  
      --high;  
  L[low]  =  L[high];  
  while (low < high && L[low] <= pt)  
      ++low;  
  L[low]  =  temp;  
  }  
  L[low]   =   temp; 
  return low;  
  }  
   
  void QSort (int *L,int low, int high)  
  {  
  if  (low < high)  
  {  
  int pl = Partition (L,low,high);      
  QSort (L, low, pl - 1);  
  QSort (L, pl + 1, high);  
  }  
  }  
   
  int main ()  
  {  
  int narry[100],addr[100];  
  int sum = 1, t;
   
  cout << "Input  number:" <<  endl;  
  cin >> t;  
   
  while   (t != -1)  
  {  
  narry[sum]  =  t;  
  addr[sum - 1]  =  t;  
  sum++;      
  cin >> t;  
  }  
   
  sum -= 1;  
  QSort (narry,1,sum);  
   
  for  (int   i = 1; i <= sum; i++)  
  cout  <<  narry[i]  <<   '/t';  
  cout   <<   endl;  
   
  int k;  
  cout  <<  "Please   input   place   you   want:"   <<   endl;  
  cin  >>  k;  
  int aa = 1;  
  int kk = 0;  
  for  (;;)  
  {  
  if  (aa == k)  
  break;  
  if  (narry[kk]  !=  narry[kk + 1])  
  {  
  aa  +=  1;  
  kk++;  
  }  

  }  

  cout   <<   "The   NO."   <<   k   <<   "number   is:" << narry[sum - kk] << endl;  
  cout   <<   "And   it's   place   is:"   ;  
  for   (i = 0;i  < sum;i++)  
  {  
  if  (addr[i] == narry[sum - kk])  
  cout   <<   i   <<   '/t';  
  }      
  return 0;  

  }

难得啊,居然在今天看到这个题。我去年笔试baidu的时候也作过,当时写的是这个答案,高手分析下:  
  #include   <math.h>  
  #include   <time.h>  
  #include   <string>  
  #include   <iostream>  
  #include   <vector>  
  using namespace std;     
  #define   n   10  
  #define   k   5     
  int main(int argc, char *argv[])  
  {  
  srand( (unsigned )time(NULL) );  
  if ( k > n )  
  {  
  cout << "error!"<< endl;  
  return  1;  
  }  
  vector<int>  src;  
  cout << "源" << n << "个数据如下:
" << endl;  
  for   ( int i = 0; i < n; i++ )  
  {  
  src.push_back( rand() );  
  cout << src[i] << "   ";  
  }  
  vector<int>  maxNum; //顺序存入最大k个数,第一个为最大的,最后一个为第k大
 
  for ( i =0; i < k; i++ )  
  {  
  maxNum.push_back(-999999); //初始化maxNum,k个
-9999999  
  }  
  for ( i = 0; i < n; i++ )  
  {  
     for ( int j = 0; j < maxNum.size(); j++ )  
     {  
       if  ( src[i] >= maxNum[j]) //比当前的大,则放入当前位置,后面的数字依次后退
 
       {  
         for  ( int i1  =  maxNum.size()-1;  i1 > j; i1-- )  
       {  
          maxNum[i1] = maxNum[i1-1];  
       }  
       maxNum[j] = src[i];  
       break;  
     }  
    }  
  }  

cout << endl << “第” << k << “大的数字为:” << maxNum[k-1] << endl;
 return  0;  
  }  
  分析:算法对n个数字只访问一次,此部分的时间复杂度为O(n);但每访问一次,须与k个数字分别比较,所以总的时间渐复杂度为O(n*k)

思想:1.consider   if(k>n)   exit(0)  
        2.if  number  n  is  a big one, use pile/stack sort  
      3.if  number  n is a small one ,use quick sort;  
      4;find your k number and print in the screen;      
  find_orderk(const   int*   narry,const   int   n,const   int   k)    
  {  
  if(n>k)   exit   (0);  
  sort(*narry);  
  for(i=0;i<n;i++)  
    if(i=k)  return  narry[k];  /*the number of  the  k  is  similiar  to  point*/  
  }

===================================================================   函数功能:返回一个第K小的元素(采用快排思想)  
  参数:(T a[]目标数组 || int l左边界 || int r右边界 ||  int  k第几小元素)
 
================================================================= template <class  T>  
T  select(T a[], int  l, int  r, int  k)  
  {  
  if(l >= r)   return  a[l]; //参数错误直接返回

  int   i  =  l;  
  int   j  =  r+1;  
  T   pivot  =  a[i];  
  while(true)    
  {  
  do  
  {  
  i = i + 1;  
  }while(a[i] > pivot);  
  do  
  {  
  j = j - 1;  
  }while(a[j] < pivot);  
  if(i >= j)  
  {  
  break;  
  }  
  Swap(a[i], a[j]);  
  }  
  if(j - l + 1 == k) //
如果当前基准适合的位置刚好是K的话,则满足了条件 返回基准值  
  {  
  return  pivot;  
  }  
  a[l] =  a[j];  
  a[j] =  pivot;  
  if(j - l + 1 < k)  
  {  
  return  select(a, j+1, r, k-j+l-1); //如果基准当前位置在K的左边则对右进行快排
 
  }  
  else  
  {  
  return select(a, l, j-1, k); //如果基准当前位置在K的右边则对左进行快排
 
  }  
  }

 

 

 

分析程序:

#include<stdio.h>

class A

{

public:

       static int numA;

       A()

       {

              num++;

       };

       ~A()

       {

              num--;

       };

       virtual void print(void)

       {

              printf("class A, mum:%d/n", num);

       }

 

       void test(void)

       {

              printf("class A test/n");

              print();

       }

};

class B:public A

{

public:

       static int numB;

       B()

       {

              num--;

       };

       ~B()

       {

 

       };

       virtual void print()

       {

              printf("class B, num:%d/n", num);

       }

 

       void test(void)

       {

              printf("class B test/n");

              print();

       }

};

class C

{

public:

       virtual void print()

       {

              printf("class B/n");

       }

};

int A::numA = 0;

int B::numB = 0;

void main()

{

       B b;

       b.print();

       b.test();

       printf("1/n");

       A *a;

       B *p= new(class B);

       p->print();

       p->test();

       printf("1/n");

       a = p;

       a->print();

       a->test();

       delete(a);

       printf("sizeof(C):%d/n", sizeof(C));

}

 

 

 

#include <stdio.h>

class A1

{

public:

    A1(){ doSth(); }

    virtual void doSth(){printf("I am A/n");}

       void test() {doSth();}

};

class B1:public A1

{

public:

 

    virtual void doSth(){ printf("I am B/n");}

};

 

void main()

{

       B1 *b = new B1;

       b->test();

}

 

1 用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。

class ClxBase
{
public
:
    ClxBase() {};
    
virtual
 ~ClxBase() {};

    
virtual void
 DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};

class ClxDerived : public
 ClxBase
{
public
:
    ClxDerived() {};
    ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; 

    
void
 DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};

 

void main()

{

ClxBase *pTest = new ClxDerived;
pTest->DoSomething();
delete pTest;

}

    的输出结果是:

Do something in class ClxDerived!
Output from the destructor of class ClxDerived!

    这个很简单,非常好理解。
    但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:

Do something in class ClxDerived!

    也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
    所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。

原文地址:https://www.cnblogs.com/byfei/p/3112245.html