浙大数据结构第三周初识二叉树

news2025/4/25 23:37:13

03-树1 树的同构 (25分)

给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。

现给定两棵树,请你判断它们是否是同构的。

输入格式:

输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:

如果两棵树是同构的,输出“Yes”,否则输出“No”。

输入样例1(对应图1):

8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -
8
G - 4
B 7 6
F - -
A 5 1
H - -
C 0 -
D - -
E 2 -

输出样例1:

Yes

输入样例2(对应图2):

8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4

输出样例2:

No

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

主要思路:

先要理解这句话:对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点

这句话的意思是:第i行节点编号是i,但建树时可不一定按0~n-1从左到右从上到下来建,而要根据节点关系来

难点主要分为两大部分:

(一)建树:

用一个大数组来建树,大数组的下标i对应节点i,在过程中找到根节点,扫描树时利用根节点先序遍历

(1)先初始化大数组,将每个节点存储的character设置为EMPTY,状态设施为true

(2)再遍历输入,其中处理后面子节点有讲究,应该先按字符读取,然后在判断,如果是数字,就改为数字后存入节点,否则说明子节点为空,并将子节点状态定义为false

(3)遍历大数组,其中节点character不为EMPTY且状态不为false的就是根节点

(二)判断:递归三部曲:

(1)参数和返回值

参数:两棵树各自根节点;返回值:以当前根节点是否满足题意

(2)结束条件:

遍历到空节点

(3)遍历顺序:

前序遍历,其中的单层递归逻辑:先判断当前两个根节点是否相等,在看各自左孩子与各自右孩子是否相等,如果相等直接分别递归,如果不相等,就将第一棵子树左孩子传入下一层递归与第二棵子树右孩子比较;第一棵子树右孩子传入下一层递归与第二棵子树左孩子比较

第一次写错误:

(1)建树时不仅要如果左右孩子是空,不仅要将左右孩子地址设置为NO,左右孩子存储的character也要设置为EMPTY

代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX 20
#define NO -1
#define EMPTY '|'
typedef struct {
    char character;
    int leftAddress;
    int rightAddress;
    int id;
}Node;
Node tree1[MAX], tree2[MAX];
int nodeNum1, nodeNum2;
int buildTree(Node* tree, int* nodeNum) {
    scanf("%d", nodeNum);
    getchar();    //读取换行符
    for(int i = 0; i < MAX; i++) {    //初始化即将存储数的数组
        tree[i].id = true;    //先将每个节点的状态都定义为true,即假设都是根节点
        tree[i].character = EMPTY;    //将每节点存储字符位置都定义为EMPTY
    }
    
    for(int i = 0; i < *nodeNum; i++) {
        char tmpLeft, tmpRight;
        scanf("%c %c %c", &tree[i].character, &tmpLeft, &tmpRight);
        //按字符-空格-字符-空格-字符读取
        getchar();
        if(tmpLeft >= '0' && tmpLeft <= '9') {
            tree[i].leftAddress = tmpLeft - '0';
            // printf("left = %d\n", tree[i].leftAddress);
            int left = tree[i].leftAddress;
            tree[left].id = false;
        }
        else {
			tree[i].leftAddress = NO;
    		tree[tree[i].leftAddress].character = EMPTY;    	
		}
        
        if(tmpRight >= '0' && tmpRight <= '9') {
            tree[i].rightAddress = tmpRight - '0';
            int right = tree[i].rightAddress;
            tree[right].id = false;
        }
        else {
        	tree[i].rightAddress = NO;
        	tree[tree[i].rightAddress].character = EMPTY;
		}
    }
    // for(int i = 0; i < MAX; i++) {
    //     if(tree[i].character != EMPTY) {
    //         printf("%c %d %d %d\n", tree[i].character, tree[i].leftAddress, tree[i].rightAddress, tree[i].id);
    //     }
    // }
    // printf("-----------------\n");
    int root;
    for(int i = 0; i < MAX; i++) {
        if(tree[i].id && tree[i].character != EMPTY) {
            root = i;
            break;
        }
    }
    return root;
}
int depth = 0;
bool judge(int root1, int root2) {
//    printf("depth = %d\n", depth++);
//    printf("nodeNum1 = %d nodeNum2 = %d\n", nodeNum1, nodeNum2);
    if(nodeNum1 != nodeNum2) return false;
    if(nodeNum1 == 0 || nodeNum2 == 0) return true;
    char tree1cur = tree1[root1].character;
    char tree2cur = tree2[root2].character;
//    printf("tree1cur = %c tree2cur = %c\n", tree1cur, tree2cur);
    if(tree1cur == EMPTY && tree2cur == EMPTY) return true;
    
    char tree1LeftNode = tree1[tree1[root1].leftAddress].character;
    char tree1RightNode = tree1[tree1[root1].rightAddress].character;
    char tree2LeftNode = tree2[tree2[root2].leftAddress].character;
    char tree2RightNode = tree2[tree2[root2].rightAddress].character;
    bool leftSubtree;
    bool rightSubtree;
    if(tree1cur == tree2cur) {
//        printf("tree1LeftNode = %c ", tree1LeftNode);
//        printf("tree2LeftNode = %c\n", tree2LeftNode);
//        printf("tree1RightNode = %c ", tree1RightNode);
//        printf("tree2RightNode = %c\n", tree2RightNode);
//        printf("-----------------------\n");
        if(tree1LeftNode == tree2LeftNode && tree1RightNode == tree2RightNode) {
            leftSubtree = judge(tree1[root1].leftAddress, tree2[root2].leftAddress);
            if(!leftSubtree) return false;
            rightSubtree = judge(tree1[root1].rightAddress, tree2[root2].rightAddress);
            if(!rightSubtree) return false;
        }
        else {
            leftSubtree = judge(tree1[root1].rightAddress, tree2[root2].leftAddress);
            if(!leftSubtree) return false;
            rightSubtree = judge(tree1[root1].leftAddress, tree2[root2].rightAddress);
            if(!rightSubtree) return false;
        }
    	return true;
    }
    return false;
}
int main(void) {
    int root1 = buildTree(tree1, &nodeNum1);
    // printf("%d\n", root1);
    // printf("===================\n");
    int root2 = buildTree(tree2, &nodeNum2);
    // printf("%d\n", root2);
    if(judge(root1, root2)) printf("Yes");
    else printf("No");
    return 0;
}

