2019吉林大学计算机高级程序设计笔记

3.26日复试完,玩了一天,28日去了招聘会,因为自己没把握能不能考上,不管怎么样,先去找份工作,等待的过程太焦急了,今天去参加技术面试。

首先我先劝退一波,今年计专线是373分。
我专业课135,这个分数确实只能算是平均分,和我一起复试的最高有149的,普遍130多分,各位权当看看吧,高级程序设计部分的笔记,数据结构过两天再总结。

相关的专题

1,排列组合类题型,这类在软件专硕出现过,主要思想是交换再递归重排

//这是排列算法 方法1
void permutation(char *p, char * pbegin){
    if(*pbegin == '\0')
        printf("%s",p);
    else{
        for(char *ch = pbegin; *ch != '\0'; ch++){
            swap(*pbegin,*ch);
            permutation(p, pbegin+1);
            swap(*pbegin, *ch);
        }
    }
}

//方法2,其实和方法1区别不大,换一种写法
void permutation(char*p, int k, int m){
    if(k == m)
        printf("%s",p);
    else{
        for(int i = k; i<=m ; i++){
            swap(*(p+k),*(p+i));
            permutation(p, k+1, m);
            swap(*(p+k),*(p+i));
        }
    }
}

//如果去除重复的组合
bool Isswap(char *pbegin, char *pend){
    char *p;
    for(p = pbegin; p<pend; p++){
        if(*p == *pend)
            return false;
    }
    return true;
}

组合算法

const int N = m;
int temp[];
int a[];
void combine(int n, int m){  //从n个元素中选出m个
    if(m == 0){
        for(int i = 0; i<N; i++){
            cout<<temp[i];
        }
        cout<<endl;
    }else if(n<m)return;
    else{
        combine(n-1,m); //不选当前元素,从剩下的n-1中选出m个
        temp[m-1]=a[n-1];
        combine(n-1,m-1);//选择当前元素
    }
}
//另一种写法
void combine(int n, int m){
    for(int i = m; i<n; i++){
        temp[m-1] = a[i-1];
        if(m > 1)
            combine(i-1,m-1);
        else{
            for(int j = 0;j<N;j++)
                cout<<temp[j];
        }
        cout<<endl;
    }
}

2,幂集问题,这是软专考过的一个问题,顺便提一嘴,吉大命题喜欢把计专,软专,计学,软学,这些题目交叉考,所以建议各位无论是考什么,都要把这四项真题全部过一遍。

//这类题目涉及到位运算,不懂的可以先去看看相关的资料或视频

void powerset(char *set, int size){
    int pow_size = 1<<size;   // 2^size or pow(2,size)
    int counter,j;
    for(counter = 0; counter<pow_size; counter++){
        for(j=0; j<size; j++){
            if(counter&(1<<j))
                cout<<set[j];
        }
        cout<<endl;
    }
}

3,计算几何问题

  1. 矢量点积运算
  2. 矢量叉积运算
矢量点积运算
double Dot(point p1,point p2){    //这里p2 p1都是坐标
    return p1.x * p2.x + p1.y*p2.y;
} 
若矢量点积运算结果
< 0 锐角
> 0 钝角
= 0 直角


矢量叉积运算
double Det(point p1,point p2){
    return p1.x * p2.y - p1.y * p2.x;
}  

结果
> 0 p1在p2顺时针
< 0 p1在p2逆时针
= 0 p1 p2共线,可以同向也可以反向

顺便一提海伦公式(求三角形面积),a,b,c为三边长度,p为半周长

p = (a+b+c)/2
s = sqrt(p*(p-a)*(p-b)*(p-c))

4,奇数幻方问题(这个问题出现在吉大推荐的高级程序设计那本书上)

罗伯法的具体方法如下:
把1(或最小的数)放在第一行正中;
按以下规律排列剩下的n2-1个数:
1)每一个数放在前一个数的右上一格;
2)如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
3)如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;
4)如果这个数(例如6)所要放的格已经超出了顶行且超出了最右列那么就把它放在它的下一行同一列的格内;
5)如果这个数所要放的格已经有数填入,处理方法同4)。
package test1;

import java.util.Scanner;

//奇数阶幻方的实现
public class Practice {  

    //n为用户输入的n阶奇数幻方   n为奇数
    public static int[][] magicOdd(int n) {  
        //构造一个(n+2)*(n+2)矩阵
        int[][] square = new int[n + 1][n + 1];  
        int i = 0;  
        int j = (n + 1) / 2;  

        //从第一行的中间那个数字(是1)开始填幻方
        //n阶幻方一共有n*n个数字(从1~n*n)
        //奇数阶幻方的实现算法
        for (int key = 1; key <= n * n; key++) {  
            if ((key % n) == 1)  
                i++;  
            else {      // //填充当前数的右上角那个数
                i--;  
                j++;  
            }  
            if (i == 0)  {      判断条件:若是在(n+2)*(n+2)阶方阵的第一行
                i = n; 
            }
            if (j > n) {
                 j = 1;  
            }
            square[i][j] = key;  
        }  
        //对(n+2)*(n+2)阶的方阵进行筛选出中间的n*n阶幻方
        int[][] matrix = new int[n][n];  
        for (int k = 0; k < matrix.length; k++) {  
            for (int l = 0; l < matrix[0].length; l++) { 
                matrix[k][l] = square[k + 1][l + 1];  
            }  
        }  
        return matrix;  
    }  
    public static void main(String[] args) {  
        Scanner a=new Scanner(System.in);
        int b=a.nextInt();
        //b为用户输入的奇数
        System.out.println(); 
        int[][] magic = Practice.magicOdd(b); 
        for (int k = 0; k < magic.length; k++) {  
            for (int l = 0; l < magic[0].length; l++) { 
                System.out.print(magic[k][l] + "    ");  
            }  
            System.out.println();  
        }  
    }  
}  
原文:https://blog.csdn.net/wilson_m/article/details/78643202 

