数据结构作业三:双向链表与静态链表_双向静态链表 删除-程序员宅基地

技术标签: 链表  数据结构  

双向链表:

        双向链表也叫双链表,是链表的一种,它的每个数据 结点 中都有两个 指针 ,分别指向直接后继和直接前驱。 所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

 

一,结构体定义及宏

#include <stdio.h>
#include <malloc.h>

/**
 *  定义字符双向链表。
 */
typedef struct DoubleLinkNode{
    char data;
    struct DoubleLinkNode *previous;
    struct DoubleLinkNode *next;
} DLNode, *DLNodePtr;

二,初始化双向链表

/**
 * 初始化头节点。
 * @return 返回头节点的指针。
 */
DLNodePtr initLinkList(){
    DLNodePtr tempHeader = (DLNodePtr)malloc(sizeof(struct DoubleLinkNode));
    tempHeader->data = '\0';
    tempHeader->previous = NULL;
    tempHeader->next = NULL;
    return tempHeader;
}

三,打印双向链表

/**
 * 打印链表。
 * @param paraHeader 是链表的头结点。
 */
void printList(DLNodePtr paraHeader){
    DLNodePtr p = paraHeader->next;
    if(p == NULL){
        printf("The list is empty.");
    }
    while(p != NULL){
        printf("%c", p->data);
        p = p->next;
    }
    printf("\r\n");
}

四,在给定的位置插入元素

/**
 * 在给定的位置加入元素。
 * @param paraHeader 是链表的头结点。
 * @param paraChar 给定的char元素。
 * @param paraPosition 给定的位置。
 */
void insertElement(DLNodePtr paraHeader, char paraChar, int paraPosition){
    DLNodePtr p, q, r;

    // Step 1. 搜索给定的位置。
    p = paraHeader;
    for(int i = 0; i < paraPosition; i ++){
        p = p->next;
        if(p == NULL){
            printf("The position %d is beyond the scope of the list.", paraPosition);
            return;
        }
    }

    // Step 2. 创建一个新节点
    q = (DLNodePtr)malloc(sizeof(struct DoubleLinkNode));
    q->data = paraChar;

    // Step 3. 链接链表和节点。
    printf("linking\r\n");
    r = p->next;
    q->next = p->next;
    q->previous = p;
    p->next = q;
    if (r != NULL){
        r->previous = q;
    }
}

五,删除指定元素

/**
 * 删除链表中的元素。
 * @param paraHeader 是链表的头结点。
 * @param paraChar 给定的char元素。
 */
void deleteElement(DLNodePtr paraHeader, char paraChar){
    DLNodePtr p, q, r;
    p = paraHeader;

    // Step 1. 定位
    while((p->next != NULL) && (p->next->data != paraChar)){
        p = p->next;
    }

    // Step 2. 检查错误
    if(p->next == NULL){
        printf("The char %c does not exist.\r\n", paraChar);
        return;
    }

    // Step 3. 改变链接
    q = p->next;
    r = q->next;
    p->next = r;
    if(r != NULL){
        r->previous = p;
    }
    
    // Step 4. 释放内存
    free(q);
}

六,找到双向链表中特定数据的位置

 

/**
 * 找到双向链表中特定的数据的位置
 */
void locateElement(DLNodePtr paraHeader, char paraChar){
    DLNodePtr p;
    p = paraHeader;
	while(p->next != NULL){
        p = p->next;
        if(p->data == paraChar){
            printf("Found the char %c\r\n", paraChar);
            return;
        }
    }

    printf("The char %c is not been found.\r\n", paraChar);
	return ;
}

七,删除双向链表

void LinkDestory(DLNodePtr paraHeader){
    DLNodePtr p;
    p = paraHeader;
    p->next = NULL;
    printf("The list has been destoryed.\r\n");
    return;
}

八,函数功能测试

/**
 * 功能测试。
 */