补充:

(1)打印每次递归输出检查的时候要以第二棵二叉树进行前序遍历,因为第一棵已经交换过左右孩子了不太好看

如下是Example1的输出:

depth = 0
tree1cur = A tree2cur = A
tree1LeftNode = B tree2LeftNode = C
tree1RightNode = C tree2RightNode = B
-----------------------
depth = 1
tree1cur = C tree2cur = C
tree1LeftNode = G tree2LeftNode = G
tree1RightNode = | tree2RightNode = |
-----------------------
depth = 2
tree1cur = G tree2cur = G
tree1LeftNode = H tree2LeftNode = |
tree1RightNode = | tree2RightNode = H
-----------------------
depth = 3
tree1cur = | tree2cur = |	//从这里看第二棵二叉树就很明显,左子树遍历完了,在遍历右子树
depth = 4
tree1cur = H tree2cur = H
tree1LeftNode = | tree2LeftNode = |	
tree1RightNode = | tree2RightNode = |
-----------------------
depth = 5
tree1cur = | tree2cur = |
depth = 6
tree1cur = | tree2cur = |
depth = 7
tree1cur = | tree2cur = |
depth = 8
tree1cur = B tree2cur = B	//到这里可以看出根节点左子树遍历完开始遍历右子树了
tree1LeftNode = D tree2LeftNode = E
tree1RightNode = E tree2RightNode = D
-----------------------
depth = 9
tree1cur = E tree2cur = E
tree1LeftNode = F tree2LeftNode = F
tree1RightNode = | tree2RightNode = |
-----------------------
depth = 10
tree1cur = F tree2cur = F
tree1LeftNode = | tree2LeftNode = |
tree1RightNode = | tree2RightNode = |
-----------------------
depth = 11
tree1cur = | tree2cur = |
depth = 12
tree1cur = | tree2cur = |
depth = 13
tree1cur = | tree2cur = |
depth = 14
tree1cur = D tree2cur = D
tree1LeftNode = | tree2LeftNode = |
tree1RightNode = | tree2RightNode = |
-----------------------
depth = 15
tree1cur = | tree2cur = |
depth = 16
tree1cur = | tree2cur = |
Yes

