异常处理
产生过程当程序运行时,可能会产生异常,当cpu检测到这些时间发生时,就会通过异常表跳转到异常处理程序,然后进行处理。
异常表示常驻于内存中的,每个异常都有一个异常号,事件发送的是异常号,之后根据异常号找到异常表中的对应项再跳转过去。异常表的首地址存放在一个特殊的寄存器中。
当一场处理结束之后,可能会跳转到下一条语句,可能跳转到当前语句,也可能终止程序。
要注意,这里讲的异常是系统提供的异常,要把用户程序中设定的异常区分开。
类别中断中断是用来和外部设备进行交互的,例如网卡,usb和磁盘。
每当这些设备有操作完成时,都会发给cpu一个信号叫cpu去取数据(cpu上有一个特殊的引脚专门去接受这些数据)。之后cpu就会执行中断程序然后去取数据。
一个显著的例子就是scanf,cpu不可能一到scanf就停止运行,肯定还要继续做各种各样的事。他只是调用了scanf函数给标准输入发出信号,有数据来了就告诉我。之后标准输入输入完成之后并不是直接存到内存中,而是先存到一个缓存中(例如键盘有usb缓存),然后告诉cpu要读数据,cpu才会执行中断去读数据。
执行中断程序之前,首先要把所有寄存器的值都保 ...
java 内部类
内部类就是在类的内部又定义一个类。
实例内部类实例内部类就是没有static修饰的内部类。他有以下几点需要注意
在创建内部类的实例时,外部类必须已经创立。例如:
Outer.InnerTool tool = new Outer().newInnerTool();这个语句相当于
Outer outer = new Outer();
Outer.InnerTool Tool = outer.new InnerTool();
内部类也是在外部类的内部,可以访问外部类的任何级别的成员方法和成员变量。这是因为想要创建内部类,首先要创建外部类,这个时候可以看成内部类有外部类的引用。
一个外部类可以对应多个内部类,一个内部类对应一个外部类。外部类不能直接访问内部类的成员,必须要通过实例去访问。例如
public class A{ public class B { private int b1 = 1; public int b2 = 2; class C(); } public void te ...
java 泛型
发展过程由父类转给子类时允许的,但是会抛出ClassCastException。这种异常是运行时异常,编译期不会检查,这就加大了检查的难度。为了解决这个问题,从jdk5开始引入了泛型。泛型可以把ClassCastException转换成编译时类型不兼容错误。
泛型符号是<>,里面可以使任意一种类(不能是int等基础类型,可以是Integer).
例如: Set<Object> set = new HashSet<Object>();//实例中的类型必须要和前面相同
泛型类,数组,接口,方法泛型类
例:
public class Bag<T>{ private T content; public Bag(T content) { this.content = content; } public T get() { return this.content; } public void set(T conten ...
埃氏筛
在筛质数时,我们会发现,筛去2后,2的倍数4、6、8等一定不是素数;筛去3后,3的倍数6、9、12等一定不是倍数。简单模拟这个过程如下const int MAXN = 1000000; void Prime() { for (int i=0; i<MAXN; i++) prime[i]=1; //先把每个数都定义为质数 prime[0]=prime[1]=0; for (int i=2; i<MAXN; i++) { if (!prime[i]) continue; for (int j=i*2; j<MAXN; j+=i) prime[j] = 0; //将i的倍数标记为合数 } }
线性筛
埃氏筛中有重复,例如6,2与3都筛了一次,效率低线性筛定理,(口语不准确)一个数i乘以小于等于它的最小素因数的素数所得到的合数之间没有重复 #define N 10000int flag[N+1],prime[N+1],pnum;/*flag[n] 表示n是否是素数,1是素数,0不是prime 中是所有的素数按从小到大排列、pnum 表示素数的个数*/void CreatePrime(){ pnum=0;//初始化没有素数 //先将所有数看做素数,然后开始筛选 for(int i=0; i<=N; i++){ flag[i]=1; } //遍历筛去所有最大因数是i的合数 for(int i=2; i<=N; i++){ if(flag[i]==1){ //把素数记录下来 p[pnum++]=i; } //遍历已知素数表中比i的最小素因数小的素数,并筛去合数 for(int j=0; j<pnum && p[j]*i<=N; j++){ //筛去合数 ...
java 数组
基础声明可以这样声明:
int[] scores;String[] names;
也可以这样声明int scores[];String names[];二维更为古怪int [][]x;int []x[];int x[][];
这里注意一点,声明时不能往括号中加东西,会报错。例如:int x[1];//报错
java中推荐吧括号放到前面,可能int[]也成了一个对象?
创建数组对象创建数组对象语法和c++中创建动态数组类似。
int[] scores = new int[100];
上面这个代码首先要在堆中分配空间,然后把里面的数据初始化。
括号中的数字可以使常量,也可以是变量,甚至可以是0(表示里面没有数据).
访问数组的元素和长度和c++一样,下标索引。如果越界,会抛出ArrayIndexOutOfBoundsException异常
所有数组都有length属性,表示数组的长度: public final length.
所以我们可以直接输出这一属性,例如:
int x[] = new int[40];System.out.println(x.length); //输出length
...
查找
静态查找顺序查找就是一个个找,过程不必多少。
如果查找每个元素概率相等,那么查找第n个元素只需要一次,第n-1需要两次…。所以平均查找次数是 1+2+…+n / n = (n+1)/2
折半查找其实就是二分查找,代码
分块查找分块查找就是每个找出每个块中最大的元素然后单独建一个表,之后就可以先查找这个表然后根据表来查找。大致意思就是这样,具体代码
动态查找二叉排序树(查找树)二叉查找树特点是左儿子都比父亲小,右儿子都比父亲大。
上面就不是二叉排序树,因为66比50还要大。
用链表进行存储。
struct node{ node *lchild; node *rchild; int val;}
二叉树的查找算法:
如果二叉树是空,那么直接返回
如果该节点的val正好是要查找的数,则查找成功
如果大,那么去右边找
如果小,去坐标找
插入
先要进行查找,如果查找不成功才会插入。
插入过程最好单独写一个函数,因为使用递归。如果要插入的点比当前点大,那么就去右边,反之就去左边。知道这个点是空为止,把要插入的点插入到这个空的点中。
删除
如果要删除的点是叶 ...
dw
dw即define word,定义字型数据。例如,dw 0123h,0456h,0789h.这样就定义了几个字型数据,那这些数据都在哪里呢,他们的段地址都是从cs开始的,而偏移地址从0开始,也就是说,0123h的偏移地址是0,0456h的偏移地址是2,0789h的偏移地址是6。
但是这样会带来一个问题,因为前十六个字节是dw所定义的字型数据,所以这样可能使程序的入口出现问题,所以可以assume cs:codesgcodesg segmentdw 0123h,0456h,0789hstart: mov bx,0mov ax,0mov cx,8s: add ax,cs:[bx]add bx,2loop smov ax,4c00hint 21hcodesg endsend start
这里就是加上了一个标号start,这个标号的意思就是确定程序的入口,而最后在end这里还要来一个start,因为end的作用除了确定程序在哪里终止之外,还有一个作用是告诉编译器程序在哪里开始(因为这时一个伪指令)
快速排序
步骤:1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
例 6 1 2 7 9 3 4 5 10 8 进行排序 1 以6为基准数,先从右边找比6小的数,我们用一个变量j一步步向左移动,好在移动三次后我 们找到了5,j为7。现在再让另一个变量i向右移动去找比6大的数,当i为3时找到了7.现在再让5 和7互换,得到了6 1 2 5 9 3 4 7 10 8,。在让j向左移动,找到了4,i向右找到了9,再让两个数 互换,j再向左到3,此时i向左也到3,两者相遇,便让3和6互换,第一次结束 (想想原因) 2 现在分为两部分,左边全比6小,右边全比6大,为3 1 2 5 4 6 9 7 10 8 再在3 1 2 5 4 中用同样的方法搜索一次得到2 1 3 5 4,再在2 1 中搜索得到1 2 然后在5 4 中搜索得到4 5,左边排序完成,右边用同样的方法排序就可得到答案
不说了,上代码
void sort(int a[],int l,int r) { if ...
二分搜索
(主要是怕自己忘记了) 一个要点,用二分时要先排序
int erfen(int arr[],int key,int n) { int low=0,high=n-1; while(low<=high) { int mid=(low+high)/2; if(arr[mid]<key) { low=mid+1; } if(arr[mid]==key) { return mid; } if(arr[mid]>key) { high=mid-1; } } return -mid-1; }