• 数据结构——栈和队列


    目录

    一、栈

    1.栈的概念及结构栈

    2.栈的实现

    二、队列

    1.队列的概念及结构队列

    2.队列的实现


    一、栈

    1.栈的概念及结构栈

    一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。不同于我们所说的栈区,栈是一种数据结构,栈区是操作系统的内容。

    进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出的原则。

    压栈:栈的插入操作叫做入栈,入数据在栈顶。

    出栈:栈的删除操作叫做出栈,出数据也在栈顶。

    相当于只能尾插尾删的顺序表

    2.栈的实现

    栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些,因为数组在尾上插入数据的代价比较小。

    这里只需要完全使用顺序表的增删查改的操作函数即可,包括:顺序表的初始化,扩容,尾插,尾删,判空,元素个数等,但是注意栈中的元素被使用后会立刻出栈。

    stack.h

    1. #define TYPE int
    2. typedef struct stackzone
    3. {
    4. TYPE* arr;
    5. int volume;
    6. int top;//top是栈顶的元素编号,相当于size(不是下标)
    7. }stack;
    8. //初始化栈
    9. void initstack(stack* p);
    10. //扩容
    11. void enlarge(stack* p);
    12. //栈只能尾插数据,插入数据
    13. void stackpush(stack* p, TYPE x);
    14. //栈也只能尾删数据,删除数据
    15. void stackpop(stack* p);
    16. //找到栈顶的元素
    17. TYPE stacktop(stack* p);
    18. //判断栈是否为空
    19. bool stackempty(stack* p);
    20. //判断栈中元素的多少
    21. int stacksize(stack* p);

     stack.c

    1. #include"stack.h"
    2. //初始化
    3. void InitSeqlist(SList* p)
    4. {
    5. assert(p);
    6. p->size = 0;
    7. p->volume = 0;
    8. p->SL = NULL;
    9. }
    10. //销毁
    11. void destory(SList* p)
    12. {
    13. assert(p);
    14. free(p->SL);
    15. p->size = 0;
    16. p->volume = 0;
    17. p->SL = NULL;
    18. }
    19. //扩容
    20. void enlarge(SList* p)
    21. {
    22. if (p->size == p->volume)//容量与数据量相同扩容,每次扩容当前二倍大小的空间
    23. {
    24. assert(p);
    25. int newvolume = (p->volume == 0 ? 4 : 2 * p->volume);
    26. //定义一个变量保存新容量的大小,容量为0扩容4个,不为0扩容二倍
    27. TYPE* p1 = (TYPE*)realloc(p->SL, newvolume*sizeof(TYPE));
    28. //容量为0时,malloc与realloc效果相同
    29. if (p1 == NULL)
    30. {
    31. perror("realloc");
    32. return;
    33. }
    34. p->SL = p1;
    35. p->volume = newvolume;
    36. }
    37. }
    38. void Seqlist_back_push(SList* p, TYPE a)
    39. {
    40. assert(p);
    41. enlarge(p);//函数负责在适当时负责扩容
    42. *((p->SL) + (p->size)) = a;//此时size正好是应插入位置的下标
    43. p->size++;//size 自增
    44. }
    45. void Seqlist_front_push(SList* p, TYPE a)
    46. {
    47. assert(p);
    48. enlarge(p);//函数负责在适当时负责扩容
    49. int i = p->size;
    50. while (i >= 0)
    51. {
    52. p->SL[i] = p->SL[i - 1];//顺序表的头插需要将所有数据从后向前后挪一位
    53. i--;
    54. }
    55. *(p->SL) = a;//插入数据
    56. p->size++;//自增
    57. }
    58. void Seqlist_back_pop(SList* p)
    59. {
    60. assert(p);
    61. p->size--;//只需要减少有效数据的个数,自减即可
    62. }
    63. void Seqlist_front_pop(SList* p)
    64. {
    65. assert(p);
    66. int i = 0;
    67. for (i = 0; i < p->size - 1; i++)
    68. {
    69. p->SL[i] = p->SL[i + 1];//把每一个数据从前向后挪一位
    70. }
    71. p->size--;
    72. }
    73. void print(SList* p)
    74. {
    75. assert(p);
    76. int i = 0;
    77. for (i = 0; i < p->size; i++)
    78. {
    79. printf("%d ", p->SL[i]);
    80. }
    81. printf("\n");
    82. }
    83. int Seqlist_search_element(SList* p, TYPE a)
    84. {
    85. assert(p);
    86. int i = 0;
    87. for (i = 0; i < p->size; i++)
    88. {
    89. if (p->SL[i] == a)
    90. {
    91. return i;//找到了返回下标
    92. }
    93. }
    94. return -1;//找不到返回-1
    95. }
    96. void Seqlist_modify_element(SList* p, size_t pos, TYPE b)
    97. {
    98. p->SL[pos] = b;//改变某个下标对应的数据
    99. }
    100. //顺序表在pos位置插入a
    101. void Seqlist_insert_element(SList* p, int pos, TYPE a)//包括pos从后向前后挪一位再赋值
    102. {
    103. assert(p);
    104. assert(pos < (p->size));
    105. enlarge(p);
    106. int i = pos;
    107. for (i = pos; i < p->size; i++)
    108. {
    109. p->SL[i + 1] = p->SL[i];
    110. }
    111. p->SL[pos] = a;
    112. p->size++;
    113. }
    114. //顺序表删除pos位置的值
    115. void Seqlist_delete_element(SList* p, int pos)
    116. {
    117. int i = 0;
    118. for (i = pos; i < p->size - 1;i++)
    119. {
    120. p->SL[i] = p->SL[i + 1];//从前向后覆盖pos后的数据
    121. }
    122. p->size--;//自减
    123. }

    test.c

    1. #include"stack.h"
    2. void test()
    3. {
    4. stack s;
    5. stack* p = &s;
    6. initstack(p);
    7. stackpush(p, 1);
    8. stackpush(p, 2);
    9. stackpush(p, 3);
    10. stackpush(p, 4);
    11. printf("%d\n",stacktop(p));//使用
    12. stackpop(p);//出栈
    13. printf("%d\n", stacktop(p));//使用
    14. stackpop(p);//出栈
    15. //栈在使用后就会删除
    16. stackpop(p);
    17. stackpop(p);
    18. printf("%d\n",stacksize(p));
    19. stackdestory(p);
    20. }
    21. int main()
    22. {
    23. test();
    24. return 0;
    25. }

    二、队列

    1.队列的概念及结构队列

    只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列中数据具有先进先出入的性质。

    就像排队一样,有一群人在银行柜台前排队,有的办完业务离开了,就相当于出队列;又有的人在后面加入排队,相当于入队列,一头进一头出。

    入队列:进行插入操作的一端称为队尾,将数据尾插即为入队列。

    出队列:进行删除操作的一端称为队头,在队头删除数据即为出队列。

    2.队列的实现

    队列的实现队列可以数组或链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

     这里只需要完全使用链表的增删查改的操作函数即可,包括:顺序表的初始化,尾插,头删,判空,元素个数等

    queue.h

    1. #include
    2. #include
    3. #include
    4. #include
    5. #define TYPE int
    6. typedef struct QueueStructre
    7. {
    8. int size;
    9. struct queueNode* front;
    10. struct queueNode* back;
    11. }queue;
    12. typedef struct queueNode
    13. {
    14. TYPE data;
    15. struct queueNode* next;
    16. }Node;
    17. //初始化队列
    18. void initqueue(queue* p);
    19. //初始化
    20. void initqueue(queue* p);
    21. //初始化
    22. void initqueue(queue* p);
    23. //队列只能尾插
    24. void queuepush(queue* p, TYPE x);
    25. //队列只能头删
    26. void queuepop(queue* p);
    27. //销毁
    28. void destory(queue* p);
    29. //判断是否为空
    30. bool QueueEmpty(queue* p);
    31. //计算元素个数
    32. int QueueSize(queue* p);
    33. //找首元素
    34. TYPE queuefront(queue* p);
    35. //找尾元素
    36. TYPE queueback(queue* p);

     queue.c

    1. #include"queue.h"
    2. //初始化队列
    3. void initqueue(queue* p)
    4. {
    5. p->size = 0;
    6. p->front = NULL;
    7. p->back = NULL;
    8. }
    9. //队列只能尾插
    10. void queuepush(queue* p, TYPE x)
    11. {
    12. Node* newcode = (Node*)malloc(sizeof(Node));
    13. if (newcode == NULL)
    14. {
    15. perror("malloc fail");
    16. return;
    17. }
    18. newcode->data = x;
    19. newcode->next = NULL;
    20. if (QueueEmpty(p))
    21. {
    22. p->front = newcode;
    23. p->back = newcode;
    24. }
    25. else
    26. {
    27. p->back->next = newcode;
    28. p->back = newcode;
    29. }
    30. p->size++;
    31. }
    32. //队列只能头删
    33. void queuepop(queue* p)
    34. {
    35. if (QueueEmpty(p))
    36. {
    37. return;
    38. }
    39. else
    40. {
    41. Node* n1 = p->front;
    42. Node* n2 = n1->next;
    43. p->front = n2;
    44. free(n1);
    45. p->size--;
    46. }
    47. }
    48. //销毁
    49. void destory(queue* p)
    50. {
    51. Node* cur = p->front;
    52. while (cur)
    53. {
    54. Node* next = cur->next;
    55. free(cur);
    56. cur = next;
    57. }
    58. p->front = NULL;
    59. p->back = NULL;
    60. p->size = 0;
    61. }
    62. //判断是否为空
    63. bool QueueEmpty(queue* p)
    64. {
    65. return (p->size == 0);
    66. }
    67. //计算元素个数
    68. int QueueSize(queue* p)
    69. {
    70. return p->size;
    71. }
    72. //找首元素
    73. TYPE queuefront(queue* p)
    74. {
    75. return p->front->data;
    76. }
    77. //找尾元素
    78. TYPE queueback(queue* p)
    79. {
    80. return p->back->data;
    81. }

    test.c

    1. #include"queue.h"
    2. void test1()
    3. {
    4. queue s;
    5. queue* p = &s;
    6. initqueue(p);
    7. queuepush(p,1);
    8. queuepush(p,2);
    9. queuepush(p,3);
    10. printf("%d\n", queuefront(p));
    11. printf("%d\n", queueback(p));
    12. printf("%d\n", QueueSize(p));
    13. queuepop(p);
    14. queuepush(p, 4);
    15. printf("%d\n", queuefront(p));
    16. printf("%d\n", queueback(p));
    17. destory(p);
    18. }
    19. int main()
    20. {
    21. test1();
    22. return 0;
    23. }

    除此之外,还有一个特殊的循环队列,讲解如下:循环队列的实现_聪明的骑士的博客-CSDN博客

  • 相关阅读:
    [6]辨析云计算交付模型IaaS PaaS SaaS和云部署模型
    COSCon'22 论坛集锦 1+16个论坛就等你了!
    阿里顶级架构师多年总结的JVM宝典,哪里不会查哪里。
    Python花瓣雨
    算法为屠龙刀,设计模式为倚天剑
    Moonbirds 是什么,为何公售后能迅速出圈 ?
    开启算法之旅:hello world!
    真题集P123---2011年真题(包括力扣662)
    亚马逊云科技 Build On 2022 - AIot 第二季物联网专场实验心得
    linux 用户不在sudoers文件中,此事将被报告
  • 原文地址:https://blog.csdn.net/qq_65285898/article/details/126569114