题目详情:03-树2 List Leaves

Given a tree, you are supposed to list all the leaves in the order of top down, and left to right.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree -- and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a "-" will be put at the position. Any pair of children are separated by a space.

Output Specification:

For each test case, print in one line all the leaves' indices in the order of top down, and left to right. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.

Sample Input:

8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6

Sample Output:

4 1 5

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

简单翻译:

就是给一把二叉树节点,其中要按从左往右,从上往下顺序依次输出所有叶子节点

主要思路:

这题主要思路其实还好,也就是分为两部分,一部分是建树,与上一题一样,另一部分就是层序遍历,不过这里的队列数据结构是用c语言循环队列实现的,如果是特别要求逐层操作,往往考虑层序遍历,层序遍历顺序:

(1)从队列中取出一个元素

(2)访问该元素所指节点

(3)若该元素所指节点左右孩子非空,则将其左右孩子顺序入队

代码实现:

#include <stdio.h>
#include <stdbool.h>
#define MAX 11
#define EMPTY '|'
#define NO -1
#define MAX_QUEUE_SIZE 10
typedef struct {    //实现循环队列
    int data[MAX_QUEUE_SIZE];
    int front;
    int rear;
    int count;
} CircularQueue;

void initialize_queue(CircularQueue* queue) {
    queue->front = 0;
    queue->rear = -1;
    queue->count = 0;
}

int is_full(CircularQueue* queue) {
    return (queue->count == MAX_QUEUE_SIZE);
}

int is_empty(CircularQueue* queue) {
    return (queue->count == 0);
}

int enqueue(CircularQueue* queue, int data) {
    if(is_full(queue)) {
        return 0;
    }
    queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;
    queue->data[queue->rear] = data;
    queue->count++;
    return 1;
}

int dequeue(CircularQueue* queue) {
    if(is_empty(queue)) {
        return -1;
    }
    int data = queue->data[queue->front];
    queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
    queue->count--;
    return data;
}
/*----------------------------------------------------------*/
int count = 0;
typedef struct {
    int leftChild;
    int rightChild;
    bool isRoot;
}Node;
Node tree[MAX];
int buildTree() {
    for(int i = 0; i < MAX; i++) {
        tree[i].isRoot = true;
    }
    int nodeNum;
    scanf("%d", &nodeNum);
    getchar();
    for(int i = 0; i < nodeNum; i++) {
        char tmpLeft, tmpRight;
        scanf("%c %c", &tmpLeft, &tmpRight);
        getchar();
        if(tmpLeft >= '0' && tmpLeft <= '9') {
            tree[i].leftChild = tmpLeft - '0';
            tree[tree[i].leftChild].isRoot = false;
        } else {
            tree[i].leftChild = NO;
        }
        if(tmpRight >= '0' && tmpRight <= '9') {
            tree[i].rightChild = tmpRight - '0';
            tree[tree[i].rightChild].isRoot = false;
        } else {
            tree[i].rightChild = NO;
        }
        if(tree[i].leftChild == NO && tree[i].rightChild == NO) count++;
    }
    int root = 0;
    for(int i = 0; i < nodeNum; i++) {
        if(tree[i].isRoot) {
            root = i;
            break;
        }
    }
    return root;
}

void printLeave(int root) {
    if(root < 0) return;
    CircularQueue myQueue;
    initialize_queue(&myQueue);

    enqueue(&myQueue, root);
    while(!is_empty(&myQueue)) {
        int head = dequeue(&myQueue);
        // printf("head = %d ", head);
        // printf("leftChild = %d ", tree[head].leftChild);
        // printf("rightChild = %d\n", tree[head].rightChild);
        // printf("----------------------\n");
        if(tree[head].leftChild < 0 && tree[head].rightChild < 0) {
            count--;
            if(count) printf("%d ", head);
            else printf("%d", head);
        }
        if(tree[head].leftChild >= 0) enqueue(&myQueue, tree[head].leftChild);
        if(tree[head].rightChild >= 0) enqueue(&myQueue, tree[head].rightChild);
    }
}
int main() {
    int root = buildTree();
    //printf("%d", root);
    int depthOrder = 1;
    printLeave(root);
    return 0;
}

