目录:


01. Week01 - Lec02 - Revision and setting the scene

  • C语言除法只有一个符号,与 Python 不同,如果想要得到 float 类型,首先变量需要为 float,另外就是 除数 或者 被除数 之一是 float 类型
    如果变量为 int,则自动获取整数部分,不管 除数 与 被除数 是否为 float

    1. float a = 10.0/3, a = 3.333333
    2. int a = 10.0/3, a = 3
  • Array 可以通过下面方式声明
    1. int fac[20]; //对于每个元素具体赋值
    2. int v[5] = {1, 2, 3, 4, 5}; //直接赋值的话,需要加上大括号
  • 字符数组需要保留最后为'\0'
    1. char s[6] = {'h', 'e', 'l', 'l', 'o'};
    2. char t[6] = "hello";
  • 数组作为函数参数的时候,同时需要加入数组的长度
    1. int sumArray(int harry[], int length) {...}
    2. or
    3. int sumArray(int *harry, int length) {...}

    其中 Harry[] 与 *harry 可以达到一样的效果

  • 二维数组可以看成数组的数组
    1. m[2][3] 包含2个元素,每个元素都有一个包含3个元素的数组
    2. m[0] 包含 m[0][0], m[0][1], m[0][2],第1
    3. m[1] 包含 m[1][0], m[1][1], m[1][2],第2
    4. int m[2][3] = {{1, 2, 3}, {4, 5, 6}};

    m[3][2][4] 包含3个元素,其中每个元素一个2*4的数组
    分层,最外层3个元素,然后一层是2个元素,最里面是4个元素

    1. int m[3][2][4] = {{{1, 2, 3, 4}, {5, 6, 7, 8}},
    2. {{9, 10, 11, 12}, {13, 14, 15, 16}},
    3. {{17, 18, 19, 20}, {21, 22, 23, 24}}};
  • struct date {...};
    其中 struct date 本身是一个新的数据类型,因此定义新的变量需要这样:
    struct date birthday;
  • #define 用来定义常量
    typedef 用来将数据类型重命名
    注意,前面有符号的,后面没有分号,前面没有符号的,后面需要分号
    1. #define MAX 20
    2. typedef struct date Date;
    3. typedef float Real;
    4. typedef struct {
    5. int day, month, year;
    6. } Date;
    7. Date birthdays[MAX]; // an array of structs
  • 结构体访问
    1. structTypeName s, *sp;
    2. sp = &s;
    3. s.element
    4. (*sp).element
    5. sp->element
    1. int main(int argc, char *argv[])
    2. argc: number of arguments
    3. argv[]: allow access to arguments represented as strings
    4. atoi(Origin_string): string to number
    5. sscanf(Origin_string, "%d", &num): string to everything(num)

02. Week02 - Lec01 - Data structures - memory allocation

  • a char takes 1 byte (8 bits)
    an int takes 4 bytes (32 bits)
    a pointer takes 8 bytes (64 bits) (64 bit computers)
    sizeof structs
    组成 8 bytes,无法组成的就空缺,可以设想成 8 bytes 一个卡壳,而且按顺序放

    1. struct s1 {
    2. char c;
    3. int i;
    4. char *s;
    5. };

    其中 1 + 4 (+ 3) + 8 = 16

    1. struct s2 {
    2. char c;
    3. char *s;
    4. int i;
    5. };

    其中 1 (+ 7) + 8 + 4 (+4) = 24