void insertDeleteTest(){
    // Step 1. 初始化一个空链表。
    DLNodePtr tempList = initLinkList();
    printList(tempList);

    // Step 2. 加入一些字符。
    insertElement(tempList, 'H', 0);
    printList(tempList);
    insertElement(tempList, 'e', 1);
    printList(tempList);
	insertElement(tempList, 'l', 2);
    printList(tempList);
	insertElement(tempList, 'l', 3);
    printList(tempList);
	insertElement(tempList, 'o', 4);
    printList(tempList);
	insertElement(tempList, '!', 5);
	printList(tempList);

    // Step 3. 删除一些字符(第一次出现的)。
    deleteElement(tempList, 'e');
    printList(tempList);
	deleteElement(tempList, 'a');
    printList(tempList);
	deleteElement(tempList, 'o');
	printList(tempList);

    // Step 4. 在链表给定位置插入特定元素。
    insertElement(tempList, 'o', 1);//首位插入
    printList(tempList);
    insertElement(tempList, 'o', 5);//末位插入
    printList(tempList);
    insertElement(tempList, 'o', 3);//中间插入
    printList(tempList);

    // Step 5. 查找指定元素
    locateElement(tempList, 'H');
    locateElement(tempList, 'l');
    locateElement(tempList, 'o');
    locateElement(tempList, 'a');

    // Step 6. 清空链表
    LinkDestory(tempList);
    printList(tempList);
}

        在老师的基础上,加入了对插入功能的更进一步的测试,同时加入了更多的打印函数来更好地了解函数地运行规律,之后又加入了对locateElement函数地测试。

九,对于链表地址地测试

/**
 * 地址测试.
 */
void basicAddressTest(){
	DLNode tempNode1, tempNode2;

	tempNode1.data = 4;
	tempNode1.next = NULL;

	tempNode2.data = 6;
	tempNode2.next = NULL;

	printf("The first node: %d, %d, %d\r\n",
		&tempNode1, &tempNode1.data, &tempNode1.next);
	printf("The second node: %d, %d, %d\r\n",
		&tempNode2, &tempNode2.data, &tempNode2.next);

	tempNode1.next = &tempNode2;
}

十,程序入口

/**
 * 程序入口。
 */
int main(){
	insertDeleteTest();
	basicAddressTest();
}

十一,运行结果

The list is empty.
linking
H
linking
He
linking
Hel
linking
Hell
linking
Hello
linking
Hello!
Hllo!
The char a does not exist.
Hllo!
Hll!
linking
Holl!
linking
Holl!o
linking
Holol!o
Found the char H
Found the char l
Found the char o
The char a is not been found.
The list has been destoryed.
The list is empty.
The first node: 6421968, 6421968, 6421984
The second node: 6421936, 6421936, 6421952

静态链表

        静态链表,也是线性存储结构的一种,它兼顾了顺序表和链表的优点于一身,可以看做是顺序表和链表的升级版。

        使用静态链表存储数据,数据全部存储在数组中(和顺序表一样),但存储位置是随机的,数据之间"一对一"的逻辑关系通过一个整形变量(称为"游标",和指针功能类似)维持(和链表类似)。

        例如,使用静态链表存储 {1,2,3} 的过程如下:

        创建一个足够大的数组,假设大小为 6,如图一所示:


图 一 空数组


        接着,在将数据存放到数组中时,给各个数据元素配备一个整形变量,此变量用于指明各个元素的直接后继元素所在数组中的位置下标,如图 2 所示:


图 二 静态链表存储数据

        通常,静态链表会将第一个数据元素放到数组下标为 1 的位置(a[1])中。

        图 2 中,从 a[1] 存储的数据元素 1 开始,通过存储的游标变量 3,就可以在 a[3] 中找到元素 1 的直接后继元素 2;同样,通过元素 a[3] 存储的游标变量 5,可以在 a[5] 中找到元素 2 的直接后继元素 3,这样的循环过程直到某元素的游标变量为 0 截止(因为 a[0] 默认不存储数据元素)。

        类似图 2 这样,通过 "数组+游标" 的方式存储具有线性关系数据的存储结构就是静态链表。

一,结构体定义及宏

#include <stdio.h>
#include <malloc.h>

#define DEFAULT_SIZE 5

typedef struct StaticLinkedNode{
    char data;

    int next;
} *NodePtr;

typedef struct StaticLinkedList{
    NodePtr nodes;
    int* used;
} *ListPtr;

二,初始化静态链表

/**
 * 初始化头节点。
 * @return 返回头节点的指针。
 */
