学习笔记---更进一步的双向链表专题~~

目录
1. 双向链表的结构🦊
2. 实现双向链表🐝
2.1 要实现的目标🎯
2.2 创建+初始化🦋
2.2.1 List.h
2.2.2 List.c
2.2.3 test.c
2.2.4 代码测试运行
2.3 尾插+打印+头插🪼
思路分析
2.3.1 List.h
2.3.2 List.c
2.3.3 test.c
2.3.4 代码测试运行
2.4 尾删+头删🐊
2.4.0 思路分析
2.4.1 List.h
2.4.2 List.c
2.4.3 test.c
2.4.4 代码测试运行
2.5 查找数据+pos节点后插入+删除pos节点🦩
2.5.0 思路分析
2.5.1 List.h
2.5.2 List.c
2.5.3 test.c
2.5.4 代码测试运行
2.6 销毁☄️
2.6.0思路分析
1. 一级指针
2.6.1 List.h
2.6.2 List.c
2.6.3 test.c
2.6.4 代码测试运行
2. 二级指针
2.6.1 List.h
2.6.2 List.c
2.6.3 test.c
2.6.4 代码测试运行
2.7 完整代码💦
2.7.1 List.h
2.7.2 List.c
2.7.3 test.c
3. 顺序表和双向链表的分析🍻
1. 双向链表的结构🦊

这里的双向链表,准确的说是:带头双向循环链表
这里的“头节点”指的是“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这⾥“放哨
的”。
“哨兵位”存在的意义:遍历循环链表避免死循环。
注意⚠️
双向链表的每一个节点存储一个有效数据+下一个节点的地址+上一个节点的地址
头节点和尾节点有些特殊:头节点指向的上一个节点的地址是尾节点,尾节点指向的下一个节点的地址是头节点
2. 实现双向链表🐝
2.1 要实现的目标🎯
我们需要多个接口帮助我们实现:创建、一系列具体操作、销毁
具体操作包括:头部/尾部插入数据、头部/尾部删除数据、打印出双向链表、指定节点之后插入数据、删除指定节点的数据、查找指定节点
2.2 创建+初始化🦋
2.2.1 List.h
#include<assert.h>
#include<string.h>
#include<stdbool.h>typedef int LTDataType;
//创建双向链表的结构体
typedef struct ListNode {LTDataType data;struct ListNode* prev;struct ListNode* next;
}ListNode;//初始化
ListNode* LTInit();//不用传入参数,直接调用接口返回一个头节点
2.2.2 List.c
#include"List.h"
//初始化
ListNode* LTInit()//不用传入参数,直接调用接口返回一个头节点
{//为头节点申请空间ListNode* phead = (ListNode*)malloc(sizeof(ListNode));//判断开辟是否成功if (phead == NULL){perror("malloc error!\n");return;}//开辟成功--->初始化头节点phead->data = -1;//头节点不存储有效数据,可以任意赋值//只有哨兵位的时候,要实现双向链表,不能指向NULL,否则无法双向循环,所以我们指向自己phead->prev = phead->next = phead;return phead;
}
2.2.3 test.c
#include"List.h"
void ListTest()
{ListNode* plist = LTInit();
}
int main()
{ListTest();return 0;
}
2.2.4 代码测试运行

2.3 尾插+打印+头插🪼
思路分析



2.3.1 List.h
//在双向链表中不会改变哨兵位,所以这里都可以传一级指针
//尾插
void LTPushBack(ListNode* phead, LTDataType x);//打印
void LTPrint(ListNode* phead);//头插
void LTPushFront(ListNode* phead, LTDataType x);
2.3.2 List.c
//在双向链表中不会改变哨兵位,所以这里都可以传一级指针
// 只改变数据,不改变地址//开辟空间
ListNode* ListBuyNode(LTDataType x)
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));if (node == NULL){perror("malloc error!\n");return;}node->data = x;node->next = node->prev = NULL;return node;
}//尾插
void LTPushBack(ListNode* phead, LTDataType x)
{assert(phead);//注意哨兵位不能为空//申请空间ListNode* node = ListBuyNode(x);//先处理node的前驱指针和后继指针node->prev = phead->prev;node->next = phead;//再处理之前的尾节点和pheadphead->prev->next = node;phead->prev = node;
}//打印
void LTPrint(ListNode* phead)
{//哨兵位不能改变ListNode* cur = phead->next;while (cur != phead)//当cur再次指向phead的时候,循环结束{printf("%d->", cur->data);cur = cur->next;}printf("\n");
}//头插
void LTPushFront(ListNode* phead, LTDataType x)
{assert(phead);//注意哨兵位不能为空//申请空间ListNode* node = ListBuyNode(x);//node插入头节点之后才算头插//先处理node的前驱指针和后继指针node->prev = phead;node->next = phead->next;//再处理phead和phead->nextphead->next->prev = node;phead->next = node;
}
2.3.3 test.c
#include"List.h"
void ListTest()
{ListNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPrint(plist);//1 2 3 4 LTPushFront(plist, 5);LTPrint(plist);//5 1 2 3 4
}
int main()
{ListTest();return 0;
}
2.3.4 代码测试运行