补充:c语言实现循环队列

(1)实现循环队列原因:

一般队列会出现假溢出

(2)实现循环队列难点:

如何判断当前队列空还是满:

方法一:增设一个变量

方法二:少用一个元素空间

(3)代码实现:

#include <stdio.h>
#include <stdlib.h>

#define MAX_QUEUE_SIZE 10

typedef struct {
    int data[MAX_QUEUE_SIZE];
    int front;
    int rear;
    int count;
} CircularQueue;

void initialize_queue(CircularQueue* queue) {
    queue->front = 0;
    queue->rear = -1;
    queue->count = 0;
}

int is_full(CircularQueue* queue) {
    return (queue->count == MAX_QUEUE_SIZE);
}

int is_empty(CircularQueue* queue) {
    return (queue->count == 0);
}

int enqueue(CircularQueue* queue, int data) {
    if(is_full(queue)) {
        return 0;
    }
    queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;    //因为是循环,所以不是简单加1,还要取余
    queue->data[queue->rear] = data;
    (queue->count)++;
    return 1;
}

int dequeue(CircularQueue* queue) {
    if(is_empty(queue)) {
        return -1;
    }
    int data = queue->data[queue->front];
    queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
    queue->count--;
    return data;
}

int main() {
    CircularQueue queue;
    initialize_queue(&queue);

    enqueue(&queue, 10);
    enqueue(&queue, 20);
    enqueue(&queue, 30);
    enqueue(&queue, 40);
    enqueue(&queue, 50);

    printf("Queue elements: ");
    while(!is_empty(&queue)) {
        printf("%d ", dequeue(&queue));
    }

    return 0;
}

03-树3 Tree Traversals Again

An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.


Figure 1

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: "Push X" where X is the index of the node being pushed onto the stack; or "Pop" meaning to pop one node from the stack.

Output Specification:

For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop

Sample Output:

3 4 2 6 5 1

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

 

简单翻译:

给出一棵树按一定规律给出的节点顺序,要求复建这棵树并且输出这棵树的后序遍历结果

主要思路:

关键一点在于发现题干中给出的push顺序就是原二叉树的前序遍历结果,pop出的顺序就是原二叉树的中序遍历结果

代码实现:(目前这个代码还有点小问题,不知道是切割字符串时有问题还是哪……)

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define EMPTY '|'
#define maxNodeNum 100
/*-------构造循环队列数据结构-----------*/
#define MAX_QUEUE_SIZE 100
typedef struct {
    int data[MAX_QUEUE_SIZE];
    int front;
    int rear;
    int count;
} CircularQueue;

void initialize_queue(CircularQueue* queue) {
    queue->front = 0;
    queue->rear = -1;
    queue->count = 0;
}

int queue_is_full(CircularQueue* queue) {
    return (queue->count == MAX_QUEUE_SIZE);
}

int queue_is_empty(CircularQueue* queue) {
    return (queue->count == 0);
}

int enqueue(CircularQueue* queue, int data) {
    if(queue_is_full(queue)) {
        return 0;
    }
    queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;
    queue->data[queue->rear] = data;
    queue->count++;
    return 1;
}

int dequeue(CircularQueue* queue) {
    if(queue_is_empty(queue)) {
        return -1;
    }
    int data = queue->data[queue->front];
    queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
    queue->count--;
    return data;
}
/*----------------构造循环队列数据结构-------------*/

/*----------构造栈数据结构---------------*/
#define MAX_STACK_SIZE 100
typedef struct {
    int data[MAX_STACK_SIZE];
    int top;
} Stack;

void initialize_stack(Stack* stack) {
    stack->top = -1;
}

bool stack_is_full(Stack* stack) {
    return (stack->top == MAX_STACK_SIZE - 1);
}

bool stack_is_empty(Stack* stack) {
    return (stack->top == -1);
}

bool stack_push(Stack* stack, int data) {
    if (stack_is_full(stack)) {
        return false;
    }
    stack->data[++stack->top] = data;
    return true;
}

int stack_pop(Stack* stack) {
    if (stack_is_empty(stack)) {
        return -1;
    }
    return stack->data[stack->top--];
}