ListPtr initLinkedList(){
    // 指向整个链表空间的指针
    ListPtr tempPtr = (ListPtr)malloc(sizeof(struct StaticLinkedList));

    // 分配总空间
    tempPtr->nodes = (NodePtr)malloc(sizeof(struct StaticLinkedNode) * DEFAULT_SIZE);
	tempPtr->used = (int*)malloc(sizeof(int) * DEFAULT_SIZE);

    // 第一个节点是头结点
    tempPtr->nodes[0].data = '\0';
    tempPtr->nodes[0].next = -1;
    
    // 初始化时只有头结点使用
    tempPtr->used[0] = 1;
	for (int i = 1; i < DEFAULT_SIZE; i ++){
		tempPtr->used[i] = 0;
	}

	return tempPtr;
}

三,打印静态链表

/**
 * 打印链表。
 * @param paraHeader 是链表的头结点。
 */
void printList(ListPtr paraListPtr){
	int p = 0;
	while (p != -1) {
		printf("%c", paraListPtr->nodes[p].data);
		p = paraListPtr->nodes[p].next;
	}
	printf("\r\n");
}

四,在给定的位置插入元素

/**
 * 在给定的位置加入元素。
 * @param paraHeader 是链表的头结点。
 * @param paraChar 给定的char元素。
 * @param paraPosition 给定的位置。
 */
void insertElement(ListPtr paraListPtr, char paraChar, int paraPosition){
	int p, q, i;

	// Step 1. 搜索位置
	p = 0;
	for (i = 0; i < paraPosition; i ++) {
		p = paraListPtr->nodes[p].next;
		if (p == -1) {
			printf("The position %d is beyond the scope of the list.\r\n", paraPosition);
			return;
		}
	} 

	// Step 2. 创建一个新的节点
	for ( i; i < DEFAULT_SIZE; i ++){
		if (paraListPtr->used[i] == 0){
			printf("Space at %d allocated.\r\n", i);
			paraListPtr->used[i] = 1;
			q = i;
			break;
		}
	}
	if (i >= DEFAULT_SIZE){
		printf("No space.\r\n");
		return;
	}

	paraListPtr->nodes[q].data = paraChar;

	// Step 3. 链接节点
	printf("linking\r\n");
	paraListPtr->nodes[q].next = paraListPtr->nodes[p].next;
	paraListPtr->nodes[p].next = q;
}

五,删除指定元素

/**
 * 删除链表中的元素。
 * @param paraHeader 是链表的头结点。
 * @param paraChar 给定的char元素。
 */
void deleteElement(ListPtr paraListPtr, char paraChar){
	int p, q;
	p = 0;
	while ((paraListPtr->nodes[p].next != -1) && (paraListPtr->nodes[paraListPtr->nodes[p].next].data != paraChar)){
		p = paraListPtr->nodes[p].next;
	}

	if (paraListPtr->nodes[p].next == -1) {
		printf("Cannot delete %c\r\n", paraChar);
		return;
	}

	q = paraListPtr->nodes[p].next;
	paraListPtr->nodes[p].next = paraListPtr->nodes[paraListPtr->nodes[p].next].next;
	
	// 此语句和free(q)功能相同
	paraListPtr->used[q] = 0;
}

六,函数功能测试

/**
 * 功能测试。
 */
void appendInsertDeleteTest(){
	// Step 1. 初始化一个空链表
	ListPtr tempList = initLinkedList();
	printList(tempList);

	// Step 2. 加入一些元素
	insertElement(tempList, 'H', 0);
	insertElement(tempList, 'e', 1);
	insertElement(tempList, 'l', 2);
    insertElement(tempList, 'l', 1);
	insertElement(tempList, 'l', 3);
	insertElement(tempList, 'o', 4);
	printList(tempList);

	// Step 3. 删除一些元素(首次出现的该元素)
	printf("Deleting 'e'.\r\n");
	deleteElement(tempList, 'e');
	printf("Deleting 'a'.\r\n");
	deleteElement(tempList, 'a');
	printf("Deleting 'o'.\r\n");
	deleteElement(tempList, 'o');
	printList(tempList);

	insertElement(tempList, 'x', 1);
	printList(tempList);
}

        增加了部分的打印函数以更好地理解函数功能。