2.4 尾删+头删🐊
2.4.0 思路分析


2.4.1 List.h
//尾删
void LTPopBack(ListNode* phead);//头删
void LTPopFront(ListNode* phead);
2.4.2 List.c
//尾删
void LTPopBack(ListNode* phead)
{//不能为空链表,只有一个哨兵位不能尾删assert(phead&&(phead->prev!=phead||phead->next!=phead));ListNode* del = phead->prev;//phead->prev就是尾节点//先处理deldel->prev->next = phead;//再处理pheadphead->prev = del->prev;free(del);del = NULL;
}//头删
void LTPopFront(ListNode* phead)
{//不能为空链表,只有一个哨兵位不能头删assert(phead && (phead->prev != phead || phead->next != phead));ListNode* del = phead->next;del->next->prev = phead;phead->next = del->next;free(del);del = NULL;
}
2.4.3 test.c
#include"List.h"
void ListTest()
{ListNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPrint(plist);//1 2 3 4 LTPushFront(plist, 5);LTPrint(plist);//5 1 2 3 4 LTPopBack(plist);LTPrint(plist);//5 1 2 3LTPopFront(plist);LTPrint(plist);//1 2 3
}
int main()
{ListTest();return 0;
}
2.4.4 代码测试运行

2.5 查找数据+pos节点后插入+删除pos节点🦩
2.5.0 思路分析