03. Week02 - Lec02 - Input - Output

  • 3 main sources of input for programs:
    from the command line: argc, argv[]
    from standard input (also called stdin)
    stdin can be the keyboard, a data file, or the output of other program
    from an 'internally-defined' file
    open a file, use fscanf(), and don't forget to close the file
  • command line
    sscanf(argv[1], "%d", &num) != 1
    如果赋值成功的话,会返回赋值的个数,将字符串 argv[1] 转换为 数字 num
  • standard input (stdin)
    1. scanf("%d", &num) != 1
    2. or
    3. scanf("%d%d, &num1, &num2) != 2 //表示两个数字,中间可以间隔whitespace

    没有 string 参数,直接获取 stdin 的信息,或者是输入的,或者是文件
    pipe command: |, 将前一个输出当做后一个输入

    使用 getchar()
    一次获取一个字符,检测是否到达 '\n'

    1. char c = getchar();
    2. while (c != '\n') {...}
  • a user file
    fopen(), fscanf(), fclose()
  • stdout, stderr
    fprinf(stream, ...)
    stdin: scanf()
    stdout: printf()
  • scanf(): to read from stdin,只能读取 keyboard 或者 文件,与 printf 对应
    多个含有空格的字符,无线调用 scanf 可以读取数字
    sscanf(): to read from the command line,从字符串获取信息
    printf(): to write to stdout,只能输出到控制台 或者 文件
    fprintf(): to write to stderr

04. Week03 - Lec01 - ADTs

  • 实现 struct

    1. typedef struct point {
    2. float x;
    3. float y;
    4. } *Point;

    struct point 用来计算 malloc 中空间大小
    Point 以指针形式,可以直接修改地址对应的数据

    1. Point p;
    2. p = malloc(sizeof(struct point));
    3. p->x
    4. p->y
  • Stacks and queues
    stacks: Last in, first out
        通过数组实现,快速简单,不过要固定长度
        通过 linkedlist 实现,慢,不过可以灵活增加内存
        a postfix calculator
    queues: First in, first out
        ‘circular’ queue
    数组实现:
        stacks:尾部push,尾部pop
        queues:头部qush,尾部pop

05. Week03 - Lec02 - Dynamic memory allocation

  • 声明的变量放在 stack 里面
    malloc 的内存空间放在 heap 里面
  • For every malloc() there should be a corresponding free()
    when free'd, that heap space may be re-used by the system
    free(p);
    p = NULL;
  • When a program teminates, all memory the program uses is automatically freed.
    It is not dangerous to forget to free memory at the end of a program,
    but it's poor style. Sometimes it's dangerous.
  • Realloc
    If the space returned by a malloc() is too little, you can create more by calling realloc().
    1. char *p = malloc(SIZEINBYTES)
    2. .
    3. .
    4. char *pext = realloc(p, BIGGERSIZEINBYTES);
    5. .
    6. .

06. Week04 - Lec01 - LinkedLists

  • 与数组相比的优点:

    • 动态分配空间,可以是任意大小
    • 数组需要连续的空间,不好把控
    • 更容易删除节点
  • 与数组相比的缺点:声明:
    • 不能随机访问,数组可以
    • 只能连续访问,但是数组更快
    • 操作量更大
    • 每个元素都有一个额外的指针
  • Sedgwick
    1.  
    1. typedef struct node *Link;
    2. struct node{
    3. int data;
    4. Link next;
    5. }

    Albert

    1.  
    1. typedef struct node {
    2. int data;
    3. struct node *next;
    4. } List;
    1.  
  • 通过 LinkedList 来实现 Quack
    • push:将 node 放在 head 之后,就是最前面
    • qush:需要找到最后一个节点,然后直接连接上
    • pop:Quack qs,qs 不能是 NULL,不能使 Empty, 删除第一个 node 并且释放
    • destroyQuack:释放出 head 之外的所有节点
    • makeEmptyQuack:pop 掉所有节点
    • isEmptyQuack:是否头节点指向 NULL
    • showQuack:按顺序输出 data
  • Head nodeA linkedlist ADT interface
    • 创建出来的
    • 存储的是 dummy data,最大值,没意义
    • 不能被删除,不是 linkedlist 信息内容
    • 如果 quack 为空,指向 NULL
    • 如果 quack 不为空,指向 top node
    • 返回 head node 给 client
       
  • typedef struct node *List;
    ...
    因此 interface 里面可以用到 List
  • A linkedlist ADT
    1. struct node {
    2. int data;
    3. struct node *Next;
    4. };
    5. ...

    因此 ADT 里面可以用访问结构体内部信息

07. Week06 - Lec01 - Heaps

  • heap memory

    • a programmer can request heap memory by using malloc()
    • the memory is 'returned' to the heap by using free()
  • heap data structure
    • higher-level than array and linked list

      • a heap data structrue is built on an array, or linked list
    • two-dimensional because it forms a tree of data
      • a binary tree (at most 2 children per node)
  • Max-heaps
    • the element with the largest key is at the root
    • the children of a node have keys smaller than the parent
  • Min-heaps
    • the element with the smallest key is at the root
    • the children of a node have keys larger than the parent
  • 2 properties
    • HOP (Heap-Order Property): 子节点的值比父节点小或者大
    • CTP (Complete-Tree Property): 完全二叉树,可以保证子节点与父节点的位置是2倍关系
    • heaps 用来实现 priority queues,使用在最短路径算法
  • Heap Implementation
    • 根节点索引值为 1
    • 给定节点索引 i:
      • 它的左节点是 2i
      • 它的右节点是 2i + 1
      • 它的父节点是 i/2(使用整数结果)
  • Operation on heaps
    • Get the maximum element

      • 根节点,位置 1
    • Insert an element
      • 把新要素放到最下面最右边的位置,放在数组的最后
      • fixUp:随着单一路径向根部传递,按照 Heap-Order Property
    • Delete the maximum element
      • delMax 大根堆
      • delMin 小根堆
      • 删除叶子节点,可以直接操作
      • 删除根节点
        • 删除root,将最后的元素替换掉,并将其删除,然后
        • fixDown from the root (Heap-Order Property)
        • return the saved root node
      • fixDown:随着单一路径从根部向叶子节点传递

08. Week06 - Lec02 - Priority Queues and Heap Sort

  • A priority queue supports 2 abstract operations:

    • insert: a new item (push, qush)
    • delMax (pop)
  • A Priority Queue ADT
    • insertPQ:通过 fixUp,构建大根堆
    • delMaxPQ:删掉第一个值,然后执行 fixDown
  • Three implementations of the PQ ADT
    • an unordered array

        1. struct pqRep {
        2. int nItems; // actual count of Items
        3. int *items; // array of Items
        4. int maxsize; // maximum size of array
        5. };
      • 插入数据,放置在最后
      • 删除最大值,通过遍历来获取
    • an ordered array
      • 插入数据,查找数据按照顺序的位置,然后将后面的数据逐个后移,将数据插入
      • 删除最大值,就是最后一个元素
    • a heapified array
      • 插入数据,调用 fixUp,将数据进行排序
      • 删除最大值,删除一个元素,最后一个元素补入,通过 fixDown 操作

09. Week07 - Lec01 - Graphs

  • Complete graph

    • 任何两点都有相连的边
    • |E| = V(V-1)/2 (排列组合里面 V 个顶点,里面随机选取 2 个的可能性)
  • Clique
    • a complete subgraph
    • a subset of vertices that form a complete graph
  • Sparseness/denseness of a gragh
    • dense graphs: |E| is closer to V(V-1)/2
    • sparse graphs: |E| is closer to V (minimum is V-1)
  • Tree
    • a connected (sub)graph with no cycles
  • Spanning Tree
    • a tree that contains all vertices in the graph (可以是所有孤立的点,只删除 edges,点集不变)
    • 包含所有 graph 中顶点的 tree,例如 最小生成树
  • Terminology
    • graph;顶点集与边集
    • subgraph:顶点集与边集都是 上面graph 的子集
    • induced subgraph:导出子图,顶点集是子集(只删除顶点的子集,相连的边会自动删除)
      ref: https://www.youtube.com/watch?v=dPHkyRvLtIU
    • cycle:首尾相接
    • connected graph:连接所有顶点的路径
    • adjacency:两个相连接的顶点
    • degree:一个顶点与其相连的顶点个数
  • Hamiltonian path and cycle
    • 每个顶点只访问一次,path
    • 如果首尾相接,cycle(所有顶点的degree >= n/2)
  • Eulerian path and cycle
    总结:
    • 遍历每条边正好一次,path(恰好只有2个顶点有奇数的degree)
    • 如果收尾相接,cycle(所有的顶点都是偶数的degree)
    • 两者都不是:看奇数degree顶点个数,如果1个或者大于2个,都是没有的
  • 1. 不可能同时有欧拉path或者cycle
    2. 有Hamiltonian cycle一定有path
    3. 判断H 回路 的方法就是所有顶点的度都≥n/2
    4. 判断欧拉path:只有两个是奇数的度
    5. 判断欧拉cycle:所有都为偶数的度
  • 其他
    • Undirected Graphs

      • edge(u, v) = edge(v, u)
      • no self-loops (i.e. no edge(v, v))
    • Directed Graphs
      • edge(u, v) ≠ edge(v, u)
      • can have self-loops (i.e. edge(v, v))
    • Weighted Graphs
      • 有权值的
      • road map
    • Multi-graph
      • 两个顶点间可以拥有多条边相连
      • 去一个地方的不同方式,线路等
  • Implementing Graphs
    • Vertex that is represented by an int
    • Edge that is represented by 2 vertices
    • Graph that is represented by an Adjacency matrix, or as an Adjacency list.
    • building:
              create a graph
              create an edge
              add an edge to a graph
          deleting
              remove an edge from a graph
              remove and free a graph
          printing
              'show' a graph
    • Edge
      1.  
      1. typedef int Vertex; // define a VERTEX
      2.  
      3. typedef struct { // define an EDGE
      4. Vertex v;
      5. Vertex w;
      6. } Edge;
  • GraphAM.c: based on an Adjacency Matrix
      1.  
      1. struct graphRep {
      2. int nV; // #vertices
      3. int nE; // #edges
      4. int **edges; // matrix of Booleans ... THIS IS THE ADJACENCY MATRIX
      5. };
  • GraphAL.c: based on an Adjacency Linked List
      1.  
      1. typedef struct node *List;
      2. struct node {
      3. Vertex name;
      4. List next;
      5. };
      6.  
      7. struct graphRep {
      8. int nV; // #vertices
      9. int nE; // #edges
      10. List *edges; // array of linked lists ... THIS IS THE ADJACENCY LIST
      11. };
      1.  
    • insertEdge: 两个顶点都要加,并且是插入到头部的位置
  • Reading a graph
    • scanf("%d", &v) != EOF,说明没有读取到文件结尾
    • scanf("%d", &v) != '\n',说明没有读取到换行符
    • scanf 会自动跳过空格、制表符或者回车
      1.  
      1. int readNumV(void) { // returns the number of vertices numV or -1
      2. int numV;
      3. char w[WHITESPACE];
      4. scanf("%[ \t\n]s", w); // skip leading whitespace
      5. if ((getchar() != '#') ||
      6. (scanf("%d", &numV) != 1)) {
      7. fprintf(stderr, "missing number (of vertices)\n");
      8. return -1;
      9. }
      10. return numV;
      11. }
      1.  
      1. int readGraph(int numV, Graph g) { // reads number-number pairs until EOF
      2. int success = true; // returns true if no error
      3. int v1, v2;
      4. while (scanf("%d %d", &v1, &v2) != EOF && success) {
      5. if (v1 < 0 || v1 >= numV || v2 < 0 || v2 >= numV) {
      6. fprintf(stderr, "unable to read edge\n");
      7. success = false;
      8. }
      9. else {
      10. insertEdge(newEdge(v1, v2), g);
      11. }
      12. }
      13. return success;
      14. }

10. Week07 - Lec02 - Graph search

  • Depth-first search (BFS)

    • stack
      1.  
      1. //HANDLES CONNECTED GRAPHS ONLY
      2. void dfsQuack(Graph g, Vertex v, int numV) {
      3. int *visited = mallocArray(numV);
      4. Quack s = createQuack();
      5. push(v, s);
      6. showQuack(s);
      7. int order = 0;
      8. while (!isEmptyQuack(s)) {
      9. v = pop(s);
      10. if (visited[v] == UNVISITED) { // we visit only unvisited vertices
      11. printArray("Visited: ", visited, numV);
      12. visited[v] = order++;
      13. for (Vertex w = numV - 1; w >= 0; w--) { //push adjacent vertices
      14. if (isEdge(newEdge(v,w), g)) { // ... in reverse order
      15. push (w, s); // ... onto the stack
      16. }
      17. }
      18. }
      19. showQuack(s);
      20. }
      21. printArray("Visited: ", visited, numV);
      22. free(visited);
      23. return;
      24. }
      1.  
  • dfsQuack() (disconnected graphs)
    • 设置一个参数 allVis,判断是否全部顶点都访问了
      1.  
      1. //HANDLES CONNECTED GRAPHS ONLY
      2. void dfsQuack(Graph g, Vertex v, int numV) {
      3. int *visited = mallocArray(numV);
      4. Quack s = createQuack();
      5. push(v, s);
      6. showQuack(s);
      7. int order = 0;
      8. while (!isEmptyQuack(s)) {
      9. v = pop(s);
      10. if (visited[v] == UNVISITED) { // we visit only unvisited vertices
      11. printArray("Visited: ", visited, numV);
      12. visited[v] = order++;
      13. for (Vertex w = numV - 1; w >= 0; w--) { //push adjacent vertices
      14. if (isEdge(newEdge(v,w), g)) { // ... in reverse order
      15. push (w, s); // ... onto the stack
      16. }
      17. }
      18. }
      19. showQuack(s);
      20. }
      21. printArray("Visited: ", visited, numV);
      22. free(visited);
      23. return;
      24. }
      1.  
  • Recursive Depth-First Search
    • 包含了 disconnected graphs 的情况,另外函数内部加入指针,可以改变地址同时相当于全局变量
      1.  
      1. void dfs(Graph g, Vertex rootv, int numV) {//'wrapper' for recursive dfs
      2. int *visited = mallocArray(numV); // ... handles disconnected graphs
      3. int order = 0;
      4. Vertex startv = rootv; // this is the starting vertex
      5. int allVis = 0; // assume not all visited
      6. while (!allVis) { // as long as there are vertices
      7. dfsR(g, startv, numV, &order, visited);
      8. allVis = 1; // are all visited now?
      9. for (Vertex w = 0; w < numV && allVis; w++) { // look for more
      10. if (visited[w] == UNVISITED) {
      11. printf("Graph is disconnected\n"); // debug
      12. allVis = 0; // found an unvisited vertex
      13. startv = w; // next loop dfsR this vertex
      14. }
      15. }
      16. }
      17. printArray("Visited: ", visited, numV);
      18. free(visited);
      19. return;
      20. }
      21.  
      22. void dfsR(Graph g, Vertex v, int numV, int *order, int *visited) {
      23. visited[v] = *order; // records the order of visit
      24. *order = *order+1;
      25. for (Vertex w = 0; w < numV; w++) {
      26. if (isEdge(newEdge(v,w), g) && visited[w]==UNVISITED) {
      27. dfsR(g, w, numV, order, visited);
      28. }
      29. }
      30. return;
      31. }
      1.  
  • Breadth First Search
    • queue
      1.  
      1. void bfsQuack(Graph g, Vertex v, int numV) { //name change
      2. int *visited = mallocArray(numV);
      3. Quack q = createQuack();
      4. qush(v, q); //qush, not push
      5. showQuack(q);
      6. int order = 0;
      7. while (!isEmptyQuack(q)) {
      8. v = pop(q);
      9. if (visited[v] == UNVISITED) {
      10. printf("Visit %d\n", v); // debug
      11. visited[v] = order++;
      12. for (Vertex w = 0; w < numV; w++) {//vertex order
      13. if (isEdge(newEdge(v,w), g)) {
      14. qush(w, q); //qush, not push
      15. }
      16. }
      17. }
      18. showQuack(q);
      19. }
      20. printArray("Visited: ", visited, numV);
      21. free(visited);
      22. makeEmptyQuack(q);
      23. return;
      24. }
      1.  

11. Week08 - Lec02 - Applications of Graph Search

  • Breadth-First Search: Shortest path

    • ref: https://www.cnblogs.com/alex-bn-lee/p/11242024.html#A42
      1.  
      1. void shortestPath(Graph g, Vertex start, Vertex goal, int numV) {
      2. int *visited = mallocArray(numV);
      3. int *parent = mallocArray(numV); // THIS IS NEW
      4.  
      5. Quack q = createQuack();
      6. qush(start, q);
      7. int order = 0;
      8. visited[start] = order++;
      9. int found = 0;
      10. while (!isEmptyQuack(q) && !found) { // FOUND TELLS US TO STOP
      11. Vertex v = pop(q);
      12. for (Vertex w = 0; w < numV && !found; w++) {
      13. if (isEdge(newEdge(v,w), g)) { // for adjacent vertex w ...
      14. if (visited[w] == UNVISITED) { // ... if w is unvisited ...
      15. qush(w, q); // ... queue w
      16. printf("Doing edge %d-%d\n", v, w); // DEBUG
      17. visited[w] = order++; // w is now visited
      18. parent[w] = v; // w's PARENT is v
      19. if (w == goal) { // if w is the goal ...
      20. found = 1; // ..FOUND IT! NOW GET OUT
      21. }
      22. }
      23. }
      24. }
      25. }
      26. if (found) {
      27. printf("SHORTEST path from %d to %d is ", start, goal);
      28. printPath(parent, numV, goal); // print path from START TO GOAL
      29. putchar('\n');
      30. }
      31. else {
      32. printf("no path found\n");
      33. }
      34. printArray("Visited: ", visited, numV); // debug
      35. printArray("Parent : ", parent, numV); // debug
      36. free(visited);
      37. free(parent);
      38. makeEmptyQuack(q);
      39. return;
      40. }
      1.  
      1. // head recursion
      2. void printPath(int parent[], int numV, Vertex v) {
      3. if (parent[v] != UNVISITED) { // parent of start is UNVISITED
      4. if (0 <= v && v < numV) {
      5. printPath(parent, numV, parent[v]);
      6. printf("-->");
      7. }
      8. else {
      9. fprintf(stderr, "\nprintPath: invalid goal %d\n", v);
      10. }
      11. }
      12. printf("%d", v); // the last call will print here first
      13. return;
      14. }
      1.  
      1. void printPath(int parent[], int numV, Vertex v) {
      2. printf("%d", v);
      3. if (0<=v && v<numV) {
      4. Vertex p = parent[v];
      5. while (p != UNVISITED) {
      6. printf("<--%d", p);
      7. p = parent[p];
      8. }
      9. }
      10. else {
      11. fprintf(stderr, "printPath: illegal vertex in parent[]\n");
      12. }
      13. }

       
  • Depth-First Search: Cycle detection
    • ref: https://www.cnblogs.com/alex-bn-lee/p/11242024.html#A43
      1.  
      1. // a wrapper for the recursive call to hasCycle()
      2. void searchForCycle(Graph g, int v, int numV) {
      3. int *visited = mallocArray(numV);
      4. int order = 0;
      5.  
      6. if (hasCycle(g, numV, v, v, &order, visited)) {
      7. printf("found a cycle\n");
      8. }
      9. else {
      10. printf("no cycle found\n");
      11. }
      12. printArray("Visited ", visited, numV);
      13. free(visited);
      14. return;
      15. }
      16.  
      17. int hasCycle(Graph g, int numV, Vertex fromv, Vertex v, int *order, int *visited) {
      18. int retval = 0;
      19. visited[v] = *order;
      20. *order = *order+1;
      21. for (Vertex w = 0; w < numV && !retval; w++) {
      22. if (isEdge(newEdge(v,w), g)) {
      23. if (visited[w] == UNVISITED) {
      24. printf("traverse edge %d-%d\n", v, w);
      25. retval = hasCycle(g, numV, v, w, order, visited);
      26. }
      27. else {
      28. if (w != fromv) { // exclude the vertex we've just come from
      29. // WE HAVE REVISITED A VERTEX ==> CYCLE
      30.  
      31. printf("traverse edge %d-%d\n", v, w);
      32. retval = 1;
      33. }
      34. }
      35. }
      36. }
      37. return retval;
      38. }
      1.  
  • Depth-First Search: Eulerian cycles
    • https://www.cnblogs.com/alex-bn-lee/p/11242024.html#A44
      1.  
      1. void findEulerianCycle(Graph g, int numV, Vertex startv) {
      2. Quack s = createQuack();
      3. printf("Eulerian cycle: ");
      4.  
      5. push(startv, s);
      6. while (!isEmptyQuack(s)) {
      7. Vertex v = pop(s); // pop and then ...
      8. push(v, s); // ... push back on, so no change
      9. Vertex w = getAdjacent(g, numV, v); // get largest adj. v
      10. if (w >= 0) { // if true, there is an adj. vertex
      11. push(w, s); // push this vertex onto stack
      12. removeEdge(newEdge(v, w), g); // remove edge to vertex
      13. }
      14. else { // top v on stack has no adj. vertices
      15. w = pop(s);
      16. printf("%d ", w);
      17. }
      18. }
      19. putchar('\n');
      20. }
      21.  
      22. Vertex getAdjacent(Graph g, int numV, Vertex v) {
      23. Vertex retv = -1; // assume no adj. vertices
      24. for (Vertex w = numV-1; w >= 0 && retv == -1; w--) {
      25. if (isEdge(newEdge(v, w), g)) {
      26. retv = w; // found largest adj. vertex
      27. }
      28. }
      29. return retv;
      30. }
  • Depth-First Search: Finding a path
    • https://www.cnblogs.com/alex-bn-lee/p/11242024.html#A45
      1. void dfsR(Graph g, Vertex v, int numV, int *order, int *visited) {
      2. visited[v] = *order;
      3. *order = *order+1;
      4. for (Vertex w = 0; w < numV; w++) {
      5. if (isEdge(newEdge(v,w), g) && visited[w]==UNVISITED) {
      6. dfsR(g, w, numV, order, visited);
      7. }
      8. }
      9. return;
      10. }
      11.  
      12. int isPath(Graph g, Vertex v, Vertex goalv, int numV, int *order, int *visited) {
      13. int found = 0;
      14. visited[v] = *order;
      15. *order = *order+1;
      16. if (v == goalv) {
      17. found = 1;
      18. }
      19. else {
      20. for (Vertex w = 0; w < numV && !found; w++) {
      21. if (isEdge(newEdge(v,w), g)) {
      22. if (visited[w] == UNVISITED) {
      23. found = isPath(g, w, goalv, numV, order, visited);
      24. printf("path %d-%d\n", w, v);
      25. }
      26. }
      27. }
      28. }
      29. return found;
      30. }

12. Week09 - Lec01 - Weighted Graph Algorithms

13. Week09 - Lec02 - Binary Search Trees

  • Height:具体根节点的高度,root 为 0
  • Node level or depth:跟 Height 差不多
  • Types of trees
    • ordered tree: 有序树
    • binary tree: 二叉树
    • full binary tree: 满二叉树,每个节点都有2个孩子,可能参差不齐
    • perfect binary tree: 完美二叉树,类似三角形那种,都铺满了
    • ordered binary tree:有序二叉树,也叫做 binary search tree,二叉搜索树
      • left subtree values <= parent value
      • right subtree values >= parent value
    • full m-ary tree: 类似满二叉树
  • Binary Trees
    • balanced:尽量满,最短的
    • degenerate:退化的,一边倒,最长的
  • Height of a binary tree
    • 最长路径的长度
    • degenerate: height is n-1
    • balanced: height is ln(n)
  • Data structure for a binary tree
      1. typedef struct node *Tree;
      2. struct node {
      3. int data;
      4. Tree left;
      5. Tree right;
      6. };
  • Comparing Binary Search Trees and Heaps
  • Searching in BSTs

    • 结束条件就是 顶点 为 NULL,返回 0,或者查到了 v 值,返回 1
      1. int searchTree(Tree t, int v){ // Search for the node with value v
      2. int ret = 0;
      3. if (t != NULL) {
      4. if (v < t->data) {
      5. ret = searchTree(t->left, v);
      6. }
      7. else if (v > t->data) {
      8. ret = searchTree(t->right, v);
      9. }
      10. else { // v == t->data
      11. ret = 1;
      12. }
      13. }
      14. return ret;
      15. } // returns non-zero if found, zero otherwise
  • Creating a node in a BST

    • 构建结构体,建立数,结构体是一个 node 点,但是树是一个指针 Tree,连接着所有的点
    • 创建树,首先就是分配内存空间,然后就是赋值
      默认左右节点都为 NULL
      1. typedef struct node *Tree;
      2. struct node {
      3. int data;
      4. Tree left;
      5. Tree right;
      6. };
      7.  
      8. Tree createTree(int v) {
      9. Tree t;
      10. t = malloc(sizeof(struct node));
      11. if (t == NULL) {
      12. fprintf(stderr, "Out of memory\n");
      13. exit(1);
      14. }
      15. t->data = v;
      16. t->left = NULL;
      17. t->right = NULL;
      18. return t;
      19. }
  • Freeing a node in a BST
    • 结束条件就是遇到叶子节点,因为其左右节点均为 NULL  
      1. void freeTree(Tree t) { // free in postfix fashion
      2. if (t != NULL) {
      3. freeTree(t->left);
      4. freeTree(t->right);
      5. free(t);
      6. }
      7. return;
      8. }
  • Inserting a node in a BST
    • 重点是返回值是 Tree
      结束条件就是遇到叶子节点,因为其左右节点均为 NULL,因此会创建新的 node 点,然后将值依次返回
      由于返回值为 Tree,因此自动连接的起来  
      1. Tree insertTree(Tree t, int v) {
      2. if (t == NULL) {
      3. t = createTree(v);
      4. }
      5. else {
      6. if (v < t->data) {
      7. t->left = insertTree (t->left, v);
      8. }
      9. else {
      10. t->right = insertTree (t->right, v);
      11. }
      12. }
      13. return t;
      14. }
    • do it iteratively
    • 通过遍历找到对应的叶子节点,然后连接上 node
      1. Tree insertTreeI(Tree t, int v) { // An iterative version of the above
      2. if (t == NULL) {
      3. t = createTree(v);
      4. }
      5. else { // t != NULL
      6. Tree parent = NULL; // remember the parent to link in new child
      7. Tree step = t;
      8. while (step != NULL) { // this is the iteration
      9. parent = step;
      10. if (v < step->data) {
      11. step = step->left;
      12. }
      13. else {
      14. step = step->right;
      15. }
      16. } // step == NULL
      17. if (v < parent->data) {
      18. parent->left = createTree(v);
      19. }
      20. else {
      21. parent->right = createTree(v);
      22. }
      23. }
      24. return t;
      25. }
  • Printing the tree
    • 遍历打印,先左 再中 后右
      1. void printTree(Tree t) { // not the final version
      2. if (t != NULL) {
      3. printTree (t->left);
      4. printf ("%d ", t->data);
      5. printTree (t->right);
      6. }
      7. return;
      8. }
    • 2D printing
    • 每次递归,depth 自增,打印数据的时候,先将制表符打印出来,出现层次感
      1. void printTree(Tree t, int depth) { // extra depth parameter
      2. if (t != NULL) {
      3. depth++;
      4. printTree (t->left, depth);
      5. for (int i=1; i<depth; i++){ // 'depth'*whitespace
      6. putchar('\t');
      7. }
      8. printf ("%d\n", t->data); // node to print
      9. printTree (t->right, depth);
      10. }
      11. return;
      12. }
    • 反方向打印
      1. void printTree2(Tree t, int depth) {
      2. if (t != NULL) {
      3. depth++;
      4. printTree2 (t->right, depth);
      5. int i;
      6. for (i=1; i<depth; i++){
      7. putchar('\t');
      8. }
      9. printf ("%d\n", t->data);
      10. printTree2 (t->left, depth);
      11. }
      12. return;
      13. }
    • 效果如下:
      1. 1
      2. 2
      3. 3
      4. 4
      5. 5
      6. 6
      7. 7
      8. 8
      9. ====================================
      10. 8
      11. 7
      12. 6
      13. 5
      14. 4
      15. 3
      16. 2
      17. 1
  • Count the number of nodes in a BST
    • 遍历相加,每个节点为 1
      结束条件就是叶子节点,因为其左右节点均为 NULL,自动返回 1,然后不停回溯。。
      1. int count(Tree t){
      2. int countree = 0;
      3. if (t != NULL) {
      4. countree = 1 + count(t->left) + count(t->right);
      5. }
      6. return countree;
      7. }
  • Find the height of a BST
    • 对于叶子节点本身,高度为 0,因此 NULL 节点的高度就为 -1
      parent 节点的高度 = 1 + MAX (left height, right height)
      1. int max(int a, int b){
      2. if (a >= b) {
      3. return a;
      4. }
      5. return b;
      6. }
      7.  
      8. int height(Tree t){
      9. int heightree = -1;
      10. if (t != NULL){
      11. heightree = 1 + max(height(t->left), height(t->right));
      12. }
      13. return heightree;
      14. }
  • How balanced is a BST?
    How do the number of nodes in the left sub-tree and the right sub-tree compare?
    • 分别计算出左右子树的节点数,然后相减即可
      1. int balance (Tree t){ // calculates the difference between left and right
      2. int diff = 0;
      3.  
      4. if (t != NULL) {
      5. diff = count(t->left) - count(t->right); // count declared elsewhere
      6. if (diff < 0) {
      7. diff = diff;
      8. }
      9. }
      10. return diff;
      11. }
  • Deleting a node from a BST
    • 3 cases

      • node is a leaf: unlink node from parent
      • node has 1 child: replace the node by its child
      • node has 2 children: rearrange the tree in some way
        • DLMD: Deepest Left-Most Descendent
        • DRMD: Deepest Right-Most Descendent
    • 把 DLMD 摘下来,左边连接 t1,右边连接 t2
      DLMD 为最左,因此其次需要将其 parent 节点的 left 与 DLMD 的 right 相连
      p->left = nuroot->right
      注意需要保留 DLMD 的 parent 节点
      1. Tree deleteTree(Tree t, int i){ // delete node with value 'v'
      2. if (t != NULL) {
      3. if (v < t->data) {
      4. t->left = deleteTree(t->left, v);
      5. }
      6. else if (v > t->data) {
      7. t->right = deleteTree(t->right, v);
      8. }
      9. else { // v == t->data, so the node 't' must be deleted
      10. // next fragment of code violates style, just to make logic clear
      11. Tree n; // temporary
      12. if (t->left==NULL && t->right==NULL) n=NULL; // 0 children
      13. else if (t->left ==NULL) n=t->right; // 1 child
      14. else if (t->right==NULL) n=t->left; // 1 child
      15. else n=joinDLMD(t->left,t->right);
      16. free(t);
      17. t = n;
      18. }
      19. }
      20. return t;
      21. }
      1. // Joins t1 and t2 with the deepest left-most descendent of t2 as new root.
      2. Tree joinDLMD(Tree t1, Tree t2){
      3. Tree nuroot;
      4. if (t1 == NULL) { // actually should never happen
      5. nuroot = t2;
      6. }
      7. else if (t2 == NULL) { // actually should never happen
      8. nuroot = t1;
      9. }
      10. else { // find the DLMD of the right subtree t2
      11. Tree p = NULL;
      12. nuroot = t2;
      13. while (nuroot->left != NULL) {
      14. p = nuroot;
      15. nuroot = nuroot->left;
      16. } // nuroot is the DLMD, p is its parent
      17. if (p != NULL){
      18. p->left = nuroot->right; // give nuroot's only child to p
      19. nuroot->right = t2; // nuroot replaces deleted node
      20. }
      21. nuroot->left = t1; // nuroot replaces deleted node
      22. }
      23. return nuroot;
      24. }

14. Week10 - Lec01 - Splay Trees

  • Right rotation

    • its right child moves to the root's left child the root moves to its right child
    • 折下来,parent变成child
  • Left rotation
    • its left child moves to the root's right child the root moves to its left child
    • 翻上去,child变成parent
    • 相当于告诉了root,然后获取转折点,第一个是 E 是root,然后获取 C,同理。。
      然后就是连接起来即可
      1. // NOT REAL CODE: CHECKS REQUIRED: ACTUAL CODE BELOW
      2. Tree rotateR(Tree root) { // old root
      3. Tree newr = root->left; // newr is the new root
      4. root->left = newr->right; // old root has new root's right child
      5. newr->right = root; // new root has old root as right child
      6. return newr; // return the new root
      7. }
      8. // NOT REAL CODE: CHECKS REQUIRED: ACTUAL CODE BELOW
      9. Tree rotateL(Tree root) { // old root
      10. Tree newr = root->right; // newr will become the new root
      11. root->right = newr->left; // old root has new root's left child
      12. newr->left = root; // new root has old root as left child
      13. return newr; // return the new root
      14. }
  • root insertion
    • assume that we have just inserted node G in the BST below

      • rotate right the subtree with root the parent of G (i.e. H)

      • rotate right the subtree with root the parent of G (i.e. R)

      • rotate left the subtree with root the parent of G (i.e. E)

    • 一次只是转一次,保证 G 不停向上走
  • Counting the number of nodes in a subtree
      1. typedef struct node *Tree;
      2. struct node {
      3. int data;
      4. Tree left;
      5. Tree right;
      6. int count;
      7. };
      8.  
      9. Tree createTree(int v) {
      10. Tree t = malloc (sizeof(struct node));
      11. if (t == NULL) {
      12. fprintf(stderr, "Out of memory\n");
      13. exit(1);
      14. }
      15. t->data = v;
      16. t->left = NULL;
      17. t->right = NULL;
      18. t->count = 1;
      19. return t;
      20. }
      21.  
      22. int sizeTree(Tree t) {
      23. int retval = 0;
      24. if (t != NULL){
      25. retval = t->count;
      26. }
      27. return retval;
      28. }
      29.  
      30. Tree insertTree(Tree t, int v) {
      31. if (t == NULL) {
      32. t = createTree(v);
      33. }
      34. else {
      35. if (v < t->data) {
      36. t->left = insertTree (t->left, v);
      37. }
      38. else {
      39. t->right = insertTree (t->right, v);
      40. }
      41. t->count++; // update the counter at each ancestor
      42. }
      43. return t;
      44. }
  • Selecting the i-th element from a BST
    获取某一索引的节点值
    类似数组里面 arr[3] 的意思
    Balanced Trees
    • check the number of nodes in the left subtree

      • if the left subtree contains numOnLeft elements, and

        • numOnLeft>i, we recursively look in this left subtree for element i, else if
        • numOnLeft<i, we recursively look in the right subtree for element i-(numOnLeft+1), else if
        • numOnLeft=i, return with the current element's data
    • 如果在左子树直接递归
      如果在右子树,需要减掉所有左子树+root的节点数
      1. // For tree with n nodes – indexes are 0..n-1
      2. int selectTree(Tree t, int i) { // for tree with n nodes - indexed from 0..n-1
      3. int retval = 0;
      4. if (t != NULL) {
      5. int numOnLeft = 0; // this is if there is no left branch
      6. if (t->left != NULL) {
      7. numOnLeft = t->left->count; // this is if there is a left branch
      8. }
      9. if (numOnLeft > i) { // left subtree or ...
      10. retval = selectTree(t->left, i);
      11. }
      12. else if (numOnLeft < i) { // ... right subtree ?
      13. retval = selectTree(t->right, i-(numOnLeft+1));
      14. }
      15. else {
      16. retval = t->data; // value index i == numOnLeft
      17. }
      18. }
      19. else {
      20. printf("Index does not exist\n");
      21. retval = 0;
      22. }
      23. return retval;
      24. }
  • Approach 1: Global rebalancing
  • Rotating with a count
    • Example of left rotation

      • 算法与上面一致,只是增加了 count 的计算
        对于 E 的count就是等于前面 A 的count
        对于 A 的count就直接计算他的左右节点
        1. Tree rotateLeft(Tree t) { // Rotate left code: includes count field
        2. Tree retval = NULL;
        3. if (t != NULL) {
        4. Tree nuroot = t->right; // left rotate: hence right root-child will become new root
        5. if (nuroot == NULL) {
        6. retval = t;
        7. }
        8. else {
        9. t->right = nuroot->left; // the left child of nuroot becomes old root's right child
        10. nuroot->left = t; // nuroot's left child is the old root
        11. nuroot->count = t->count; // nuroot and old root have the same count
        12. t->count = 1 + sizeTree(t->left) + sizeTree(t->right); // recompute count in old root
        13. retval = nuroot; // return with the new root
        14. }
        15. }
        16. return retval;
        17. }
    • Example of right rotation
        1. Tree rotateRight(Tree t) { // Rotate right code: includes count field
        2. Tree retval = NULL;
        3. if (t != NULL) {
        4. Tree nuroot = t->left;
        5. if (nuroot == NULL) {
        6. retval = t;
        7. }
        8. else {
        9. t->left = nuroot->right;
        10. nuroot->right = t;
        11. nuroot->count = t->count;
        12. t->count = 1 + sizeTree(t->left) + sizeTree(t->right);
        13. retval = nuroot;
        14. }
        15. }
        16. return retval;
        17. }
  • Partitioning,分隔,分区
    • We can rewrite select() to partition around the ith element in the BST:

      • we descend recursively

        • to the ith element of each subtree

      • rotate-with-count that element in the opposite direction to its position

        • if it is a left child: do a right rotation

        • if it is a right child: do a left rotation

      • this will make the ith element the root of the BST

    • 将第 i 个元素作为 root
      不停的左右移动
      1. Tree partition(Tree t, int i) { // make node at index i the root
      2. Tree retval = NULL;
      3. if (t != NULL) {
      4. int numOnLeft = 0;
      5. if (t->left != NULL) {
      6. numOnLeft = t->left->count;
      7. }
      8. if (numOnLeft > i) {
      9. t->left = partition(t->left, i);
      10. t = rotateRight(t);
      11. }
      12. if (numOnLeft < i) {
      13. t->right = partition(t->right, i-(numOnLeft+1));
      14. t = rotateLeft(t);
      15. }
      16. retval = t;
      17. }
      18. else {
      19. printf("Index does not exist\n");
      20. retval = NULL;
      21. }
      22. return retval;
      23. }
  • Balancing the BST
    Approach 2: Local Rebalancing
    • Move the median node to the root by partitioning on i = count/2

      • balance the left sub-tree
      • balance the right sub-tree
    • 先把 median 移动到 root
      递归移动左右,最终所有的都是 median 在中间
      1. Tree balance(Tree t) {
      2. Tree retval = NULL;
      3. if (t != NULL) {
      4. if (t->count <= 1){
      5. retval = t;
      6. }
      7. else {
      8. t = partition(t, t->count/2);
      9. t->left = balance(t->left);
      10. t->right = balance(t->right);
      11. retval = t;
      12. }
      13. }
      14. return retval;
      15. }
  • Splaying an item to the top means to move an item to the root of the BST, using one of the operations:

    1. zigzag

    2. zigzig

  • zigzag operation (先下后上)

    • the item is the right child of the parent, which is a left child of the grandparent

      • do a rotate-left of the parent followed by a rotate-right of the grandparent
      • /                  
        \  先是左转parent 
         /
        /  然后再右转grandparent /\
    • the item is the left child of the parent, which is a right child of the grandparent

      • do a rotate-right of the parent followed by a rotate-left of the grandparent
      • \                 
        /  先是右转parent 
        \
          \  然后再左转grandparent /\
  • zigzig operation (先上后下)

    • the item is the left child of the parent, which is a left child of the grandparent

      • do a rotate-right of the grandparent followed by a rotate-right of the parent

      • (not a rotate-right of the parent followed by a rotate-right of the grandparent
      • /                                         
        /  先是右转grandparent  /\  然后再右转parent
        \
         \
    • the item is the right child of the parent, which is a right child of the grandparent

      • do a rotate-left of the grandparent followed by a rotate-left of the parent

      • (not a rotate-left of the parent followed by a rotate-left of the grandparent
      • \                                             
         \  先是左转grandparent  /\  然后再左转parent
         /
        /
  • Example
    • H is the right child of the left child so requires a zigzag splay

      • this is simply a left-rotate followed by a right-rotate
    • P is the left child of the right child so requires a zigzag splay

      • this is simply a right-rotate followed by a left-rotate
    • C is the left child of the left child so requires a zigzig splay

      • a zigzig splay does a right-rotate of the grandparent M, followed by another right-rotate of the parent E

    • T is the right child of the right child so requires a zigzig splay

      • a zigzig splay does a left-rotate of the grandparent M, followed by a left-rotate of the parent Q

    • The first double rotation below is not a zigzig rotation, the second is:
      区别在于,第一个图是 先下后上
      而 zigzig 是 先上后下

  • Operation splay-search
    • If we search for an item, and move the item to the root by using normal left and right rotations then there is no rebalancing

      • for example: a normal search for item 1 would result in
        每次移动一个节点,就是 1 不停向上移动

    • If we splay-search for an item, once found we

      • splay the item to the root
        1作为目标节点,整体是一个左左型,从grandparent右转,然后parent右转

    • If the item is not found

      • the last item (leaf) on the path is splayed to the root
    • For example, in the following splay tree we search for item 3, and because it fails, the 'last' item accessed, which is 4, is splayed:
      找3,结果找到了4,那就移动4,就是判断点是否为叶子节点,是的话就动

  • Operation splay-insertion
    • We have seen 2 types of BST insertion, leaf insertion and root insertion. Assume that we wish to insert the sequence of numbers 3, 2, 4, 5, 1.
    • leaf insertion

      • each node is simply added as a leaf
        按照 zigzig,zigzag 来操作
        分别 先上后下,先下后上

    • root insertion

      • each node is added as a leaf, and then
      • that leaf is promoted to the root position rotating the parent node to the left or right at each step
        就是一个一个移动到 root

  • Operation splay deletion
    • Normally, when an item is deleted in a BST, the node is simply replaced by its DLMD predecessor or DRMD successor.

      In splay-deletion, if you wish to delete a node y:

      • delete the node y as normal using either:

        • DRMD: if the predecessor of y is x, and the parent of x is p, then

          • follow the deletion by splaying p

        • DLMD: if the successor node of y is z, and the parent of z is p, then

          • follow the deletion by splaying p
            首先把 DLMD 替换 root,然后再将 DLMD 的 parent 移动到 root

      For example, let us splay-delete item 2 from the following splay tree

      we will use DLMD (DRMD would be similar)
      要删除2节点
      successor为4,4的父节点是5
      把4替换为2节点,作为root
      再把5移动上去

  • Minimum or maximum of a splay tree
    • search for the minimum or maximum item in a BST
    • splay the item to the root
    • For example, we show below a splay tree after

      1. a search for the minimum and then
      2. a search for the maximum item


  • in summary

    2-3-4 trees

    • We note that in each operation:

      • search for an item in a splay tree

        • the found item is splayed
        • if not found, the last accessed item is splayed
      • insertion of an item in a splay tree

        • the new item is splayed
      • deletion of an item in a splay tree

        • the parent of the item that replaces the deleted item is splayed
      • search for the minimum/maximum item in a splay tree

        • the found minimum/maximum is splayed

      A 'splay' of an item involves:

      • zigzig whenever the item is left-left or right-right

      • zigzag whenever the item is left-right or right-left

      • zig whenever the item is the child of the root (so a zigzag or zigzig is not possible)

      Splay Tree Analysis

      • number of comparisons per operation is O(log(n))

      • gives good (amortized) cost overall
      • no guarantee for any individual operation: worst-case behaviour may still be O(N)

      • remember, amortisation means averaging over a large number k operations

    • is self-balancing
    • is commonly used to implement dictionaries
    • has the property that all external nodes are at the same depth
    • generalises the concept of a node
      • 3 types of nodes:

        • 2nodes: 1 key, a left link to smaller nodes, a right link to larger nodes (this is the normal node)
          里面只有一个key就是一个字母,类似二叉树,因此只存在大小之分

        • 3nodes: 2 keys, a left link to smaller, a middle link to in-between, and right link to larger
          里面两个字母,小于,中间,大于三部分

        • 4nodes: 3 keys: links to the 4 ranges
          三个字母, M O S 分成四个部分

      • In the above example:

        • 'A' is an example of a 2node
        • 'LM' of a 3node
        • 'EGH' of a 4node

        Example of a search, for 'P':

        • start at the root 'I'
        • larger, go right to 'NR'
        • middle, go middle to 'P'

        Examples of insertions:

        • 'B': easy, change node 'A' into 'AB'
        • 'O': easy, change node 'NR' into 'NOR'
        • 'D': the node is full ??

        4node insertions

        • split the 4node分裂4度节点:

          • left key becomes a new 2node 左节点变成一个新的2度节点
          • middle key goes up to parent 中间节点上提到parent里面
          • right node becomes a new 2node 右节点变成一个新的2度节点
        • add new key to one of the new 2nodes, creating a 3node

        Example: insert 'D' in a 2-3-4 tree

        This insertion assumes that you can move the 'middle' key up to the parent.

        What happens if the parent is a 4node, and its parent is a 4node, and its parent ... ?

        Solution, during insertion, on the way down:

        • [A] transform 2node->4node into 3node->(2node+2node)

        • [B] transform 3node->4node into 4node->(2node+2node)

        • [C] if the root is a 4node, transform into 2node->(2node+2node)

        Example:

        Basic insertion strategy:

        • because of the transformations (splits) on inserts on the way down, we often end on a 2node or 3node, so easy to insert

        • insert at the bottom:
          • if 2node or 3node, simply include new key
          • if 4node, split the node
            4node需要将中间节点上调,上调后parent又需要上调,以此类推
            相当于递归了
            • if the parent is a 4node, this needs to be split

              • if the grandparent is a 4node, this needs to be split

                • ...

        Results:

        • trees are

          • split from the top down

          • (split and) grow from the bottom up

        • after insertions or deletions, 2-3-4 trees remain in perfect balance

        • What do you notice about these search trees?

        2-3-4 trees are actually implemented using BSTs!

【433】COMP9024 复习的更多相关文章

  1. iOS总结_UI层自我复习总结

    UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ...

  2. vuex复习方案

    这次复习vuex,发现官方vuex2.0的文档写得太简略了,有些看不懂了.然后看了看1.0的文档,感觉很不错.那以后需要复习的话,还是先看1.0的文档吧.

  3. 我的操作系统复习——I/O控制和系统调用

    上篇博客介绍了存储器管理的相关知识——我的操作系统复习——存储器管理,本篇讲设备管理中的I/O控制方式和操作系统中的系统调用. 一.I/O控制方式 I/O就是输入输出,I/O设备指的是输入输出设备和存 ...

  4. 复习(1)【Maven】

    终于开始复习旧知识了,有输入必然要有输出.输入和输出之间的内化过程尤为重要,在复习的同时,真正把学到的东西积淀下来,加深理解. Maven项目概念与配置 Maven是一个项目管理和综合工具.Maven ...

  5. 《CSS权威指南》基础复习+查漏补缺

    前几天被朋友问到几个CSS问题,讲道理么,接触CSS是从大一开始的,也算有3年半了,总是觉得自己对css算是熟悉的了.然而还是被几个问题弄的"一脸懵逼"... 然后又是刚入职新公司 ...

  6. JS复习--更新结束

    js复习-01---03 一 JS简介 1,文档对象模型 2,浏览器对象模型 二 在HTML中使用JS 1,在html中使用<script></script>标签 2,引入外部 ...

  7. jQuery 复习

    jQuery 复习 基础知识 1, window.onload $(function(){});   $(document).ready(function(){}); 只执行函数体重的最后一个方法,事 ...

  8. jQuery5~7章笔记 和 1~3章的复习笔记

    JQery-05 对表单和表格的操作及其的应用 JQery-06 jQuery和ajax的应用 JQery-07 jQuery插件的使用和写法 JQery-01-03 复习 之前手写的笔记.实在懒得再 ...

  9. HTML和CSS的复习总结

    HTML(Hypertext Markup Language)超文本标记语言:其核心就是各种标记!<html> HTML页面中的所有内容,都在该标签之内:它主要含<head>和 ...

随机推荐

  1. notepad++ 调整行间距

    在“设置”-“语言格式设置”里面,找到style里面的Line number margin一项,调整字体大小就可以调整左边标号的大小,然后文本内容的行间距即可任意调整.

  2. oracle中日期相关的区间

    and czrqb.lsrqb_rh_sj >= to_date('[?query_date_begin|2011-09-01?]A', 'yyyy-mm-dd') and czrqb.lsrq ...

  3. C#技巧与解析(部分)

    DesignMode 以下项目在设计器界面,需判断DesignMode OnPaint(e)/Form_Paint 自定义控件中需要特殊方法进行判断,如下: public partial class ...

  4. 语义(Semantics)

    流计算语义(Semantics)的定义 每一条记录被流计算系统处理了几次 有三种语义: 1.At most once 一条记录要么被处理一次,要么没有被处理 2.At least once 一条记录可 ...

  5. 4.3 axios

    axios全局拦截器:

  6. [React] Write a Custom React Effect Hook

    Similar to writing a custom State Hook, we’ll write our own Effect Hook called useStarWarsQuote, whi ...

  7. 【爬虫】大杀器——phantomJS+selenium

    [爬虫]大杀器——phantomJS+selenium 视频地址 江湖上有一个传说,得倚天屠龙者可称霸武林.爬虫中也有两个大杀器,他们结合在一起时,无往不利,不管你静态网站还是动态网站,通吃. pha ...

  8. Apache Kylin在4399大数据平台的应用

    来自:AI前线(微信号:ai-front),作者:林兴财,编辑:Natalie作者介绍:林兴财,毕业于厦门大学计算机科学与技术专业.有多年的嵌入式开发.系统运维经验,现就职于四三九九网络股份有限公司, ...

  9. mysql 8.0.17 安装配置方法图文教程

    1.URL:https://www.jb51.net/article/167782.htm 2.装好之后需要使用add user中的用户名和密码登录(之前安装数据库时出现的) 使用navicat连接时 ...

  10. windbg调试托管代码 .Net clr

    现在很多的程序都是多语言混合编程的,比如我司的产品,就是用C++/.net clr混合编制的.那么当我们调试这样的程序时,一定要注意,比如有时我们只看到c++的栈和名称,而.net clr的代码确看不 ...