练习

来源:互联网 发布:linux常用命令cat 编辑:程序博客网 时间:2024/06/02 16:09

1、两个已排序数组合并以后的中位数

int getMedin(int A[],int m,int B[],int n)  {      int p1=0;      int p2=0;      int mid=p1;      int flag=0;      for(int i=0;i<(m+n)/2;)      {          while(p1<m&&p2<n&&i<(m+n)/2&&!flag)          {              if(B[p2]<A[mid])              {                  ++p2;++i;              }              else              {                  mid=p2;                  flag=1;                  ++p1;                  ++i;              }          }          while(p1<m&&p2<n&&i<(m+n)/2&&flag)          {              if(A[p1]<B[mid])              {                  ++p1;++i;              }              else              {                  mid=p1;                  flag=0;                  ++p2;                  ++i;              }          }          while((p1==m||p2==n)&&i<(m+n)/2)          {              ++mid;              ++i;          }      }      if(flag)          return B[mid];      return A[mid];    }  

2、已知两个链表各自有序,写一个程序使他们合并起来依然有序

struct node  {      int _data;      node* _next;  };    void merge(node *head1,node *head2,node *head3)  {      node *pl1=head1->_next;      node *pl2=head2->_next;      node *pl3;      head3=head1;      head3->_next=NULL;      free(head2);      pl3=head3;      while(pl1!=NULL&&pl2!=NULL)      {          if(pl1->_data<=pl2->_data)          {              pl3->_next=pl1;              pl1=pl1->_next;              pl3=pl3->_next;          }          else          {              pl3->_next=pl2;              pl2=pl2->_next;              pl3=pl3->_next;          }             }      pl3->_next=NULL;      if(pl1!=NULL)          pl3->_next=pl1;      if(pl2!=NULL)          pl3->_next=pl2;  } 
如果想得到相反的序列就用头插法

3、字符串匹配查找

#include<iostream>  using namespace std;    //str1指向带查找字符串,str2指向待匹配字符串  char *strfind(const char *str1,const char *str2)  {      const char *ptr1=str1;      const char *ptr2=str2;      const char *result=(char *)0;      while(*ptr1!='\0')  //查找字符串没有结束      {          if(*ptr1==*ptr2)          {              result=ptr1;              while(*ptr2!='\0')              {                  if((*ptr1!='\0')&&(*ptr1==*ptr2))                  {                      ptr1++;                      ptr2++;                  }                  else                      break;              }              if(*ptr2=='\0')                  return (char *)result;              else if(*ptr1!='\0')              {                  ptr2=str2;                  ptr1=result+1;                  result=(char *)0;              }              else              {                  break;              }          }          ptr1++;      }      return (char*)0;  }    int main()  {      char s1[]="abcdefghijk";      char s2[]="def";      char *ptr=strfind(s1,s2);      cout<<*ptr<<endl;      return 0;  }  

这是一道风行的笔试题,其实代码比较简单,就是里面的逻辑关系要考虑清楚,不能漏掉任何一种情况

4、反转字符串,保持子串相对位置不变


思路:先将字符串里面的子串反转,然后再将整个字符串反转
void reverse(char *str,int m,int n)  {      if(!str)  //字符串为空直接退出          exit(0);      if(m==n)//子串只有一个元素不用交换          return;      for(int i=m,j=n;i<j;i++,j--)  //交换元素      {          char temp=str[i];          str[i]=str[j];          str[j]=temp;      }  }    int main()  {      char str[]="a bc def gh ijk";      int len=strlen(str);      int m=0,n=0;      for(int i=0;i<len;i++)      {          if(str[i]==' ')          {              n=i-1;              reverse(str,m,n); //交换子串              m=i+1;              n=i+1;          }      }      reverse(str,0,len-1);//交换整个数组      for(int i=0;i!=len;i++)          cout<<str[i]<<" ";      cout<<endl;      return 0;  }  

5、给定一数组a[N],我们希望构造数组b [N],其中b[j]=a[0]*a[1]…a[N-1] / a[j],在构造过程中,不允许使用除法


#include<iostream>  using namespace std;    void printfn(int a[],int n)  {      for(int i=0;i<n;i++)          cout<<a[i]<<" ";      cout<<endl;  }  int main()  {      const int MAX=5;      int a[MAX]={1,2,3,4,5};      int b[MAX];      b[0]=1;      for(int i=1;i<MAX;i++)      {          b[i]=b[i-1]*a[i-1];      }      /*        b[0]=1;        b[1]=a[0];        b[2]=a[0]*a[1];        b[3]=a[0]*a[1]*a[2];        b[4]=a[0]*a[1]*a[2]*a[3];        */      for(int i=MAX-1;i>0;i--)      {          b[i]*=b[0];          b[0]*=a[i];                }      /*         b[4]=b[4]=a[0]*a[1]*a[2]*a[3];                 b[0]=a[4];          b[3]=b[3]*a[4]=a[0]*a[1]*a[2]*a[4];            b[0]=a[4]*a[3];          b[2]=b[2]*a[2]=a[0]*a[1]*a[3]*a[4];            b[0]=a[4]*a[3]*a[2];         b[1]=b[1]*b[4]=a[0]*a[2]*a[3]*a[4];            b[0]=a[4]*a[3]*a[2]*a[1];         */      printfn(a,5);      printfn(b,5);      return 0;  }  

6、如下为类型MyString的声明,请为该类型添加赋值运算符函数

class CMyString{public:CMyString(char* pdata=NULL);CMyString(const CMyString& str);CMyString& operator=(const CMyString& str);~CMyString(void);private:char* m_data;};


 写出的代码要关注以下几点
1、是否把返回值声明为该类型的引用,只有返回一个引用才允许连续赋值。
2、是否传入的参数是常量引用
3、是否释放实例本身已有的内存
4、是否判断传入的参数和当前的实例是不是同一个实例

综合一下可以写出
CMyString& CMyString::operator=(const CMyString &str){if(this==&str)return *this ;delete []m_data;  m_data=NULL;m_data=new char[strlen(str.m_data)+1];strcpy(m_data,str.m_data);return *this;}
但是这并不是很完善的代码
参照effective C++中的条款11
如果new char导致异常,CMyString最终会持有一个指针指向一块被删除的char[],这样的指针有害,你无法安全的删除它们,甚至无法安全的读取它们,唯一能对它们做的安全事情是付出许多调试找出错误的根源。
为了避免异常,对代码做出以下的修改
CMyString& CMyString::operator=(const CMyString &str){if(this!=&str){CMyString strTemp(str);char *ptemp=strTemp.m_data;strTemp.m_data=m_data;m_data=ptemp;}return *this;}

先创建一个临时实例strTemp,接着把strTemp.m_data和自身实例的m_data作交换。由于strTemp是一个局部变量,当程序运行到if外面时就会自动调用析构函数,相当于用析构函数释放之前实例的内存。