2.5.1 List.h
//查找数据
ListNode* LTFind(ListNode* phead, LTDataType x);//pos节点之后插入
void LTPushAfter(ListNode* pos, LTDataType x);//删除pos节点
void LTErase(ListNode* pos);
2.5.2 List.c
//查找数据
ListNode* LTFind(ListNode* phead, LTDataType x)
{assert(phead);ListNode* cur = phead->next;while (cur!= phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}//pos节点之后插入
void LTPushAfter(ListNode* pos, LTDataType x)
{assert(pos);ListNode* node = ListBuyNode(x);//nodenode->next = pos->next;node->prev = pos;//pospos->next = node;node->next->prev = node;
}//删除pos节点
void LTErase(ListNode* pos)
{assert(pos);pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);pos = NULL;
}
2.5.3 test.c
#include"List.h"
void ListTest()
{ListNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPrint(plist);//1 2 3 4 LTPushFront(plist, 5);LTPrint(plist);//5 1 2 3 4 LTPopBack(plist);LTPrint(plist);//5 1 2 3LTPopFront(plist);LTPrint(plist);//1 2 3ListNode* find = LTFind(plist, 1);/*LTPushAfter(find, 4);*/ //LTPrint(plist);//1 4 2 3LTErase(find);LTPrint(plist);//2 3}
int main()
{ListTest();return 0;
}
2.5.4 代码测试运行


2.6 销毁☄️
2.6.0思路分析
一开始的初始化,我们直接调用了接口,返回头节点进行初始化。我们没有考虑一级指针还是二级指针的问题。
那么,最后的销毁又该怎么办?是一级指针?还是二级指针?下面我们一一来尝试
1. 一级指针
2.6.1 List.h
//销毁
void LTDestroy(ListNode* phead);
2.6.2 List.c
//销毁
void LTDestroy(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while(cur!=phead){ListNode* next = cur->next;free(cur);cur = next;}//注意哨兵位还没有释放free(phead);phead = NULL;
}
2.6.3 test.c
#include"List.h"
void ListTest()
{ListNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPrint(plist);//1 2 3 4 //LTPushFront(plist, 5);//LTPrint(plist);//5 1 2 3 4 //LTPopBack(plist);//LTPrint(plist);//5 1 2 3//LTPopFront(plist);//LTPrint(plist);//1 2 3//ListNode* find = LTFind(plist, 1);/*LTPushAfter(find, 4);*/ LTPrint(plist);//1 4 2 3//LTErase(find);//LTPrint(plist);//2 3LTDestroy(plist);}
int main()
{ListTest();return 0;
}
2.6.4 代码测试运行

一级指针:
phead的改变不影响plist,phead释放之后,plist指向已经释放掉的空间——>把plist置为空那么置为空之前,还要不要将plist指向的空间再free一次?
我们尝试一下
那么再思考一下:一级指针是会导致phead的改变不影响plist,那么plist是什么没有改变?是指plist保存的值没有被改变还是plist的这块空间的地址没有被释放?


这里报错指的是plist指向无效地址
注意⚠️
如果plist的地址没有被释放,那么直接free(plist)是不会报错的所以在一级指针的情况下:plist的地址已经被释放了,没有被置为空的可以理解是plist的地址名称
2.6.5 一级指针的改进---test.c

2. 二级指针
2.6.1 List.h
//销毁
//void LTDestroy(ListNode* phead);
void LTDestroy(ListNode** phead);
2.6.2 List.c
//销毁
void LTDestroy(ListNode** phead)
{assert(phead && *phead);ListNode* cur = (*phead)->next;while (cur != *phead){ListNode* next = cur->next;free(cur);cur = next;}free(*phead);*phead = NULL;
}
2.6.3 test.c
#include"List.h"
void ListTest()
{ListNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPrint(plist);//1 2 3 4 //LTPushFront(plist, 5);//LTPrint(plist);//5 1 2 3 4 //LTPopBack(plist);//LTPrint(plist);//5 1 2 3//LTPopFront(plist);//LTPrint(plist);//1 2 3//ListNode* find = LTFind(plist, 1);///*LTPushAfter(find, 4);*/ LTPrint(plist);//1 4 2 3//LTErase(find);//LTPrint(plist);//2 3//LTDestroy(plist);//plist = NULL;LTDestroy(&plist);
}
int main()
{ListTest();return 0;
}
2.6.4 代码测试运行

虽然,二级指针不用手动将plist置为空
但是,更推荐一级指针,因为其他接口基本上都是一级指针——>保持接口的一致性
2.7 完整代码💦
2.7.1 List.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<stdbool.h>typedef int LTDataType;
//创建双向链表的结构体
typedef struct ListNode {LTDataType data;struct ListNode* prev;struct ListNode* next;
}ListNode;//初始化
ListNode* LTInit();//不用传入参数,直接调用接口返回一个头节点//在双向链表中不会改变哨兵位,所以这里都可以传一级指针
//尾插
void LTPushBack(ListNode* phead, LTDataType x);//打印
void LTPrint(ListNode* phead);//头插
void LTPushFront(ListNode* phead, LTDataType x);//尾删
void LTPopBack(ListNode* phead);//头删
void LTPopFront(ListNode* phead);//查找数据
ListNode* LTFind(ListNode* phead, LTDataType x);//pos节点之后插入
void LTPushAfter(ListNode* pos, LTDataType x);//删除pos节点
void LTErase(ListNode* pos);//销毁
void LTDestroy(ListNode* phead);
2.7.2 List.c
#include"List.h"
//初始化
ListNode* LTInit()//不用传入参数,直接调用接口返回一个头节点
{//为头节点申请空间ListNode* phead = (ListNode*)malloc(sizeof(ListNode));//判断开辟是否成功if (phead == NULL){perror("malloc error!\n");return;}//开辟成功--->初始化头节点phead->data = -1;//头节点不存储有效数据,可以任意赋值//只有哨兵位的时候,要实现双向链表,不能指向NULL,否则无法双向循环,所以我们指向自己phead->prev = phead->next = phead;return phead;
}//在双向链表中不会改变哨兵位,所以这里都可以传一级指针
// 只改变数据,不改变地址//开辟空间
ListNode* ListBuyNode(LTDataType x)
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));if (node == NULL){perror("malloc error!\n");return;}node->data = x;node->next = node->prev = NULL;return node;
}//尾插
void LTPushBack(ListNode* phead, LTDataType x)
{assert(phead);//注意哨兵位不能为空//申请空间ListNode* node = ListBuyNode(x);//先处理node的前驱指针和后继指针node->prev = phead->prev;node->next = phead;//再处理之前的尾节点和pheadphead->prev->next = node;phead->prev = node;
}//打印
void LTPrint(ListNode* phead)
{//哨兵位不能改变ListNode* cur = phead->next;while (cur != phead)//当cur再次指向phead的时候,循环结束{printf("%d->", cur->data);cur = cur->next;}printf("\n");
}//头插
void LTPushFront(ListNode* phead, LTDataType x)
{assert(phead);//注意哨兵位不能为空//申请空间ListNode* node = ListBuyNode(x);//node插入头节点之后才算头插//先处理node的前驱指针和后继指针node->prev = phead;node->next = phead->next;//再处理phead和phead->nextphead->next->prev = node;phead->next = node;
}//尾删
void LTPopBack(ListNode* phead)
{//不能为空链表,只有一个哨兵位不能尾删assert(phead&&(phead->prev!=phead||phead->next!=phead));ListNode* del = phead->prev;//phead->prev就是尾节点//先处理deldel->prev->next = phead;//再处理pheadphead->prev = del->prev;free(del);del = NULL;
}//头删
void LTPopFront(ListNode* phead)
{//不能为空链表,只有一个哨兵位不能头删assert(phead && (phead->prev != phead || phead->next != phead));ListNode* del = phead->next;del->next->prev = phead;phead->next = del->next;free(del);del = NULL;
}//查找数据
ListNode* LTFind(ListNode* phead, LTDataType x)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}//pos节点之后插入
void LTPushAfter(ListNode* pos, LTDataType x)
{assert(pos);ListNode* node = ListBuyNode(x);//nodenode->next = pos->next;node->prev = pos;//pospos->next = node;node->next->prev = node;
}//删除pos节点
void LTErase(ListNode* pos)
{assert(pos);pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);pos = NULL;
}//销毁
void LTDestroy(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while(cur!=phead){ListNode* next = cur->next;free(cur);cur = next;}//注意哨兵位还没有释放free(phead);phead = NULL;
}
2.7.3 test.c
#include"List.h"
void ListTest()
{ListNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPrint(plist);//1 2 3 4 LTPushFront(plist, 5);LTPrint(plist);//5 1 2 3 4 LTPopBack(plist);LTPrint(plist);//5 1 2 3LTPopFront(plist);LTPrint(plist);//1 2 3ListNode* find = LTFind(plist, 1);/*LTPushAfter(find, 4);*/ //LTPrint(plist);//1 4 2 3LTErase(find);LTPrint(plist);//2 3LTDestroy(plist);plist = NULL;
}
int main()
{ListTest();return 0;
}
3. 顺序表和双向链表的分析🍻
| 不同点 | 顺序表 | 链表(单链表) |
| 存储空间上 | 物理上一定连续 | 逻辑上连续,但物理上不一定连续 |
| 随机访问 | 支持O(1) | 不支持:O(N) |
| 任意位置插入或者删除元素 | 看你需要搬移元素,效率低O(N) | 只需要改变指针指向 |
| 插入 | 动态顺序表,空间不够的时候需要扩容 | 没有容量的概念 |
| 应用场景 | 元素高效存储+频繁访问 | 任意位置插入和删除频繁 |
本次的分享到这里就结束了!!!
PS:小江目前只是个新手小白。欢迎大家在评论区讨论哦!有问题也可以讨论的!
如果对你有帮助的话,记得点赞👍+收藏⭐️+关注➕