七,程序入口

/**
 * 程序入口
 */
void main(){
	appendInsertDeleteTest();
}

八,运行结果

Space at 1 allocated.
linking
Space at 2 allocated.
linking
Space at 3 allocated.
linking
Space at 4 allocated.
linking
No space.
No space.
Hlel
Deleting 'e'.
Deleting 'a'.
Cannot delete a
Deleting 'o'.
Cannot delete o
Hll
Space at 2 allocated.
linking
Hxll

完整代码

#include <stdio.h>
#include <malloc.h>

/**
 *  定义字符双向链表。
 */
typedef struct DoubleLinkNode{
    char data;
    struct DoubleLinkNode *previous;
    struct DoubleLinkNode *next;
} DLNode, *DLNodePtr;

/**
 * 初始化头节点。
 * @return 返回头节点的指针。
 */
DLNodePtr initLinkList(){
    DLNodePtr tempHeader = (DLNodePtr)malloc(sizeof(struct DoubleLinkNode));
    tempHeader->data = '\0';
    tempHeader->previous = NULL;
    tempHeader->next = NULL;
    return tempHeader;
}

/**
 * 打印链表。
 * @param paraHeader 是链表的头结点。
 */
void printList(DLNodePtr paraHeader){
    DLNodePtr p = paraHeader->next;
    if(p == NULL){
        printf("The list is empty.");
    }
    while(p != NULL){
        printf("%c", p->data);
        p = p->next;
    }
    printf("\r\n");
}

/**
 * 在给定的位置加入元素。
 * @param paraHeader 是链表的头结点。
 * @param paraChar 给定的char元素。
 * @param paraPosition 给定的位置。
 */
void insertElement(DLNodePtr paraHeader, char paraChar, int paraPosition){
    DLNodePtr p, q, r;

    // Step 1. 搜索给定的位置。
    p = paraHeader;
    for(int i = 0; i < paraPosition; i ++){
        p = p->next;
        if(p == NULL){
            printf("The position %d is beyond the scope of the list.", paraPosition);
            return;
        }
    }

    // Step 2. 创建一个新节点
    q = (DLNodePtr)malloc(sizeof(struct DoubleLinkNode));
    q->data = paraChar;

    // Step 3. 链接链表和节点。
    printf("linking\r\n");
    r = p->next;
    q->next = p->next;
    q->previous = p;
    p->next = q;
    if (r != NULL){
        r->previous = q;
    }
}

/**
 * 删除链表中的元素。
 * @param paraHeader 是链表的头结点。
 * @param paraChar 给定的char元素。
 */
void deleteElement(DLNodePtr paraHeader, char paraChar){
    DLNodePtr p, q, r;
    p = paraHeader;

    // Step 1. 定位
    while((p->next != NULL) && (p->next->data != paraChar)){
        p = p->next;
    }

    // Step 2. 检查错误
    if(p->next == NULL){
        printf("The char %c does not exist.\r\n", paraChar);
        return;
    }

    // Step 3. 改变链接
    q = p->next;
    r = q->next;
    p->next = r;
    if(r != NULL){
        r->previous = p;
    }
    
    // Step 4. 释放内存
    free(q);
}

/**
 * 找到双向链表中特定的数据的位置
 */
void locateElement(DLNodePtr paraHeader, char paraChar){
    DLNodePtr p;
    p = paraHeader;
	while(p->next != NULL){
        p = p->next;
        if(p->data == paraChar){
            printf("Found the char %c\r\n", paraChar);
            return;
        }
    }

    printf("The char %c is not been found.\r\n", paraChar);
	return ;
}

void LinkDestory(DLNodePtr paraHeader){
    DLNodePtr p;
    p = paraHeader;
    p->next = NULL;
    printf("The list has been destoryed.\r\n");
    return;
}

/**
 * 功能测试。
 */
