指针和引用的区别

指针是一个变量,其存储的是一个地址,指向内存的一个存储单元。引用(c++具备)跟原变量实质是同一个东西,只不过是原变量的一个别名,在内存中占同一个存储单元。
指针可以有多级,但引用只能有一级
指针可以为空,但引用值不能为NULL,并且引用在定义的时候必须初始化;
指针在初始化后可以改变,引用在初始化后不能再改变

 

1、二分查找的实现

#include<stdio.h>
int BinSearch(int arr[],int len,int key)                          //折半查找法(二分法)
{
    int low=0;                         //定义初始最小
    int high=len-1;                 //定义初始最大
    int mid;                            //定义中间值
    while(low<=high)
    {
        mid=(low+high)/2;              //找中间值
        if(key==arr[mid])               //判断min与key是否相等
            return mid;    
        else if(key>arr[mid])             //如果key>mid  则新区间为[mid+1,high]
            low=mid+1;
        else                                       //如果key<mid  则新区间为[low,mid-1]
            high=mid-1;
    }
    return -1;                             //如果数组中无目标值key,则返回 -1 ;
}
int main()
{
    int arr[]={1,2,3,4,5,6,7,8,9,10,11};                      //首先要对数组arr进行排序
    printf("%d \n",BinSearch(arr,(sizeof(arr)/sizeof(arr[0])),7));
    return 0;
}

 

2、求给定一个整形数,如何求出其二进制数1的个数

前言:一个数要存储在计算机中,是以该数二进制补码形式存储的。

注意题目没注明不排除为负整数

法1)

思路:我们发现一个数和该数减1后做按位与操作再赋给该数,即某数=某数&(某数-1),每执行一次,该数二进制最右边的1就会丢掉。那么我们便可以知道,只要一个数在变成0之前能执行多少次某数=某数&(某数-1)操作,该数的二进制便有多少个1。

int main()
{
    int x = 9999;
    int countx = 0;
    while(x)
    {
        countx++;
        x = x&(x-1);
    }
    cout<<countx<<endl;
    return 0;
}

此方法既适用于负数,又大大提高了程序执行的效率。

 

法2)思路:如果一个数与1作与运算则可以发现该数最后一位数为1,否则为0. 

#include <iostream>
  using namespace std;

  int main()
  {
      int n = 0;
      cout << "输入一个数";
      cin >> n;
      int count = 0;
      while (n)
 {
      if (n & 1)
      {
          count++;
      }
      n >>= 1;
  }
      cout << "1的个数为"<<count<<endl;
      return 0;
  }

但是此方法存在缺陷如果输入的数为负数则会无限死循环

//必须要循环32次,效率太低

 

法3)首先把n与1做与运算,判断n的最低位是不是为1。接着把1左移一位得到2,再和n做与运算,就能判断n的次低位是不是1….这样反复左移,

每次能判断n的其中一位是不是1.这个解法中循环的次数等于整数二进制的位数,32位的整数需要循环32次

#include <iostream>
  using namespace std;

  int main()
  {
      int n = 0;
      int key = 1;
      cout << "输入一个数";
      cin >> n;
      int count = 0;
      while (key)
 {
      if (n & key)
      {
          count++;
      }
      key <<= 1;
  }
      cout << "1的个数为"<<count<<endl;
      return 0;
  }

缺点同上是效率低

法4)

(不推荐使用):

思路:当我们想要得到一个十进制数的每一位时,通常是采用模10除10的方法,模10得到最低位,除10得到高位,一直重复。那么想要得到一个数的二进制的每一位时,也可以采用模2除2的方法。

 
//求一个数存储在二进制数中1的个数(补码形式存储,所以算的是该数二进制补码中1的个数)
 
int count_one1(int m)   //不适用于负数
{
    int count = 0;
    while (m)   
    {
        if (m % 2 == 1)   //最低位是1
        {
            count++;
        }
        m /= 2;  //处理完最低位后将其丢掉
    }
    return count;
}
int main()
{
    int n = 1;
    int count = count_one1(n);
    printf("%d\n", count);
    system("pause");
    return 0;
}

但我们发现,一个负数不论%2还是/2结果永远是负数,所以用上述代码求解1的个数时永远都是0个,所以此种方法只适用于正数。

posted on 2020-04-28 17:24  Kunix  阅读(249)  评论(0编辑  收藏  举报