软件工程师面试编程常见函数实现

1、引用与指针区别:引用必须初始化,不可以改变值,不可指向NULL。
2 、字符串比较,判断2个字符串是否相等:
int strcmp(char  *source, char *dest) 相等返回0,不等返回-1;
{  
   ASSERT((source!=NULL)&&(dest!=NULL)); //判断指针是否为空,如果为空,则报错。
   int i,j;  
   for(i=0; source[i]==dest[i]; i++)
    {   
       if(source[i]==’/0 && dest[i]=='/0')    //如果source和dest字符串同时到了尾部,则返回0.
             return 0;  
       else    
             return -1; 
    }
}



3 .字符串复制,遇到'/0'立即停止复制。
char *strcpy(char *strDest, const char *strSrc) //注意,按道理,source字符串应该是const,所以用const *src修饰。
{
   ASSERT(strDest != NULL && strSrc != NULL);
   char *addr = strDest; //创建一个指针,指向strDest的存储区域
   while(*strDest++=*strSrc++)
         NULL; //NULL可以省略,但更有利于编译器发现错误
   return addr;
}


4、子串查找,返回子字符串所在位置
int strindex(char *str,char *substr)  //在str中,查找substr,返回索引位置。
{   
   int end,i,j;
   end = strlen(str) - strlen(substr);  /*计算结束位置*/
   if ( end > 0 )                       /*子串长度必须小于str字符串*/
   {   
      for ( i = 0; i <= end; i++ )
         for ( j = i; str[j] == substr[j-i]; j++ ) /* 用循环比较 */
            if ( substr[j-i+1] == '/0' )           /* 子串查找结束*/
               return i + 1;                       /* 找到了子串*/   
   } //if
  return -1; //子串长度大于要str
}


4 、memcpy() 用来拷贝src前n个字节到dest所指的地址上。

       与strcpy()不同的是,memcpy()会完整的复制n个字节,不会因为遇到字符串结束'/0'而结束。函数返回指向dest的指针。

void *memcpy(void* dest,const void* src, int size)
{
void* pDest = (char*)dest; // memcpy函数原型里面的参数是void*,这里用(char*)做强制类型转换。
void* pSrc = (char*)src;
ASSERT(dest != NULL && src != NULL);
/*下面ASSERT,用来判断memcpy会不会有重叠。如果重叠,就不要使用memcpy()而使用memmove()函数。 */
ASSERT(pDest>=pSrc+size || pSrc>=pDest+size);
while(size-->0)   
         *pDest++ == *pSrc++;
return dest;
}
 
5、memmove(),对比memcpy()。
void *Memmove(void *Dest, const void*Src,int count)
{
ASSERT(Dest!=NULL && Src!=NULL);
void* pDest = Dest;
if (Dest<Src && (char*)Dest > (char*)Src + count) //判断内存移动时,确定没有地址重叠
   {   
          while(count--)  
                *(char*)Dest++ = *(char*)Src++;  
   }
else // 有地址重叠,从src的串尾开始复制
   {   
        Dest = (char*)Dest + count - 1;  
        Src = (char*)Src + count - 1;//指向串尾,从尾部开始复制
        while(count--)   
              *(char*)Dest- - = *(char*)Src- -;
    }
return Dest;
} 
 
6、单链表插入删除节点
首先,定义一个单链表结构体,包含数据和指针(指向下一个数据)
struct linklist  
    {int data;  
    struct linklist*next;  
    }; 
 
【6.1】单链表插入节点
     在单链表节点p后面插入s节点:只需这2步关键步骤
    (1)s=(Linklist*)malloc(sizeof(Linklist); 
    (2)s->next=p->next ;   p->next=s;
      完整程序如下:
/***************单链表插入节点********************/
int listinsert(linklist *head,int i , int data)
{
       linklist *p,*s;int j=0;
       p=head;
while(p && j++<i) { p=p-next;} //查找插入第i-1个位置
if(p==NULL ||  j>i) 
{
   cout<<"Positon Error"; 
   return 0;
}
s=(linklist*)malloc(sizeof(linklist));
assert(s!=NULL);
s->data=data; 
s->next=p->next; 
p->next=s;//在第i-1个位置后面,即指针p后面插入data
return 1;
}
 
【6.2】单链表删除节点
/***************单链表删除节点********************/
int listdelete(linklist *head,int i)
{
       linklist *p,*q;int j=0;
       p=head;
while(p->next && j++<i) { p=p-next;} //查找第i-1个位置,待删除节点的前一个节点
if(p->next==NULL ||  j>i) 
{
   cout<<"Positon Error"; 
   return 0;
}
q=p->next; 
p->next=q->next;//删除节点i
return 1;
}
 
7、 翻转链表(链表逆序),常见面试题。
void reverselinklist(linklist *head)
{
    linklist *pre,*curr;//设置两个指针
    pre=head;
    curr=head->next;
    head->next=NULL;
    while(curr!=NULL) 
            { 
              pre=curr;
              curr=curr->next;
              pre->next=head->next;
              head->next=pre; //在head后面依次插入各个pre
            }
} 
 
8、实现有序链表上的插入
void linklist(linklist head ,elemtype x)
{
   linklist pre,curr, q; 
   pre=head; 
   curr=head->next;
   while( curr!=NULL  &&  curr->data<=x )  //x为要插入的数据
           {
                pre=curr; 
                curr=curr->next; //循环向后移动这2个指针,直至找到插入位置
           } 
   q =(linklist *)malloc(sizeof(linklist));
   assert(q!=NULL);//判断是否成功分配内存
   q->data=x ;     //申请节点,插入数据x
   q->next=pre->next ; 
   pre-next=q; 
 }
 
9、折半查找干啥用?( 用于对递增顺序表的查找)
int zheban(int *t)
{
    low=0;
    high=length-1;
    while(low<=high)
          {
              mid=(low+high)/2; 
              if (table[mid].data=x)   
                     return mid;
              else
                    {  
                        if(x<t[mid].data)  
                                  high=mid-1; 
                        else 
                                   low=mid+1;
                }
           } //while
    return -1;
}
 
10、双向链表删除节点P,P后插入节点;
 
首先,定义一个双向链表的结构体元素。 
struct link{
  struct link *prior; //前驱 
  int data; 
  struct link *next; //后继
};
  
/********************双向链表删除操作***************************/
int ListDelete_DuL(struct link *head, int num)
{
   struct link *p;  
   p=head->next;
   while(p&&p->data!=num) 
         p=p->next;//查找要删除的结点
   if(p!=NULL)
   {
       p->pre->next=p->next;
       p->next->pre=p->pre;
       p->pre=NULL;  
       p->next=NULL;
       free(p);    
       return 1;// 比如要查找某元素,找到就返回1,没找到返回0。用来判断结果的
   }
  else    
  {
           return 0;
   }
}








/********************双向链表插入操作*****************************/
int ListInsert_DuL(DuLinkList *head,int num)
{
   struct link *p,*q;
   p=head->next;
   while(p&&p->data!=num)  p=p->next; // 查找插入位置
   if(p!=NULL)
   { 
        q=(struct link *)malloc(sizeof(struct link));
        ASSERT(q!=NULL);
        q->data=num;
      q->pre=p;//插入节点
      q->next=p->next;
      p->next->pre=q;
      p->next=q;   
        return 1;
  }
    else    
    {
         return 0;  
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值