void insertDeleteTest(){
    // Step 1. 初始化一个空链表。
    DLNodePtr tempList = initLinkList();
    printList(tempList);

    // Step 2. 加入一些字符。
    insertElement(tempList, 'H', 0);
    printList(tempList);
    insertElement(tempList, 'e', 1);
    printList(tempList);
	insertElement(tempList, 'l', 2);
    printList(tempList);
	insertElement(tempList, 'l', 3);
    printList(tempList);
	insertElement(tempList, 'o', 4);
    printList(tempList);
	insertElement(tempList, '!', 5);
	printList(tempList);

    // Step 3. 删除一些字符(第一次出现的)。
    deleteElement(tempList, 'e');
    printList(tempList);
	deleteElement(tempList, 'a');
    printList(tempList);
	deleteElement(tempList, 'o');
	printList(tempList);

    // Step 4. 在链表给定位置插入特定元素。
    insertElement(tempList, 'o', 1);//首位插入
    printList(tempList);
    insertElement(tempList, 'o', 5);//末位插入
    printList(tempList);
    insertElement(tempList, 'o', 3);//中间插入
    printList(tempList);

    // Step 5. 查找指定元素
    locateElement(tempList, 'H');
    locateElement(tempList, 'l');
    locateElement(tempList, 'o');
    locateElement(tempList, 'a');

    // Step 6. 清空链表
    LinkDestory(tempList);
    printList(tempList);
}

/**
 * 地址测试.
 */
void basicAddressTest(){
	DLNode tempNode1, tempNode2;

	tempNode1.data = 4;
	tempNode1.next = NULL;

	tempNode2.data = 6;
	tempNode2.next = NULL;

	printf("The first node: %d, %d, %d\r\n",
		&tempNode1, &tempNode1.data, &tempNode1.next);
	printf("The second node: %d, %d, %d\r\n",
		&tempNode2, &tempNode2.data, &tempNode2.next);

	tempNode1.next = &tempNode2;
}

/**
 * 程序入口。
 */
int main(){
	insertDeleteTest();
	basicAddressTest();
}
#include <stdio.h>
#include <malloc.h>

#define DEFAULT_SIZE 5

typedef struct StaticLinkedNode{
    char data;

    int next;
} *NodePtr;

typedef struct StaticLinkedList{
    NodePtr nodes;
    int* used;
} *ListPtr;

/**
 * 初始化头节点。
 * @return 返回头节点的指针。
 */
ListPtr initLinkedList(){
    // 指向整个链表空间的指针
    ListPtr tempPtr = (ListPtr)malloc(sizeof(struct StaticLinkedList));

    // 分配总空间
    tempPtr->nodes = (NodePtr)malloc(sizeof(struct StaticLinkedNode) * DEFAULT_SIZE);
	tempPtr->used = (int*)malloc(sizeof(int) * DEFAULT_SIZE);

    // 第一个节点是头结点
    tempPtr->nodes[0].data = '\0';
    tempPtr->nodes[0].next = -1;
    
    // 初始化时只有头结点使用
    tempPtr->used[0] = 1;
	for (int i = 1; i < DEFAULT_SIZE; i ++){
		tempPtr->used[i] = 0;
	}

	return tempPtr;
}

/**
 * 打印链表。
 * @param paraHeader 是链表的头结点。
 */
void printList(ListPtr paraListPtr){
	int p = 0;
	while (p != -1) {
		printf("%c", paraListPtr->nodes[p].data);
		p = paraListPtr->nodes[p].next;
	}
	printf("\r\n");
}

/**
 * 在给定的位置加入元素。
 * @param paraHeader 是链表的头结点。
 * @param paraChar 给定的char元素。
 * @param paraPosition 给定的位置。
 */
void insertElement(ListPtr paraListPtr, char paraChar, int paraPosition){
	int p, q, i;

	// Step 1. 搜索位置
	p = 0;
	for (i = 0; i < paraPosition; i ++) {
		p = paraListPtr->nodes[p].next;
		if (p == -1) {
			printf("The position %d is beyond the scope of the list.\r\n", paraPosition);
			return;
		}
	} 

	// Step 2. 创建一个新的节点
	for ( i; i < DEFAULT_SIZE; i ++){
		if (paraListPtr->used[i] == 0){
			printf("Space at %d allocated.\r\n", i);
			paraListPtr->used[i] = 1;
			q = i;
			break;
		}
	}
	if (i >= DEFAULT_SIZE){
		printf("No space.\r\n");
		return;
	}

	paraListPtr->nodes[q].data = paraChar;

	// Step 3. 链接节点
	printf("linking\r\n");
	paraListPtr->nodes[q].next = paraListPtr->nodes[p].next;
	paraListPtr->nodes[p].next = q;
}

