zoukankan      html  css  js  c++  java
  • 算法中琐碎知识点(排序、哈希散列、进制转化、C++)

    一、进制转化

    • 对于一个P进制想要转化为Q进制的数,需要分成两步:
    1. 将P进制数x转化为十进制数y;
    int y = 0, product = 1;//product在循环中会不断乘P,得到1, p,p^1.....
    while(x != 0){
        y += (x % 10) * product;
        x /= 10;
        product *= P;
    }
    
    2. 将十进制数y转化为Q进制z;
    • 采用除基取余法,所谓基是指进制Q,每次将数除以Q,然后将得到的余数作为低位存储,而商继续除以Q,最后当商为0时,将所有位从高到低输出就可以得到z;
    int z[40], num = 0;
    do{
        z[num++] = y % Q;
        y /= Q;
    }while(y != 0);
    
    • 这样将z数组从高位z[num-1]到低位z[0]即为Q进制z,进制转换完成。

    二、各种排序

    • 需要一个判断每一次排序后是否一致的函数:
    bool isSame(int A[], int B[]){
        for(int i = 0; i < n; i++){
            if(A[i] != B[i]) return false;
        }
        return true;
    }
    
    • 需要一个进行下一轮后输出结果的函数
    void showArray(int A[]){
        for(int i = 0; i < n; i++){
            if(i != 0) printf(" ");
            printf("%d", A[i]);
        }
        printf("
    ");
    }
    
    • 需要一个每一步排序判断的函数,即与具体的算法进行结合;
    bool insertSort(){
        bool flag = false;
        for(int i = 1; i < n; i++){
            if(i != 1 && isSame(tempOri, change)){
                flag = true;
            }
            int temp = tempOri[i], j = i;
            while(j > 0 && temp < tempOri[j-1]){
                temp[j] = temp[j-1];
                j--;
            }
            if(flag == true){
                return true;
            }
        }
        return false;
    }
    
    1. 选择排序
    • 对于一个序列A[N],进行N趟排序,第i次将i~N中选出最小的元素,然后将其与A[i]位置的元素进行交换;
    void seleteSort(){
        for(int i = 0; i < n; i++){
            int k = i;
            for(int j = i; i < n; i++){
                if(A[j] < A[k]){
                    k = j;
                }
            }
            int temp = A[i];
            A[i] = A[k];
            A[k] = temp;
        }
    }
    
    2. 插入排序
    • 默认将A[N]序列的前方1~i-1位为有序,然后将第i位插入到其中,具体实现方法为,临时使用一个变量,然后存储A[i],变量j = i,然后从i-1个元素开始比较,如果大于它,将第i-1位覆盖掉A[i], 说明第i为可以往前插入,然后j--;
    int A[Maxn], n;//数组元素个数为n,下标从1~n
    void insertSort(){
        for(int i = 2; i <= n; i++){
            int temp = A[i], j = i;
            while(j > 1 && temp < A[j - 1]){
                A[j] = A[j - 1];
                j--;
            }
            A[j] = temp;
        }
    }
    
    3. 2路-归并排序
    • 原理是通过每次将两组有序序列再进行排序,最后进行递归处理即可,首先将左边的进行递归排序,然后是右边,最后进行合并即可
    void merge(int A[], int L1, int R1, int L2, int R2){
        int i = L1, j = L2;
        int temp[maxn], index = 0;
        while(i <= R1 && j <= R2){
            if(A[i] < A[j]) temp[index++] = A[i++];
            else temp[index++] = A[j++];
        }
        while(i <= R1) temp[index++] = A[i++];
        while(j <= R2) temp[index++] = A[j++];
        for(int i = 0; i < index; i++){
            A[L1 + i] = temp[i];
        }
    }
    void mergeSort(int A[], int left, int right){
        if(left < right){
            int mid = (left + right) / 2;
            mergeSort(A, left, mid);
            mergeSort(A, mid + 1, right);
            merge(A, left, mid, mid + 1, right);
        }
    }
    
    4. 快速排序
    • 每次将主元Left上的元素放到它的基位上,也就是左边元素都小于它,右边元素都大于它, 关键是它的Partition函数,使用temp接收数组左边第一个元素,然后分别使用指针指向数组的第一个元素和最后一个元素,结束标志是左边指针和右边指针重合时,首先对右边进行查找到第一个小于temp的, 然后将该值赋到左边第一个值处,左边同理,最后将temp值放入left终止处,返回left位置;
    • 最终函数关键是第一次返回的主元位置,将数组划分为两个部分,然后递归继续划分
    int Partition(int A[], int left, int right){
        int temp = A[left];
        while(left < right){
            while(left < right && A[right] > temp) right--;
            A[left] = A[right];
            while(left < right && A[left] < temp) left++;
            A[right] = A[left];
        }
        A[left] = temp;
        return left;
    }
    //关键是第一次返回的主元位置,将数组划分为两个部分,然后递归继续划分
    void qiuckSort(int A[], int left, int right){
        if(left < right){
            int pos = Partition(A, left, right);
            quickSort(A, left, pos - 1);
            quickSort(A, pos + 1, right);
        }
    }
    

    三、哈希散列(key是整数)

    1. 插入
    • 直接将输入的数作为数组下标来对这个数的性质进行统计,用空间换时间,一般这样处理每个数不会超过10的5次方
    • 散列就将一个元素是通过一个函数转化为一个整数,使得该整数尽量唯一的代表这个元素。
    • 使用一个v数组进行存储转换后的下标,hash数组用于记录是否插入到散列中;
    	vector<int> v(n), hash(m);
    	for(int i = 0; i < n; i++){
    		scanf("%d", &v[i]);
    		int size = 0;
    		while(size < m){
    			if(hash[(v[i] + size*size) % m] != 0){
    				size++;
    			}else{
    				hash[(v[i] + size*size) % m] = 1;
    				v[i] = (v[i] + size*size) % m;
    				break;
    			}
    		}
    		if(size >= m) v[i] = -1;
    	}
    
    2. 查找
    • 查找的时候,可以根据上面插入时候的hash表,每次进行查找,方法基本一致,统计查找次数,有一点区别是,这个时候size的界限是小于等于m,而不是小于m
    • 同时,如果查到到hash值为空,也应该停止查找;
    3. 常用的散列函数:
    • 直接定址法
    • 平方取中法
    • 除留余数法(常用)
    • 公式:H(key) = key % mod, 一般将mod取成Tsize, mod一般是个素数。
    bool isPrime(int n){
        if(n <= 1) return false;
        int sqr = (int)sqrt(n);
        for(int i = 2; i <= sqr; i++){
            if(n % i == 0) return false;
        }
        return true;
    }
    
    4. 除留余数法常用解决冲突的方法
    • 线性探测法,如果被占用,那么就加一。
    • 平方探测法,当位置被占有时,将k等于1^2, 2^2, 3^2,进行查找,如果k在[0, Tsize)都找不到位置,那么当k>=Tsize也找不到位置;
    • 链地址法,直接将余数相同的值,放入一个链表中;
  • 相关阅读:
    Java中如何解决double和float精度不准的问题
    Linux防火墙Firewall和Iptables的使用
    yum 彻底删除nodejs,重新安装
    hbase集群搭建参考资料
    10分钟教你打造一个微信语音点歌系统
    微信公众平台向特定用户推送消息
    圆角与半角互相转换
    Swagger简单介绍
    测试通过!为何线上还有很多BUG?实践中的质量控制
    AXURE插件在 Chrome 浏览器中用不了怎么办?
  • 原文地址:https://www.cnblogs.com/tsruixi/p/13328081.html
Copyright © 2011-2022 走看看