相关文章:
学习笔记---更进一步的双向链表专题~~
目录 1. 双向链表的结构🦊 2. 实现双向链表🐝 2.1 要实现的目标🎯 2.2 创建初始化🦋 2.2.1 List.h 2.2.2 List.c 2.2.3 test.c 2.2.4 代码测试运行 2.3 尾插打印头插🪼 思路分析 2.3.1 List.h 2.3.2 List.…...
vscode格式化代码, 谷歌风格, 允许短if同行短块同行, tab = 4舒适风格
ctrl ,输入format, 点开C风格设置 在这块内容输入{ BasedOnStyle: Chromium, IndentWidth: 4, ColumnLimit: 200, AllowShortIfStatementsOnASingleLine: true, AllowShortLoopsOnASingleLine: true} C_Cpp: Clang_format_fallback Style 用作回退的预定义样式的名称&#x…...
百度富文本上传图片后样式崩塌
🔥博客主页: 破浪前进 🔖系列专栏: Vue、React、PHP ❤️感谢大家点赞👍收藏⭐评论✍️ 问题描述:上传图片后,图片会变得很大,当点击的时候更是会顶开整个的容器的高跟宽 原因&#…...
autoware.ai中检测模块lidar_detector caffe
lidar_apollo_cnn_seg_detect模块:该模块主要是调用百度apollo的目标分割。 1.需要安装caffe进行实现: caffe安装步骤: git clone https://github.com/BVLC/caffecd caffe && mdkir build && cd buildcmake ..出现报错: CM…...
CentOS安装Ruby环境
安装依赖项 sudo yum install -y perl zlib-devel openssl-devel安装git sudo yum install -y git git config --global http.sslVerify falsecurl取消ssl认证 echo "insecure" >> ~/.curlrc安装rbenv https://github.com/rbenv/rbenv git clone https://…...
力扣第509题 斐波那契数 新手动态规划(推荐参考) c++
题目 509. 斐波那契数 简单 相关标签 递归 记忆化搜索 数学 动态规划 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0&a…...
canvas绘制签名并保存
实现签名的三个关键方法: 1.mousedown:当鼠标按下时开始绘制签名。 2.mousemove:鼠标移动时持续绘制。 3.mouseup:鼠标抬起时结束绘制。 html: <div class"setSign"><canvasref"canvas&q…...
Android渲染流程
目录 缓冲区的不同生命周期代表当前缓冲区的状态: 多个源 ViewRootImpl: Android4.0: Android5.0: Android应用程序调用SurfaceFliger将测量,布局,绘制好的Surface借助GPU渲染显示到屏幕上。 一个Acti…...
牛客-【237题】算法基础精选题单-第二章 递归、分治
第二章 递归、分治 递归NC15173 The Biggest Water ProblemNC22164 更相减损术 递归 NC15173 The Biggest Water Problem 简单递归,直接暴力 #include <math.h> #include <stdio.h> #include <algorithm> #include <cstring> #include &…...
leetcode-字符串
1.反转字符串LeetCode344. 20230911 难度为0,此处就不放代码了 注意reverse和swap等一系列字符串函数什么时候该用,记一记库函数 swap可以有两种实现,涨知识了,除了temp存值还可以通过位运算:s[i] ^ s[j]; s[j] ^ s[i…...
多线程---synchronized特性+原理
文章目录 synchronized特性synchronized原理锁升级/锁膨胀锁消除锁粗化 synchronized特性 互斥 当某个线程执行到某个对象的synchronized中时,其他线程如果也执行到同一个对象的synchronized就会阻塞等待。 进入synchronized修饰的代码块相当于加锁 退出synchronize…...
Qt实现卡牌对对碰游戏
效果 闲来无事,实现一个对对碰游戏,卡牌样式是火影动漫。 先上效果: 卡牌对对碰_火影主题 玩法 启动游戏,进入第一关卡,所有卡牌都为未翻开状态,即背面朝上;点击卡牌,则将卡牌翻开…...
【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割7(数据预处理)
在上一节:【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割6(数据预处理) 中,我们已经得到了与mhd图像同seriesUID名称的mask nrrd数据文件了,可以说是一一对应了。 并且,mask的文件,还根据结…...
极米科技H6 Pro 4K、H6 4K高亮定焦版——开启家用投影4K普及时代
智能投影产业经过几年发展,市场规模正在快速扩大。洛图数据显示,预计今年中国投影出货量有望超700万台,2027年达950万台,可见智能投影产业规模将逐渐壮大,未来可期。2023年,投影行业呈现出全新面貌…...
软考系统架构师知识点集锦九:数据库系统
一、考情分析 二、考点精讲 2.1数据库概述 2.1.1数据库模式 (1)三级模式:外模式对应视图,模式(也称为概念模式)对应数据库表,内模式对应物理文件。(2)两层映像:外模式-模式映像,模式-内模式映像;两层映像可以保证数据库中的数据具有较高的…...
IOC课程整理-6 Spring IoC 依赖注入
1 依赖注入的模式和类型 模式 类型 2 自动绑定(Autowiring) 官方定义 “自动装配是Spring框架中一种机制,用于自动解析和满足bean之间的依赖关系。通过自动装配,Spring容器可以根据类型、名称或其他属性来自动连接协作的bean&…...
FANUC机器人PRIO-621和PRIO-622设备和控制器没有运行故障处理
FANUC机器人PRIO-621和PRIO-622设备和控制器没有运行故障处理 如下图所示,新的机器人开机后提示报警: PRIO-621 设备没有运行 PRIO-622 控制器没有运行 我们首先查看下手册上的报警代码说明,如下图所示, 如下图所示,…...
《动手深度学习》线性回归简洁实现实例
🎈 作者:Linux猿 🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊! &…...
国家数据局正式揭牌,数据专业融合型人才迎来发展良机
📕作者简介:热爱跑步的恒川,致力于C/C、Java、Python等多编程语言,热爱跑步,喜爱音乐的一位博主。 📗本文收录于恒川的日常汇报系列,大家有兴趣的可以看一看 📘相关专栏C语言初阶、C…...
基于springboot实现休闲娱乐代理售票平台系统项目【项目源码+论文说明】
基于springboot实现休闲娱乐代理售票系统演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把休闲娱乐代理售票管理与现在网络相结合,利用java技术建设休闲娱乐代理售票系统,实现休闲娱乐代理售票的信息化。则对于进一步提高休闲娱乐代理售票管理发…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