/**
 * 删除链表中的元素。
 * @param paraHeader 是链表的头结点。
 * @param paraChar 给定的char元素。
 */
void deleteElement(ListPtr paraListPtr, char paraChar){
	int p, q;
	p = 0;
	while ((paraListPtr->nodes[p].next != -1) && (paraListPtr->nodes[paraListPtr->nodes[p].next].data != paraChar)){
		p = paraListPtr->nodes[p].next;
	}

	if (paraListPtr->nodes[p].next == -1) {
		printf("Cannot delete %c\r\n", paraChar);
		return;
	}

	q = paraListPtr->nodes[p].next;
	paraListPtr->nodes[p].next = paraListPtr->nodes[paraListPtr->nodes[p].next].next;
	
	// 此语句和free(q)功能相同
	paraListPtr->used[q] = 0;
}

/**
 * 功能测试。
 */
void appendInsertDeleteTest(){
	// Step 1. 初始化一个空链表
	ListPtr tempList = initLinkedList();
	printList(tempList);

	// Step 2. 加入一些元素
	insertElement(tempList, 'H', 0);
	insertElement(tempList, 'e', 1);
	insertElement(tempList, 'l', 2);
    insertElement(tempList, 'l', 1);
	insertElement(tempList, 'l', 3);
	insertElement(tempList, 'o', 4);
	printList(tempList);

	// Step 3. 删除一些元素(首次出现的该元素)
	printf("Deleting 'e'.\r\n");
	deleteElement(tempList, 'e');
	printf("Deleting 'a'.\r\n");
	deleteElement(tempList, 'a');
	printf("Deleting 'o'.\r\n");
	deleteElement(tempList, 'o');
	printList(tempList);

	insertElement(tempList, 'x', 1);
	printList(tempList);
}

/**
 * 程序入口
 */