int stack_peek(Stack* stack) {
    if (stack_is_empty(stack)) {
        return -1;
    }
    return stack->data[stack->top];
}
/*-----------构造栈数据结构-----------------*/
int inOrderTraversal[maxNodeNum];
int preOrderTraversal[maxNodeNum];
int inOrderTraversalIndex = 0;
int preOrderTraversalIndex = 0;
int nodeNum;
void buildTwoTraversal() {
    Stack tmpStack;
    initialize_stack(&tmpStack);
    for(int i = 0; i < 2 * nodeNum; i++) {
        char line[7];
        for(int j = 0; j < 7; j++) line[j] = EMPTY;
        char ch;
        int j = 0;
        if(i < 2 * nodeNum - 1) {    //这里比较麻烦的原因是给的输入里最后一行没有换行符
            while((ch = getchar()) != '\n') {
                line[j++] = ch;
            }
        } else if(i == 2 * nodeNum - 1) {
            scanf("%7s", line);
        }
        if(line[5] >= '0' && line[5] <= '9') {
            stack_push(&tmpStack, line[5] - '0');
            preOrderTraversal[preOrderTraversalIndex++] = line[5] - '0';
        } else {
            int topStack = stack_pop(&tmpStack);
            inOrderTraversal[inOrderTraversalIndex++] = topStack;
        }
    }
    // printf("preOrderTraversal = ");
    // for(int k = 0; k < nodeNum; k++) {
    //     printf("%d ", preOrderTraversal[k]);
    // }
    // putchar('\n');
    // printf("------------------\n");
    // printf("inOrderTraversal = ");
    // for(int k = 0; k < nodeNum; k++) {
    //     printf("%d ", inOrderTraversal[k]);
    // }
    return;
}
CircularQueue retqueue;
void postOrder(int preStart, int preEnd, int inStart, int inEnd) {
//    printf("preStart = %d preEnd = %d\n", preStart, preEnd);
//    printf("inStart = %d inEnd = %d\n", inStart, inEnd);
//	printf("----------------------------\n");
	int preLen = preEnd - preStart + 1;
	int inLen = inEnd - inStart + 1;
	if(preLen < 1 || inLen < 1) return;
	if(preStart < 0 || preEnd < 0 || inStart < 0 || inEnd < 0) return;
	if(preStart >= nodeNum || preEnd >= nodeNum || inStart >= nodeNum || inEnd >= nodeNum) return;
    if(preStart == preEnd) {
        enqueue(&retqueue, preOrderTraversal[preStart]);
        return;
    }
    

    int root = preOrderTraversal[preStart];
    int cuttingLine;
    for(int i = 0; i < nodeNum; i++) {
        if(inOrderTraversal[i] == root) {
            cuttingLine = i;
            break;
        }
    }
    int leftInStart = inStart;
    int leftInEnd = cuttingLine - 1;
    int leftSubTreeLength = leftInEnd - leftInStart + 1;
    int leftPreStart = preStart + 1;
    int leftPreEnd = leftPreStart + leftSubTreeLength - 1;
    int rightPreStart = leftPreEnd + 1;
    int rightPreEnd = preEnd;
    int rightInStart = cuttingLine + 1;
    int rightInEnd = inEnd;
//    printf("cuttline = %d\n", cuttingLine);
//	printf("leftPreStart = %d leftPreEnd = %d leftInStart = %d leftInEnd = %d\n", leftPreStart, leftPreEnd, leftInStart, leftInEnd);
//	printf("rightPreStart = %d rightPreEnd = %d rightInStart = %d rightInEnd = %d\n", rightPreStart, rightPreEnd, rightInStart, rightInEnd);
//    printf("==============================================\n");
	postOrder(leftPreStart, leftPreEnd, leftInStart, leftInEnd);    //遍历左子树
    postOrder(rightPreStart, rightPreEnd, rightInStart, rightInEnd);    //遍历右子树
    enqueue(&retqueue, root);
}
int main() {
    scanf("%d", &nodeNum);
    getchar();
    buildTwoTraversal();
    initialize_queue(&retqueue);
    postOrder(0, nodeNum - 1, 0, nodeNum - 1);
    while(!queue_is_empty(&retqueue)) {
        printf("%d", dequeue(&retqueue));
        if(nodeNum-- > 1) printf(" ");
    }
    return 0;
}