5,素数环(计学考过)

问题描述相邻两个整数之和均为素数,例如输入6,输出 1 4 3 2 5 6 最后一个数和第一个数和也为素数

void dfs(int cur){  //这是刘汝佳算法竞赛入门上的一道题目,应该好理解
    if(cur == n && isp(A[0]+A[n-1])){
        //递归边界
        for(int i = 0; i<n; i++)
            cout<<A[i]<<endl;
    }
    else
    for(int i = 1; i<=n; i++){
        if(!vis[i] && isp(i+A[cur-1])){
            A[cur] = i;    
            vis[i] = 1;   //标志已经访问过了
            dfs(cur+1);
            vis[i] = 0;  //还原访问标记
        }
    }
}

接下来是一些常见的简单题型

1,分解质因子

//递归
void prim(int m, int n){ //n从2开始
    if(m >= n){
        while(m % n)n++;
        m/=n;
        prim(m,n);
        stack[++top] = n;  //得到的倒序压入栈中
    }
}


//非递归
void main(){
    int i,n;
    cout<<"please input n";
    cin>>n;
    for(i = 2; i<n ;i++){
        while(n != i){
            if(n%i == 0){
                cout<<i;
                n/=i;
            }else
            break;
        }
    }
    cout<<n;
    return 0;
}

2,对一个n*n矩阵,通过行变换,使每行元素的平均值按递增排列

这里只列出核心算法


for(i = 0;i<n;i++){
    sum[i] = 0;  //初始化
    for(int j=0; j<n; j++)
        sum[i] = sum[i] + array[i][j];
}

for(int i = 0; i<n-1;i++){
    min = i;
    for(j = i+1;j<n;j++){
        if(sum[min] > sum[j])min = j;
    }
    if(i != min){ //将array的第i行和j行交换,以及sum[i] sum[j] 交换,用到了选择排序的思想
        for(k = 0;k<n; k++){
            temp = array[i][k];
            array[i][k] = array[min][k];
            array[min][k] = temp;
        }
    }
    temp = sum[i];
    sum[i] = sum[min];
    sum[min] = temp;
}

3,蛇形阵,形如这种
2019吉林大学计算机高级程序设计笔记_第1张图片
这是在网上随便找的一张图片,这是先往下走的,还有先往右走的情况

下面代码是先往右走的

void snake_number(int A[N][N], int n){
    
    int i =0,j=0,k=1;
    while(i<n && j<n){
        while(i<n && j>-1){
            A[i][j] = k++;  //右上->左下
            i++;j--;   
        }
        if(j<0 && i<n)j=0;   //j<0处理
        else{    //i=n  处理
            j = j+2;
            i = n-1;
        }
        while(i>-1 && j<n){ //左下->右上
            A[i][j] = k++;
            i--;j++;
        }
        if(i<0 && j<n)i=0;   //i<0处理
        else{     //j = n处理
            i = i+2;
            j = n-1;
        }
    }
}

下面是大整数问题

1,大整数加法

#include
#include
char line1[210],line2[210];
int num1[210],num2[210];
int i,j,len1,len2;
int main(){
    scanf("%s%s",line1,line2);
    len1 = strlen(line1);
    len2 = strlen(line2);
    
    for(i = len1-1,j=0; i>=0 ; i--,j++)
        num1[j] = line1[i]-'0';
    for(i = len2-1,j=0; i>=0 ; i--,j++)
        num2[j] = line2[i]-'0';
    len1 = max(len1,len2);
    for(i = 0; i<len1;i++){
        num1[i] += num2[i];
        num1[i+1] += num1[i]/10;
        num1[i] %= 10;
    }
    
    while(!num1[i] && i>=0)i--;
    if(i==-1) cout<<"0";
    else
        while(i>=0)cout<<num1[i--];
    return 0;
}

2,大整数减法

#include
#include
char line1[210],line2[210];
int num1[210],num2[210];
int i,j,len1,len2;
int main(){
    scanf("%s%s",line1,line2);
    len1 = strlen(line1);
    len2 = strlen(line2);
    
    for(i = len1-1,j=0; i>=0 ; i--,j++)
        num1[j] = line1[i]-'0';
    for(i = len2-1,j=0; i>=0 ; i--,j++)
        num2[j] = line2[i]-'0';
    int len = 1;
    while(len<=len1 || len<=len2){
        if(num1[len] >= num2[len])
            num3[len] = num1[len]- num2[len];
        else{
            num3[len] = 10 + num1[len] - num2[len];
            num1[len+1] -=1
        }
        len++;
    }
    
    while(!num3[i] && len>=0)len--;
    if(len==-1) cout<<"0";
    else
        while(len>=0)cout<<num3[len--];
    return 0;
}

3,大整数乘法

前面的和上面是一样的,这里不再赘述


for(int i = 0;i<len1;i++){
    for(int j = 0;j<len2;j++){
        ans[i+j] += num1[i] * num2[j];
    }
}
for(int i = 0;i<len1+len2;i++){
    if(ans[i] >= 10){
        ans[i+1] += ans1[i]/10;
        ans[i] %= 10;
    }
}
index = len1 + len2;

此处更新,博主上岸了,大家加油!!

2019吉林大学计算机高级程序设计笔记_第2张图片
传送门 吉大数据结构笔记

你可能感兴趣的:(算法以及数据结构)