void main(){
	appendInsertDeleteTest();
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/greatwaves11/article/details/124545089

智能推荐

商业智能案例分享——汽车市场行业分析仪表板_商业分析案例 汽车行业-程序员宅基地

文章浏览阅读932次。一、案例背景许多朋友在首次购车时,一般会比较纠结自己该如何选车,用什么标准选车。因此从购车人角度制作了一个仪表板,来辅助购车人高效做出决策。二、仪表板1、每个人购买倾向不同,所以应该提供给他们更多选择自由度。因此在仪表板上方设置了多个卡片图切片器,包括价格档、车系、车类、品牌、级别、车型等2、柱形图和切片器配合,展示了规模和销量各自的信息。规模:每个车型规模和总车型平均规模之间的对..._商业分析案例 汽车行业

HTK-W801使用LuatOS编程---点灯_海凌科w801开发板 luatos-程序员宅基地

文章浏览阅读6.9k次,点赞2次,收藏12次。W801上跑LuaOS, 两个点灯程序的比较_海凌科w801开发板 luatos

华为云弹性文件服务 SFS_在华为云中同一个弹性文件服务sfs的文件系统能给不同region挂载吗-程序员宅基地

文章浏览阅读1.1k次。挂载NFS文件系统到云服务器(Linux)参考链接:https://support.huaweicloud.com/qs-sfs/zh-cn_topic_0034428728.html弹性文件服务简介弹性文件服务(Scalable File Service,SFS)提供按需扩展的高性能文件存储(NAS),可为云上多个弹性云服务器(Elastic Cloud Server,ECS),容器(CCE&CCI)、裸金属服务器(BMS)提供共享访问。如图1所示。图1 访问弹性文件服务与传统的文件共_在华为云中同一个弹性文件服务sfs的文件系统能给不同region挂载吗

编译原理复习汇总_请构造一文法,使文法产生的语言是十进制正偶数集合,并规定偶数非0开头-程序员宅基地

文章浏览阅读509次,点赞2次,收藏6次。目录第 1 章 引论第 2 章 文法和语言2.1 句型分析和语法树2.2 文法设计第 3 章 词法分析第 4 章 自顶向下语法分析方法第 6 章 LR分析第 7 章 语法制导的语义计算第 8 章 静态语义分析和中间代码生成第 9 章 运行时存储组织第 10 章 代码优化和目标代码生成第 1 章 引论第 2 章 文法和语言2.1 句型分析和语法树令文法G[E]为:E->T | E+T | E-T T->F | T*F F->(E)|i证明 E+T*F 是它的一个句型,给出该句型的所_请构造一文法,使文法产生的语言是十进制正偶数集合,并规定偶数非0开头

Java 重定位 —— redirect:_redirect:/index-程序员宅基地

文章浏览阅读747次。return "redirect:/index": 不管前面的路径是什么,满足条件后会跳转到index比如8080/a/b/c/跳转后变成8080/index_redirect:/index

Python对象的身份比较_python 身份-程序员宅基地

文章浏览阅读971次。相较于值的比较,Python也支持身份的比较。身份比较运算符:运算符 说明 is 结果为True,运算符两端是同一个对象,如果是False,则为不同对象。 is not 结果为True,运算符两端不是同一个对象,结果为False,则为同一个对象。 什么是身份比较所谓身份比较,即判断两个或更多的不同名称的对象是否为同一个对象。>>> ..._python 身份

随便推点

java string json解析_Java从String开始解析JSON-程序员宅基地

文章浏览阅读286次。一、JSON 格式简析。{"person_num": 1,"person_info": [{"body_parts": {"nose": {"x": 96.34375,"y": 101.53125},"right_knee": {"x": 89.6875,"y": 314.53125},"location": {"width": 91.40377044677734,"height": 354.71..._java string json 解析

如何用安卓手机运行Python代码_安卓 python-程序员宅基地

文章浏览阅读7.2w次,点赞246次,收藏923次。1. 写在前面的话  天天都在PC端运行Python代码的我,今天突然灵光一现,想着是不是能够在移动端运行Python代码呢?如果能够实现的话,家里的废旧手机就有用武之地了。2. 安装环境2.1 安装APK  根据搜索和调研,需要安装以下三个APK,即QPython3、QPython、QPy3.6。打包下载链接为https://download.csdn.net/download/herosunly/16683910  安装后依次为下列三个APP(QPython 3S、QPython OS、QP_安卓 python

Vim|笔记整理(1)——Vim基本概述_简述vim概念及目标-程序员宅基地

文章浏览阅读580次。学习资源B站优质视频教程—TheCWVim教程网—北航小姐姐玩转Vim 从放弃到爱不释手—PegasusWangVim Tutorial—Youtube视频Vim中文手册基本操作思维导图概述学了vim几个月,也看了网上很多教程后,我有时会觉得我们总是喜欢处于舒适区,而对接触让我们一开始感觉别扭的新内容和新工具总是有所抗拒。我希望自己能够多去尝试新内容和新工具,因为我们技能的提升就..._简述vim概念及目标

Labels4Free: Unsupervised Segmentation using StyleGAN论文解读_label4free github-程序员宅基地

文章浏览阅读1k次,点赞2次,收藏2次。入选ICCV2021,官方page website,暂未开源paper还是很有创意的,只是pipeline搭建起来很繁琐,还有很大的改进空间。背景styleGAN等生成对抗网络可以生成逼真的图像,生成器的中间特征已经有了前景和背景的特征学习能力,但目前没有方法研究让GAN生成图像的同时,还生成前景目标的mask。本篇paper正是为了解决该问题。作者基于两种假设前景和背景是独立的,因此独立生成然后组合,也能生成逼真的图像。生成器的中间特征学习到了前背景特征分布,是可以利用起来,用于生成前景目标_label4free github

Linux C/C++串口读写_linux c++ 串口收发-程序员宅基地

文章浏览阅读1.6w次,点赞10次,收藏134次。无_linux c++ 串口收发

javascript前端XML格式正确性验证方法_js判断xml-程序员宅基地

文章浏览阅读3.5k次。https://www.2cto.com/kf/201203/124608.html function validateXML(xmlContent) { //errorCode 0是xml正确,1是xml错误,2是无法验证 var xmlDoc,errorMessage,errorCode = 0; ..._js判断xml

推荐文章

热门文章

相关标签