练习

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外面时就会自动调用析构函数,相当于用析构函数释放之前实例的内存。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值