数据结构与算法XS班-左程云第一节课笔记(位运算、算法是什么、简单排序)

第1节 位运算、算法是什么、简单排序

##这是数据结构与算法新手班-左程云第一节课的笔记##

1. 位运算

// 你们会不会表示一个数字的32位啊?
// Java中int类型默认以32位二进制数在计算机内存储,只是用十进制给你显示出来(先用这个例子让你知道什么是位运算,什么是左移、右移运算符)
public class Test {
    public static void print(int number){
        for(int index = 31;index >= 0;index--){
			// &:有0则0 
			// |:有1则1 
			// ^:相同则0,不同则1 
			// ~:否
			// << 左移运算符:右边用0来补,左移1位相当于×2
			// >> 右移运算符:左边用0来补,右移1位相当于÷2
            System.out.print( (number & ( 1 << index)) == 0 ? "0":"1");
        }
        System.out.println();
    }
    public static void main(String[] args){
        // 假设数字为100
        int number = 100;
        print(number);
    }
}
// 这个代码就给你留在这里了,位运算在后面展开吧…接下来讲一下负数是怎么表示的?反码啊、补码啊这些.... 
// int的范围理应是0-2^32-1,然而我们去编译器里面打印下最大值,结果是21亿多,怎么少一半呢?
int a = Integer.MAX_VALUE;
System.out.println(a);
// out:2147483647
// 那他的二进制是什么样呢?正好有这个函数,我们看一下
System.out.print(a);
// out:01111111 11111111 11111111 11111111
// 哦!会发现最高位是0,这个是符号位,最左侧的位用1表示负数。所以JAVA中int的范围为-2^31~2^31-1,加起来总共2^32个数字,0开头的有2^31个(包括0自己),1开头的也有2^31个。

// 负数的二进制怎么表达呢?11111111 11111111 11111111 11111111:表示-1,符号位不管,其它部分按位取反再加1
int b = Integer.MIN_VALUE;
System.out.print(b);
// out:10000000 00000000 00000000 00000000,按位取反再加1,表示-2^31,,它的目标是二进制位->十进制位,先看符号位是多少,如果是1,就把负号写上,然后把符号位后面的按位取反再加1,按照32位存储,把得出来的正数直接放在符号的后面

// 那么为毛负数就是按位取反再加1呢?今天我不可能展开,但原理是这样的!
// 在计算机内,所有的算数符号底层都是用位运算符来实现的,比如a+b,如果a、b都是正数,有一套运算逻辑,但是a为负数呢?这套逻辑不符合了怎么办?再给它开辟一个新的逻辑?那么这么多算数符号,要开辟这么多逻辑吗?太麻烦了!想象能不能把负数也采用正数的逻辑?这个规则的作用就是解决这个问题的!
// 突然想到一个事,>>和>>>的区别?
// >> 右移运算符:这个是用符号位来补。例如:1024是用0来补左侧,-22是用1来补左侧。而>>>是不用符号位补,即默认用0补。

// 再者:相反数怎么写?
int c = 5;
int d = -c;
System.out.print(d);
d = (~c + 1);
System.out.print(d);
// 这里的~不管是不是符号位,都取反,它的目标是二进制位->二进制位
// 00000000 00000000 00000000 00000101 原c
// 11111111 11111111 11111111 11111011 取反加1,为-5
// 这个不管正负,都可以使用这个逻辑。
// 00000000 00000000 00000000 00000101 再取反加1,为5,回去了,测试成功!
// 正数比负数表示少一位,每一个正数都有对应的负数,那么最小那个数取相反是多少?好问题!答案是还是本身!
// 10000000 00000000 00000000 00000000 最小数字表达
// 01111111 11111111 11111111 11111111 + 00000000 00000000 00000000 00000001 按位取反再加1
// 10000000 00000000 00000000 00000000 回去了,还是最小数字
// 0的相反数是多少?
// 00000000 00000000 00000000 00000000
// 11111111 11111111 11111111 11111111 + 00000000 00000000 00000000 00000001 按位取反再加1
// 00000000 00000000 00000000 00000000 溢出了!还是其本身

3. 什么是算法?

  • 有具体的问题(要解决的问题)
  • 有涉及解决这个问题的具体流程(算法/方法)
  • 有评价处理流程的可量化指标(你可以设计流程,我也可以设计流程,肯定有个好中差,怎么评价呢?得用指标呀!)

4. 算法的分类?

  • 分类当然非常多,但大体而言就分为两类
  • 对于新手学习特别重要的一个分类:1.第一类:明确知道怎么算的流程(就是白话文吧,直接写出来的那种);2.第二类:明确知道怎么尝试的流程(比如一个数的所有因子没给出来,但是我可以算出来)

5. 题目之n的阶乘之和→也算是对可量化指标的解释吧!

/*题目一:给出一个数字N,求出1!+2!+....N!*/
class Test{

    // 小A同学的做法,用了两个方法
    public static int factor(int number){
        int result = 1;
        for(int index = 1;index <= number;index++){
            result *= index;
        }
        return result;
    }
    public static int fun1(int N){
        int sum = 0;
        for(int index = 1;index <= N;index++){
            sum += factor(index);
        }
        return sum;
    }

