1 栈

1.1 栈的基本概念

栈(stack)又名堆栈,它是一种 运算受限的线性表。限定 仅在表尾进行插入和删除操作 的线性表。表尾被称为栈顶,相对地,把另一端称为栈底。

1.1.1 特点

它的特殊之处在于限制了这个线性表的插入和删除的位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能在栈底。

1.2 栈的常用操作

  • 创建栈

  • 销毁栈

  • 清空栈

  • 进栈

  • 出栈

  • 获取栈顶元素

  • 获取栈的大小

1.2.1 栈的抽象数据类型

  1. ADT 栈(stack
  2. Data
  3. 通线性表。元素具有相同的类型,相邻的元素具有前驱和后继关系。
  4. Operation
  5. // 初始化,建立一个空栈S
  6. InitStack(*S);
  7. // 若栈存在,则销毁它
  8. DestroyStack(*S);
  9. // 将栈清空
  10. ClearStack(*S);
  11. // 若栈为空则返回true,否则返回false
  12. StackEmpty(S);
  13. // 若栈存在且非空,用e返回S的栈顶元素
  14. GetTop(S,*e);
  15. // 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
  16. Push(*Se);
  17. // 删除栈S中的栈顶元素,并用e返回其值
  18. Pop(*S, *e);
  19. // 返回栈S的元素个数
  20. StackLength(S);
  21. endADT

1.3 栈的顺序存储

1.3.1 基本概念

基本概念

栈的顺序存储结构简称顺序栈,它是运算受限制的顺序表。顺序栈的存储结构是:利用一组地址连续的的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top只是栈顶元素在顺序表中的位置。

栈是先进后出的线性表。

1.3.2 设计与实现

因为栈是一种特殊的线性表,所以栈的顺序存储可以通过顺序线性表来实现。

示例代码:

SqStack.h

  1. #ifndef _SQSTACK_H
  2. #define _SQSTACK_H
  3. #define MAXSIZE 50
  4. typedef int EnumType;
  5. typedef struct _SQSTACK
  6. {
  7. int top; // 栈顶指针
  8. EnumType data[MAXSIZE];
  9. }SqStack;
  10. // 初始化,建立一个空栈S
  11. void InitStack(SqStack *S);
  12. // 将栈清空
  13. void ClearStack(SqStack *S);
  14. // 若栈为空则返回true,否则返回false
  15. int StackEmpty(SqStack S);
  16. // 若栈存在且非空,用e返回S的栈顶元素
  17. void GetTop(SqStack S, EnumType *e);
  18. // 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
  19. void Push(SqStack *S, EnumType e);
  20. // 删除栈S中的栈顶元素,并用e返回其值
  21. void Pop(SqStack *S, EnumType *e);
  22. // 返回栈S的元素个数
  23. int StackLength(SqStack S);
  24. #endif // _SQSTACK_H

SqStack.c

  1. #include "SqStack.h"
  2. #include <string.h>
  3. void InitStack(SqStack *S)
  4. {
  5. // 空栈
  6. S->top = -1;
  7. memset(S->data, 0, sizeof(S->data));
  8. }
  9. void ClearStack(SqStack *S)
  10. {
  11. S->top = -1;
  12. }
  13. int StackEmpty(SqStack S)
  14. {
  15. if (S.top == -1)
  16. {
  17. return 1;
  18. }
  19. return 0;
  20. }
  21. void GetTop(SqStack S, EnumType *e)
  22. {
  23. // 栈为空
  24. if (S.top == -1 && S.data[S.top]!= 0)
  25. {
  26. return;
  27. }
  28. *e = S.data[S.top];
  29. }
  30. void Push(SqStack *S, EnumType e)
  31. {
  32. // 栈已经满了
  33. if (S->top == MAXSIZE - 1)
  34. {
  35. return;
  36. }
  37. // 栈顶上移
  38. S->top++;
  39. // 赋值
  40. S->data[S->top] = e;
  41. }
  42. void Pop(SqStack *S, EnumType *e)
  43. {
  44. // 栈为空
  45. if (S->top == -1 && S->data[S->top]!= 0)
  46. {
  47. return;
  48. }
  49. // 赋值
  50. *e = S->data[S->top];
  51. // 栈顶指针下移
  52. S->top--;
  53. }
  54. int StackLength(SqStack S)
  55. {
  56. return S.top + 1;
  57. }

main.c

  1. #include "SqStack.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. void main()
  5. {
  6. // 定义栈变量
  7. SqStack st;
  8. int i = -1;
  9. // 初始化栈
  10. InitStack(&st);
  11. // 压栈
  12. for (i = 0; i < 10; ++i)
  13. {
  14. Push(&st,i+1);
  15. }
  16. printf("stack size = %d\n", StackLength(st));
  17. // 出栈
  18. while (StackEmpty(st) != 1)
  19. {
  20. int temp;
  21. // 取栈顶元素
  22. GetTop(st, &temp);
  23. printf("Get stacktop elem is: %d\n", temp);
  24. // 删除栈顶元素
  25. Pop(&st, &temp);
  26. printf("Delete stacktop elem is: %d\n", temp);
  27. }
  28. system("pause");
  29. }

运行结果:

1.4 栈的链序存储

1.4.1 基本概念

栈的链式存储结构简称链栈。

1.4.2 设计与实现

链栈是一种特殊的线性表,链栈可以通过链式线性表来实现。

示例代码:

LinkStack.h

  1. #ifndef _LINKSTACK_H
  2. #define _LINKSTACK_H
  3. // 定义小链表节点
  4. typedef struct NODE
  5. {
  6. struct NODE* next;
  7. }Node;
  8. // 链表结构体
  9. typedef struct
  10. {
  11. // 栈顶指针
  12. Node *top;
  13. // 长度
  14. int length;
  15. }LinkStack;
  16. // 初始化,建立一个空栈S
  17. void InitStack(LinkStack *S);
  18. // 将栈清空
  19. void ClearStack(LinkStack *S);
  20. // 若栈为空则返回true,否则返回false
  21. int StackEmpty(LinkStack S);
  22. // 若栈存在且非空,用e返回S的栈顶元素
  23. void GetTop(LinkStack S, Node **e);
  24. // 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
  25. void Push(LinkStack *S, Node *e);
  26. // 删除栈S中的栈顶元素,并用e返回其值
  27. void Pop(LinkStack *S, Node **e);
  28. // 返回栈S的元素个数
  29. int StackLength(LinkStack S);
  30. #endif // _LINKSTACK_H

LinkStack.c

  1. #include "LinkStack.h"
  2. #include <stdio.h>
  3. void InitStack(LinkStack *S)
  4. {
  5. S->length = 0;
  6. S->top = NULL;
  7. }
  8. void ClearStack(LinkStack *S)
  9. {
  10. while (S->length)
  11. {
  12. Node* p;
  13. Pop(S, &p);
  14. }
  15. }
  16. int StackEmpty(LinkStack S)
  17. {
  18. if (S.length == 0)
  19. {
  20. return 1;
  21. }
  22. return 0;
  23. }
  24. void GetTop(LinkStack S, Node **e)
  25. {
  26. // 空栈
  27. if (S.length == 0 || S.top == NULL)
  28. {
  29. return;
  30. }
  31. *e = S.top;
  32. }
  33. // 栈顶是链表头部
  34. void Push(LinkStack *S, Node *e)
  35. {
  36. // 节点e插入到链表的头部
  37. e->next = S->top;
  38. // top指针指向第一个节点
  39. S->top = e;
  40. // 长度+1
  41. S->length++;
  42. }
  43. void Pop(LinkStack *S, Node **e)
  44. {
  45. // 删除第一个节点
  46. Node* pDel = S->top;
  47. // 空栈
  48. if (S->length == 0)
  49. {
  50. return;
  51. }
  52. // 赋值
  53. *e = pDel;
  54. // 栈顶指针后移
  55. S->top = pDel->next;
  56. // 长度减1
  57. S->length--;
  58. }
  59. int StackLength(LinkStack S)
  60. {
  61. return S.length;
  62. }

main.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "LinkStack.h"
  4. // 业务节点
  5. typedef struct stu
  6. {
  7. // 包含链表节点
  8. Node node;
  9. int id;
  10. int age;
  11. }Student;
  12. void main()
  13. {
  14. Student stu[10];
  15. // 链表结构变量
  16. LinkStack st;
  17. int i = -1;
  18. // 初始化栈
  19. InitStack(&st);
  20. // 初始化数组
  21. for (i = 0; i < sizeof(stu) / sizeof(Student); ++i)
  22. {
  23. stu[i].id = i;
  24. stu[i].age = i + 20;
  25. // 数据添加链表中
  26. Push(&st, &stu[i].node);
  27. printf("stack size = %d\n", StackLength(st));
  28. while (StackEmpty(st) != 1)
  29. {
  30. Node* p = NULL;
  31. Student* pp = NULL;
  32. // 获取栈顶元素
  33. GetTop(st, &p);
  34. pp = (Student*)p;
  35. printf("elem id = %d, age=%d\n", pp->id, pp->age);
  36. // 删除
  37. Pop(&st, &p);
  38. pp = (Student*)p;
  39. printf("Delete elem id = %d, age=%d\n", pp->id, pp->age);
  40. }
  41. }
  42. system("pause");
  43. }

运行结果:

2 队列

2.1 基本概念

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

2.1.1 特点

队列是先进先出的线性表。

在队尾添加元素,在队头删除元素。

判断队列是空队列还是已满呢?

  1. 栈空: 队首标志 = 队尾标志时,表示栈空。

  2. 栈满 : 队尾 + 1 = 队首时,表示栈满。

2.2 队列的常用操作

  • 创建队列

  • 销毁队列

  • 清空队列

  • 进队列

  • 出队列

  • 获取队头元素

  • 获取队列的长度

2.2.1 队列的抽象数据类型

  1. ADT 队列(Queue
  2. Data
  3. 通线性表。元素具有相同的类型,相邻元素具有前驱后继关系。
  4. Operation
  5. // 初始化操作,建立一个空队列Q
  6. InitQueue(*Q);
  7. // 若队列Q存储,则销毁它。
  8. DestroyQueue(*Q);
  9. // 将队列Q清空
  10. ClearQueue(*Q);
  11. // 若队列为空则返回true,否则返回false
  12. QueueEmpty(Q);
  13. // 若队列Q存在且非空,用e返回队列Q的队头元素
  14. GetHead(Q, *e);
  15. // 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
  16. EnQueue(*Q, e);
  17. // 删除队列Q中的队头元素,并用e返回其值
  18. DeQueue(*Q, *e);
  19. // 返回队列Q的元素个数
  20. QueueLength(Q);
  21. endADT

2.3 队列顺序模型和链表模型关系分析

2.4 队列的顺序存储

2.4.1 基本概念

队列也是一种特殊的线性表;可以用线性表顺序存储来模拟队列。

2.4.2 设计与实现

示例代码:

SqQueue.h

  1. #ifndef _SQQUEUE_H
  2. #define _SQQUEUE_H
  3. #define MAXSIZE 50
  4. typedef int EnumType;
  5. typedef struct _SQQUEUE
  6. {
  7. // 尾节点指针
  8. int rear;
  9. // 头结点指针
  10. int front;
  11. EnumType data[MAXSIZE];
  12. }SqQueue;
  13. // 初始化操作,建立一个空队列Q
  14. void InitQueue(SqQueue *Q);
  15. // 将队列Q清空
  16. void ClearQueue(SqQueue *Q);
  17. // 若队列为空则返回true,否则返回false
  18. int QueueEmpty(SqQueue Q);
  19. // 若队列Q存在且非空,用e返回队列Q的队头元素
  20. void GetHead(SqQueue Q, EnumType* e);
  21. // 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
  22. void EnQueue(SqQueue *Q, EnumType e);
  23. // 删除队列Q中的队头元素,并用e返回其值
  24. void DeQueue(SqQueue *Q, EnumType* e);
  25. // 返回队列Q的元素个数
  26. int QueueLength(SqQueue Q);
  27. #endif //_SQQUEUE_H

SqQueue.c

  1. #include "SqQueue.h"
  2. #include <string.h>
  3. void InitQueue(SqQueue *Q)
  4. {
  5. Q->rear = Q->front = 0;
  6. memset(Q->data, 0, sizeof(Q->data));
  7. }
  8. void ClearQueue(SqQueue *Q)
  9. {
  10. Q->rear = Q->front = 0;
  11. memset(Q->data, 0, sizeof(Q->data));
  12. }
  13. int QueueEmpty(SqQueue Q)
  14. {
  15. if (Q.rear == Q.front)
  16. {
  17. return 1;
  18. }
  19. return 0;
  20. }
  21. // 返回队首元素的值,但不删除该元素
  22. void GetHead(SqQueue Q, EnumType* e)
  23. {
  24. // 队列为空
  25. if (Q.rear == Q.front)
  26. {
  27. return;
  28. }
  29. *e = Q.data[Q.front];
  30. }
  31. // 在队尾压入新元素
  32. void EnQueue(SqQueue *Q, EnumType e)
  33. {
  34. // 队列已经满了
  35. if (Q->rear -1 == MAXSIZE)
  36. {
  37. return;
  38. }
  39. else
  40. {
  41. // 赋值
  42. Q->data[Q->rear] = e;
  43. // 队尾上移
  44. Q->rear++;
  45. }
  46. }
  47. // 删除队列首元素
  48. void DeQueue(SqQueue *Q, EnumType* e)
  49. {
  50. // 队列为空
  51. if (Q->rear == Q->front)
  52. {
  53. return;
  54. }
  55. // 赋值
  56. *e = Q->data[Q->front];
  57. // front指针上移
  58. Q->front++;
  59. }
  60. int QueueLength(SqQueue Q)
  61. {
  62. return Q.rear;
  63. }

main.c

  1. #include "SqQueue.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. void main()
  5. {
  6. // 队列变量
  7. SqQueue q;
  8. int i = -1;
  9. // 初始化队列
  10. InitQueue(&q);
  11. // 入队列
  12. for (i = 0; i < 5; ++i)
  13. {
  14. EnQueue(&q, i+1);
  15. }
  16. printf("Queue size = %d\n", QueueLength(q));
  17. // 删除全部节点
  18. while (QueueEmpty(q) != 1)
  19. {
  20. int temp;
  21. // 取栈顶元素
  22. GetHead(q, &temp);
  23. printf("Queue head value = %d\n",temp);
  24. // 删除栈顶元素
  25. DeQueue(&q, &temp);
  26. printf("Delete stacktop elem is: %d\n", temp);
  27. }
  28. system("pause");
  29. }

运行结果:

2.5 队列的链序存储设计与实现

2.5.1 基本概念

队列也是一种特殊的线性表;可以用线性表链式存储来模拟队列的链式存储。

2.5.2 设计与实现

示例代码:

LinkQueue.h

  1. #ifndef _LINKQUEUE_H
  2. #define _LINKQUEUE_H
  3. typedef struct _NODE
  4. {
  5. struct _NODE* next;
  6. }Node;
  7. typedef struct
  8. {
  9. // 长度
  10. int length;
  11. // 尾节点指针
  12. Node *rear;
  13. // 头结点指针
  14. Node *front;
  15. }LinkQueue;
  16. // 初始化操作,建立一个空队列Q
  17. void InitQueue(LinkQueue *Q);
  18. // 将队列Q清空
  19. void ClearQueue(LinkQueue *Q);
  20. // 若队列为空则返回true,否则返回false
  21. int QueueEmpty(LinkQueue Q);
  22. // 若队列Q存在且非空,用e返回队列Q的队头元素
  23. void GetHead(LinkQueue Q, Node** e);
  24. // 若队列Q存在,插入新元素e到队列Q中并成为队尾元素。
  25. void EnQueue(LinkQueue *Q, Node* e);
  26. // 删除队列Q中的队头元素,并用e返回其值
  27. void DeQueue(LinkQueue *Q, Node** e);
  28. // 返回队列Q的元素个数
  29. int QueueLength(LinkQueue Q);
  30. #endif //_LINKQUEUE_H

LinkQueue.c

  1. #include "LinkQueue.h"
  2. #include <stdio.h>
  3. void InitQueue(LinkQueue *Q)
  4. {
  5. Q->length = 0;
  6. Q->rear = NULL;
  7. Q->front = NULL;
  8. }
  9. void ClearQueue(LinkQueue *Q)
  10. {
  11. while (Q->length)
  12. {
  13. Node* p;
  14. DeQueue(Q, &p);
  15. }
  16. }
  17. int QueueEmpty(LinkQueue Q)
  18. {
  19. if (Q.length == 0)
  20. {
  21. return 1;
  22. }
  23. return 0;
  24. }
  25. // 链表的头部为队头, 尾部为队尾
  26. void GetHead(LinkQueue Q, Node** e)
  27. {
  28. // 错误处理
  29. if (Q.length == 0)
  30. {
  31. return;
  32. }
  33. *e = Q.front;
  34. }
  35. void EnQueue(LinkQueue *Q, Node* e)
  36. {
  37. if (Q->length == 0)
  38. {
  39. // 空链表
  40. Q->rear = Q->front = e;
  41. }
  42. else
  43. {
  44. // 新节点放到队尾
  45. Q->rear->next = e;
  46. // rear指向最后一个节点
  47. Q->rear = e;
  48. }
  49. // 长度
  50. Q->length++;
  51. }
  52. void DeQueue(LinkQueue *Q, Node** e)
  53. {
  54. if (Q->length == 0)
  55. {
  56. // 空链表
  57. return;
  58. }
  59. // 赋值
  60. *e = Q->front;
  61. // front指针后移
  62. Q->front = Q->front->next;
  63. // 长度
  64. Q->length--;
  65. if (Q->length == 0)
  66. {
  67. // 删除最后一个节点的时候, 尾指针需要指向NULL
  68. Q->rear = NULL;
  69. }
  70. }
  71. int QueueLength(LinkQueue Q)
  72. {
  73. return Q.length;
  74. }

main.c

  1. #include "LinkQueue.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. void main()
  5. {
  6. // 业务节点
  7. typedef struct _tag_value
  8. {
  9. // 包含一个链表节点
  10. Node node;
  11. // 数据
  12. int v;
  13. }Value;
  14. Value val[5];
  15. // 队列变量
  16. LinkQueue q;
  17. int i = -1;
  18. // init
  19. InitQueue(&q);
  20. for (i = 0; i < 5; ++i)
  21. {
  22. val[i].v = i + 20;
  23. // 入队列
  24. EnQueue(&q, &val[i].node);
  25. }
  26. printf("Queue size = %d\n", QueueLength(q));
  27. // 删除全部节点
  28. while (QueueEmpty(q) != 1)
  29. {
  30. // 取出队头元素
  31. Node* p;
  32. Value* pp;
  33. GetHead(q, &p);
  34. pp = (Value*)p;
  35. printf("Queue head value = %d\n", pp->v);
  36. // 出队列
  37. DeQueue(&q, &p);
  38. pp = (Value*)p;
  39. printf("Delete Queue head value = %d\n", pp->v);
  40. }
  41. system("pause");
  42. }

运行结果:

C++ 数据结构 2:栈和队列的更多相关文章

  1. 学习javascript数据结构(一)——栈和队列

    前言 只要你不计较得失,人生还有什么不能想法子克服的. 原文地址:学习javascript数据结构(一)--栈和队列 博主博客地址:Damonare的个人博客 几乎所有的编程语言都原生支持数组类型,因 ...

  2. python数据结构之栈与队列

    python数据结构之栈与队列 用list实现堆栈stack 堆栈:后进先出 如何进?用append 如何出?用pop() >>> >>> stack = [3, ...

  3. [ACM训练] 算法初级 之 数据结构 之 栈stack+队列queue (基础+进阶+POJ 1338+2442+1442)

    再次面对像栈和队列这样的相当基础的数据结构的学习,应该从多个方面,多维度去学习. 首先,这两个数据结构都是比较常用的,在标准库中都有对应的结构能够直接使用,所以第一个阶段应该是先学习直接来使用,下一个 ...

  4. python数据结构之栈、队列的实现

    这个在官网中list支持,有实现. 补充一下栈,队列的特性: 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIF ...

  5. PHP数据结构:栈、队列、堆、固定数组

    数据结构:栈 队列: 堆: 固定尺寸的数组:

  6. 算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)

    数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用.因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队列.本篇博客其实就是<数据结构之线 ...

  7. 数据结构之栈和队列及其Java实现

    栈和队列是数据结构中非常常见和基础的线性表,在某些场合栈和队列使用很多,因此本篇主要介绍栈和队列,并用Java实现基本的栈和队列,同时用栈和队列相互实现. 栈:栈是一种基于“后进先出”策略的线性表.在 ...

  8. python——python数据结构之栈、队列的实现

    这个在官网中list支持,有实现. 补充一下栈,队列的特性: 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIF ...

  9. JS数据结构的栈和队列操作

    数据结构:列表.栈.队列.链表.字典.散列.图和二叉查找树! 排序算法:冒牌.选择.插入.希尔.归并和快速! 查找算法:顺序查找和二分查找 在平时工作中,对数组的操作很是平常,它提供了很多方法使用,比 ...

  10. 【PHP数据结构】栈和队列的应用

    通过栈和队列的学习,我们似乎会感觉到其实数据结构还是非常简单的嘛.当然,这只是一个开始,我们从顺序表.链表开始,到现在的栈和队列,其实都是为了将来在铺路.在树和图的遍历算法中,都可以见到栈和队列的身影 ...

随机推荐

  1. 感觉学java学到自己的瓶颈期了,各种框架乱七八糟,感觉好乱。该怎么办!?

    通常我们都会有这样的一个疑问! 解决办法 这时候,你需要的是分清条理,重整知识架构 GitHub开源社区有一个这样的项目,我觉得非常好,很适合Java有基础但是想进阶提升的人. 项目简介 本期介绍的开 ...

  2. redis协议规范

    好多年前看过redis的代码,那个时候还是2.6的版本,集群和哨兵还没加入正式代码,这几年redis发展的好快.简略翻译一篇文章redis的https://redis.io/topics/protoc ...

  3. linux centos 05

    centos7安装mariadb 1.yum  得配置yum源,配置阿里云的 两个 yum源  ,阿里云的yum源中,会有 mariadb的软件包 阿里云的yum仓库中,mariadb版本如下 mar ...

  4. pytest文档43-元数据使用(pytest-metadata)

    前言 什么是元数据?元数据是关于数据的描述,存储着关于数据的信息,为人们更方便地检索信息提供了帮助. pytest 框架里面的元数据可以使用 pytest-metadata 插件实现.文档地址http ...

  5. 使用docker安装E

     环境 虚拟机软件VmWare15.5 Centos7.0 安装docker yum install docker

  6. 第十五章 nginx七层负载均衡

    一.Nginx负载均衡 1.为什么做负载均衡 当我们的Web服务器直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台Web服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到 ...

  7. Python语言应用解析,如何入门学Python?

    Python在机器学习人工智能领域非常流行,可以说是算法工程师的标配编程语言.Python语言广泛应用在web开发.大数据开发.人工智能开发.机器学习.后端开发等领域之中,近几年Python语言的趋势 ...

  8. pytest-pyppeteer:在pytest中运行pyppeteer

    pytest-pyppeteer pytest-pyppeteer是我写的一个 pytest 插件,支持在 pytest 中运行pyppeteer,起因是为了解决工作中的一个测试需求,现在将其开源并做 ...

  9. 使用经纬度得到位置Geocorder

    先得到经纬度再用geocorder 显示位置,需要手机打开位置权限,使用GPS的话把注释去掉,GPS在室内很容易收不到信号,得到位置为空 public class MainActivity exten ...

  10. Redis【一】 RESP协议

    https://redis.io/topics/protocol RESP:redis序列化协议 client-server交流 二进制安全的 网络层 client端建立tcp连接到Server po ...