补充:c语言实现堆栈 :

/*----------构造栈数据结构---------------*/
#define MAX_STACK_SIZE 30
typedef struct {
    int data[MAX_STACK_SIZE];
    int top;
} Stack;

void initialize_stack(Stack* stack) {
    stack->top = -1;
}

bool stack_is_full(Stack* stack) {
    return (stack->top == MAX_STACK_SIZE - 1);
}

bool stack_is_empty(Stack* stack) {
    return (stack->top == -1);
}

bool stack_push(Stack* stack, int data) {
    if (stack_is_full(stack)) {
        return false;
    }
    stack->data[++stack->top] = data;
    return true;
}

int stack_pop(Stack* stack) {
    if (stack_is_empty(stack)) {
        return -1;
    }
    return stack->data[stack->top--];
}

int stack_peek(Stack* stack) {
    if (stack_is_empty(stack)) {
        return -1;
    }
    return stack->data[stack->top]; 
}
/*-----------完成构造栈数据结构-----------------*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/472670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[2023.4.28]知识体系脑图

整理下工作5年来的知识体系脑图&#xff1a;

Vulnhub:DerpNStink 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.130 信息收集 端口扫描 nmap -A -v -sV -T5 -p- --scripthttp-enum 192.168.111.130 通过nmap的http-enum脚本发现目标80端口存在wordpress&#xff0c;访问目标网站的wordpress被重定向到http://derpnstink.…

政务智能办体验升级、乳腺癌创新药加速研发,飞桨和文心大模型驱动应用智能涌现...

4月27日&#xff0c;百度“飞桨中国行”落地上海&#xff0c;围绕“如何运用深度学习平台大模型技术打造壁垒快速破局”主题&#xff0c;飞桨携手区域企业、高校院所、硬件厂商、开发者等生态伙伴共话 AI 技术新动向和产业升级新趋势&#xff0c;助力上海夯实具有国际影响力的人…

设计模式 -- 状态模式

前言 月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂) 央是一片海洋,海乃百川,代表着一块海绵(吸纳万物) 泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出) 月央泽,学习的一种过程,从白纸->吸收各种知识->不断输入输出变成自己的内容 希望大家一起坚持这个过程,也同…

系统集成项目管理工程师 笔记(第11章:项目人力资源管理)

文章目录 项目人力资源管理 过程11.2.1 编制项目人力资源计划的工具与技术 375&#xff08;1&#xff09;层次结构图&#xff08;工作、组织、资源 分解结构&#xff09;&#xff08;2&#xff09;矩阵图&#xff08;责任分配矩阵&#xff0c;RAM&#xff09;&#xff08;3&…

KubeSphere 社区双周报 | 杭州站 Meetup 议题征集中 | 2023.04.14-04.27

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2023.04.14-2023.…

开源+实时+数据即服务的架构——唐建法受邀出席2023数据技术嘉年华【干货回顾】

点击报名 假设原料是一个产品公司的 SaaS 业务系统、一套 CRM、一套工单系统、一个内部人事系统&#xff0c;和内部研发管理系统&#xff1b;现在给到你 40min 的时间&#xff0c;能做出怎样的数据菜肴&#xff1f; 如果这里的厨师是 Tapdata&#xff0c;那么答案可以是一个实时…

【Python】实战:生成多层嵌套笛卡尔积组合问卷 csv《感知觉与沟通评估表》

目录 一、适用场景 二、业务需求 &#xff08;1&#xff09;原产品需求 &#xff08;2&#xff09;需求分析 ① 需求漏洞 ②「0 能力完好」分级标准问题答案组合 ③「1 轻度受损」分级标准问题答案组合 ④「2 中度受损」分级标准问题答案组合 ⑤「3 重度受损」…

Superset安装部署(docker版)

为什么选择使用docker部署superset呢&#xff1f;因为Linux的python环境版本太低&#xff0c;而且一般是不能动系统自带的python环境&#xff0c;大部分都是通过conda或docker的形式创建一个新的python环境 安装yum工具集 yum -y install yum-utils添加docker源至镜像源中 y…

利用chatgpt+低代码技术搭建进销存系统

1 前言 在当今数字化时代&#xff0c;企业管理系统已经成为各行各业不可或缺的一部分。而进销存系统更是企业管理中的重要组成部分&#xff0c;它可以帮助企业实现产品库存管理、采购管理、销售管理等多个方面的自动化管理。 然而&#xff0c;搭建一个高质量的进销存系统需要…

Fiddler抓包工具常见功能介绍,还不会的进来看

目录 Fiddler的功能面板 一、Statistics数据统计面板&#xff0c;性能分析 二、Inspectors查看请求与响应 三、Filters过滤器 1、User Filters启用 2、Action 3、过滤器实际应用 四、AutoResponder请求重定向 1、什么是请求重定向&#xff1f; 2、为什么要用这个功能&…

如何搭建信息存储中心?资源共享方案之搭建ftp个人服务器

serveru是一款由Rob Beckers开发的ftp服务器软件&#xff0c;全称为&#xff1a;serv-u ftp server&#xff0c;它功能强大又易于使用。ftp服务器用户通过ftp协议能在internet上共享文件。FTP协议是专门针对在两个系统之间传输大的文件开发出来的&#xff0c;它是TCP/IP协议的一…

(下)苹果有开源,但又怎样呢?

一开始&#xff0c;因为 MacOS X &#xff0c;苹果与 FreeBSD 过往从密&#xff0c;不仅挖来 FreeBSD 创始人 Jordan Hubbard&#xff0c;更是在此基础上开源了 Darwin。但是&#xff0c;苹果并没有给予 Darwin 太多关注&#xff0c;作为苹果的首个开源项目&#xff0c;它算不上…

【Unity-UGUI控件全面解析】| Canvas 画布组件详解

🎬UGUI控件全面解析 | Canvas 画布组件详解一、组件介绍1.1 绘制元素的顺序二、组件属性面板2.1 Canvas :画布,控制UI的渲染模式2.2 Canvas Scaler:画布缩放器,控制UI画布的放大缩放的比例2.3 Graphic Raycaster:图形射线投射器,控制是否让UI响应射线点击三、代码操作组…

快递账单管理线上化教程

对一家现代化企业来说&#xff0c;快递账单管理怎么做&#xff0c;才能高效不出错&#xff1f;到企业的快递账单管理&#xff0c;其实是伴随着快递行业的发展而改变方式的。 最早的时候&#xff0c;企业快递账单管理&#xff0c;更多的其实是底单管理&#xff0c;早期寄快递&am…

RSA算法仿真模拟

一.密码学 密码学中常见的加密方式可以分为两类&#xff1a;对称加密和非对称加密。 对称加密&#xff1a;对称加密采用相同的密钥来进行加密和解密。因为加密和解密都使用同样的密钥&#xff0c;所以对称加密速度快、效率高&#xff0c;但在密钥管理方面存在困难。常见的对称…

MySQL 精选 35 道面试题大厂稳了(含答案)

MySQL 精选 35 道面试题 1.说一下 MySQL 执行一条查询语句的内部执行过程&#xff1f;2.MySQL 查询缓存有什么优缺点&#xff1f;3.MySQL 的常用引擎都有哪些&#xff1f;4.常用的存储引擎 InnoDB 和 MyISAM 有什么区别&#xff1f;5.什么叫回表查询&#xff1f;6.如果把一个 I…

Grid.js - 跨框架的前端表格插件

只想简简单单画个表格&#xff0c;但 React&#xff0c;Vue&#xff0c;Angular&#xff0c;…&#xff0c;这么多前端框架&#xff0c;各自都有不同的表格渲染库。就没有表格库能“一次画表&#xff0c;到处运行”吗&#xff1f;来看看 Grid.js 这个跨框架的前端表格插件吧&am…

[2021.11.9]lighteffect架构优化详细设计文档

1 lighteffect系统架构图 图1-1 整改前lighteffect系统架构图 上图为整改前lighteffect系统架构图&#xff0c;存在的问题如下&#xff1a; (1)代码bug 原因&#xff1a;由于系统中兼容了lighteffect和lighteffect2&#xff0c;写代码时只记了一个&#xff0c;出现代码bug。…

springboot服务端接口外网远程调试,并实现HTTP服务监听【内网穿透】

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…