基础算法-位运算

简介: 1. 位运算符简介位运算符主要作用于位,是逐位进行操作。最常用的有:与 &、或 |、异或 ^。常见的位运算符有(假设变量 A = 60,变量 B =13):


























一、位运算

1. 位运算符简介

  • 位运算符主要作用于位,是逐位进行操作。最常用的有:与 &、或 |、异或 ^。
  • 常见的位运算符有(假设变量 A = 60,变量 B =13)

80.png


2. 为什么要使用位运算符


  • C 语言位运算符在某些编程中如果灵活应用,则可以大大提高程序的执行效率,使程序执行时速度更高。


  • C 语言主要应用于嵌入式开发、智能电器、通信行业等一些对效率和时间都要求很高的应用领域中,学好位运算符,在程序开发中灵活应用位运算符,往往能在这些应用中起到事半功倍的效果。


3. 与运算符


  • 负数按补码形式参加按位与运算。
  • 清零:如果想将一个单元清零,即使其全部二进制位为 0 ,只要与一个各位都为 0 的数值相与,结果为零。


取一个数的指定位:取数 X=1010 1110 的低4位,只需要另找一个数Y,令Y的低 4 位为1,其余位为0,即Y=0000 1111,然后将 X 与 Y 进行按位与运算即可得到 X 的指定位。

判断奇偶:根据最末位是 0 还是 1 来决定,为 0 就是偶数,为 1 就是奇数。因此可以用 if((a & 1) == 0)代替 if(a % 2 == 0)来判断a是不是偶数。


4. 或运算符


  • 负数按补码形式参加按位与运算。


将一个数据的某些位设置为 1:取数 X=1010 1110 的低4位设置为1,只需要另找一个数 Y,令 Y 的低 4 位为 1 ,其余位为 0,即 Y=0000 1111,然后将 X 与 Y 进行按位或运算即可


5. 异或运算符


  • 翻转指定位:取数 X=1010 1110 的低 4 位进行翻转,只需要另找一个数 Y ,令 Y 的低 4 位为 1 ,其余位为 0 ,即 Y=0000 1111,然后将X与Y进行异或运算即可。
  • 与 0 相异或值不变。
  • 交换两个数
void Swap(int &a, int &b)
{
    if (a != b)
    {
        a ^= b;
        b ^= a;
        a ^= b;
    }
}


6. 取反运算符

  • 如对 a 按位取反,则得到的结果为 -(a+1) 。
  • 对正数、负数和零都适用。


7. 左移运算符


  • 左边的二进制位丢弃,右边补 0 。
  • 若左移时舍弃的高位不包含 1,则每左移一位,相当于该数乘以 2。


8. 右移运算符

  • 正数左补 0,负数左补 1,右边丢弃。
  • 操作数每右移一位,相当于该数除以 2。


二、位运算例题——二进制中1的个数



题目描述

给定一个长度为 n 的数列,请你求出数列中每个数的二进制表示中 1 的个数。


输入格式

输入共两行。

第一行包含整数 n。

第二行包含 n 个整数,表示整个数列。


输出格式

共一行,包含 n 个整数,其中的第 i 个数表示数列中的第 i 个数的二进制表示中 1 的个数。

数据范围

1 ≤ n ≤ 100000

0 ≤ 数列中元素的值 ≤ 1e9



输入样例

5

1 2 3 4 5

输出样例

1 1 2 1 2



具体实现

1. 方法一(模板)

1.1 代码注解


  • for(int i=x;i;i-= i&-i)
  • i 表示 i 为真时继续执行。
  • i-= i&-i 表示 i = i - (i&-i)。
  • i & (-i) 表示的2^k,其中 k 表示 i 中从低位到高位的第一个 1 的位索引。


1.2 实现代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int x;
        int res=0;
        cin>>x;
        for(int i=x;i;i-= i&-i) 
        {
            res++ ;
        }
        cout<<res<<" ";
    }
    system("pause");
    return 0;
}



2. 方法二( lowbit )

1.1 实现思路


lowbit(x) 是 x 的二进制表达式中最低位的 1 所对应的值。

使用 lowbit 操作,每次 lowbit 操作截取一个数字最后一个 1 后面的所有位,每次减去 lowbit 得到的数字,直到数字减到 0 ,就得到了最终 1 的个数。

根据计算机负数表示的特点,如一个数字原码是 1000 1000 ,他的负数表示形式是补码,就是反码 +1 ,反码是 0111 0111 ,加一则是 0111 1000 ,二者按位与得到了1000 ,就是我们想要的 lowbit 操作。


1.2 实现代码

#include<bits/stdc++.h>
using namespace std;
int lowbit(int x)
{
    return x&(-x);
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int x;
        cin>>x;
        int res=0;
        while(x)
        {
            x-=lowbit(x);
            res++;
        }
        cout<<res<<' ';
    }
    system("pause");
    return 0;
}


3. 方法三(暴力枚举)

1.1 实现思路

  • 对于每个数字a,a &1得到了该数字的最后一位,之后将a右移一位,直到位0,就得到了1的个数。


1.2 实现代码

#include <bits/stdc++.h>
using namespace std;
int n;
int a,k;
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a;
        k=0;
        while(a)
        {
            k+=a&1;
            a=a>>1;
        }
        cout<<k<<" ";
    }
    system("pause");
    return 0;
}
















相关文章
|
6月前
|
算法
算法思想总结:位运算
算法思想总结:位运算
|
6月前
|
机器学习/深度学习 存储 算法
【算法基础】常数操作 时间复杂度 选择排序 冒泡排序 插入排序 位运算
【算法基础】常数操作 时间复杂度 选择排序 冒泡排序 插入排序 位运算
|
算法
基础算法:位运算
基础算法:位运算
54 0
|
3月前
|
算法
【算法】位运算算法——消失的两个数字(困难)
【算法】位运算算法——消失的两个数字(困难)
|
3月前
|
算法
【算法】位运算算法——只出现一次的数字Ⅱ
【算法】位运算算法——只出现一次的数字Ⅱ
|
3月前
|
算法
【算法】位运算算法——判断字符是否唯一
【算法】位运算算法——判断字符是否唯一
|
3月前
|
算法
【算法】位运算算法——两整数之和
【算法】位运算算法——两整数之和
|
3月前
|
算法
【算法】位运算算法——丢失的数字
【算法】位运算算法——丢失的数字
|
3月前
|
算法
算法】位运算——常见位运算基础操作总结
算法】位运算——常见位运算基础操作总结
算法】位运算——常见位运算基础操作总结
|
5月前
|
存储 自然语言处理 算法
位运算入门及简单算法题的应用
位运算入门及简单算法题的应用
48 1