    // 小B同学
    public static int fun2(int N){
        int sum = 0;
        int cur = 1;
        for(int index = 1;index <= N;index++){
            cur = cur * index;
            sum += cur;
        }
        return sum;
    }

    public static void main(String[] args){
        // 写的真恶心
        System.out.println(fun1(10));
		// 这个还可以
        System.out.println(fun2(10));
    }
}

5. 题目之简单排序:选择、冒泡、插入+插入优化

/*题目二:选择排序,思想很重要:每一轮把这一轮的最小值放在第一个位置,直至N轮完成后,序列自动归位*/
class Test{

    // 选择排序
    public static void selectSort(int[] arr){
        // 先想边界条件
        if(arr == null || arr.length < 2){
            return;
        }

        // 0 ~ n-1,将最小值放在0位置
        // 1 ~ n-1,将最小值放在1位置
        // 2 ~ n-1,将最小值放在2位置
        // ...
        // n-2 ~ n-1,将最小值放在n-2位置
        for(int i = 0;i < arr.length-1;i++){
            // 定义最小值的位置
            int minValueIndex = i;
            for(int j = i + 1;j < arr.length;j++){
                // 这是我的写法
                if(arr[minValueIndex] > arr[j]){
                    minValueIndex = j;
                }
                // 这是老师的写法
                // minValueIndex = arr[j] < arr[minValueIndex] ? j : minValueIndex;**
            }
            // 交换
            int temp = arr[minValueIndex];
            arr[minValueIndex] = arr[i];
            arr[i] = temp;
        }
    }

    public static void main(String[] args){
        int[] arr = {1,54,21,45,2,44};
        selectSort(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }
}
/*题目三:冒泡排序,思想很重要:每一轮把最大的值往后放,大泡泡先上去*/
// 总结:冒泡是大往后,选择是小往前
class Test{

    // 冒泡排序
    public static void bubbleSort(int[] arr){
        // 先想边界条件
        if(arr == null || arr.length < 2){
            return;
        }

        // 0 ~ n-1 区间干一坨事情
        // 0 ~ n-2 区间干一坨事情
        // 0 ~ n-3 区间干一坨事情
        // ...     区间干一坨事情
        // 0 ~ 1   区间干一坨事情
        
        // 这里就用end表示后边的变量
        for(int end = arr.length-1;end > 0;end--){
            // 后面的确定好了就不需要考虑了,所以你后面就要-i,然后判断里面写的是arr[j+1]和arr[j]判断,所以还需要额外-1,否则会溢出
            for(int first = 0;first < end;first++){
                // 这是我的写法
                if(arr[first+1] < arr[first]){
                    // 交换
                    int temp = arr[first+1];
                    arr[first+1] = arr[first];
                    arr[first] = temp;
                }
            }

        }
    }

    public static void main(String[] args){
        int[] arr = {1,54,21,45,2,44};
        bubbleSort(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }
}
/*题目四:插入排序,思想很重要:间断区间有序,类似与打斗地主*/
class Test{

    // 插入排序
    public static void insertSort(int[] arr){
				 // 先想边界条件
        if(arr == null || arr.length < 2){
            return;
        }
        // 0-1 区间有序
        // 0-2 区间有序
        // 0-3 区间有序
        // .....
        // 0-n-1 区间有序
        for(int end = 1;end < arr.length;j++){
            // 怎么实现区间内有序呢?
			int newNumIndex = end;
            while(newNumIndex - 1 >= 0 && arr[newNumIndex -1] > arr[newNumIndex]){
               // 交换
               int temp = arr[newNumIndex];
               arr[newNumIndex] = arr[newNumIndex-1];
               arr[newNumIndex-1] = temp;
			   newNumIndex--;
            }

			/* 这是我实现的,其实一模一样
			// 怎么实现区间内有序呢?
            for(int newNumIndex = end;newNumIndex > 0;newNumIndex--){
                // 现在进到区间里面了,开始判断
                if(arr[end-1] > arr[newNumIndex]){
                    // 交换
                    int temp = arr[newNumIndex];
                    arr[newNumIndex] = arr[newNumIndex-1];
                    arr[newNumIndex-1] = temp;
                }
            }
			*/

        }
    }

    public static void main(String[] args){
        int[] arr = {1,54,21,45,2,44};
        insertSort(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }
}
/*题目四:插入排序,那我们可以再优化上一个版本*/
// 咦~他的优化版本和我上面注释的自己写的部分几乎一样!那我这里就不写了....
class Test{

    // 插入排序
    public static void insertSort(int[] arr){
		// 先想边界条件
        if(arr == null || arr.length < 2){
            return;
        }
        // 0-1 区间有序
        // 0-2 区间有序
        // 0-3 区间有序
        // .....
        // 0-n-1 区间有序
        for(int end = 1;end < arr.length;j++){
            for(int newNumIndex = end;newNumIndex > 0;newNumIndex--){
                // 现在进到区间里面了,开始判断
                if(arr[end-1] > arr[newNumIndex]){
                    // 交换
                    int temp = arr[newNumIndex];
                    arr[newNumIndex] = arr[newNumIndex-1];
                    arr[newNumIndex-1] = temp;
                }
            }
        }
    }

    public static void main(String[] args){
        int[] arr = {1,54,21,45,2,44};
        insertSort(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值