• Day 64 栈的顺序和链式存储 队列


    1.栈的概念:

    栈( stack )又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新 元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶 元素删除掉,使其相邻的元素成为新的栈顶元素。
    Stack ):是只允许在一端进行插入或删除的线性表。首先栈是一 种线性表, 但限定这种线性表只能在某一端进行插入和删除操作。
    栈顶 Top ):线性表允许进行插入删除的那一端。
    栈底 Bottom ):固定的,不允许进行插入和删除的另一端。
    空栈 :不含任何元素的空表。
    栈又称为后进先出( Last In First Out )的线性表,简称 LIFO 结构
    特性:
    它的特殊之处在于限制了这个线性表的插入和删除的位置 , 它始终只在栈顶进行。这也就使
    : == 栈底是固定的 , 最先进栈的只能在栈底 ==
    对栈的操作:
    示例如下:
    1. #include
    2. #include
    3. #include
    4. #define MAX_SIZE 50
    5. typedef struct{
    6. void *data[MAX_SIZE];
    7. int size;
    8. }Stack;
    9. typedef struct{
    10. char name[15];
    11. int age;
    12. char breed[10];
    13. }Stu;
    14. Stack *initstack(void){
    15. Stack *stack=(Stack *)malloc(sizeof(Stack));
    16. if(stack==NULL){
    17. printf("malloc error.\n");
    18. return NULL;
    19. }
    20. for(int i=0;i
    21. stack->data[i]=NULL;
    22. }
    23. stack->size=0;
    24. return stack;
    25. }
    26. void pushstack(Stack *stack,void *data){
    27. if(stack==NULL){
    28. return;
    29. }
    30. if(stack->size==MAX_SIZE){
    31. return;
    32. }
    33. if(data==NULL){
    34. return;
    35. }
    36. stack->data[stack->size]=data;
    37. stack->size++;
    38. }
    39. void popstack(Stack *stack){
    40. if(stack==NULL){
    41. return;
    42. }
    43. if(stack->size==0){
    44. return;
    45. }
    46. stack->data[stack->size-1]=NULL;
    47. stack->size--;
    48. }
    49. void *topelement(Stack *stack){
    50. if(stack==NULL){
    51. return NULL;
    52. }
    53. if(stack->size==0){
    54. return NULL;
    55. }
    56. return stack->data[stack->size-1];
    57. }
    58. int isempty(Stack *stack){
    59. if(stack==NULL){
    60. return 0;
    61. }
    62. if(stack->size==0){
    63. return 0;
    64. }
    65. return 1;
    66. }
    67. int sizestack(Stack *stack){
    68. if(stack==NULL){
    69. return -1;
    70. }
    71. return stack->size;
    72. }
    73. void clearstack(Stack *stack){
    74. if(stack==NULL){
    75. return;
    76. }
    77. for(int i=0;isize;i++){
    78. stack->data[i]=NULL;
    79. }
    80. stack->size=0;
    81. }
    82. void freestack(Stack *stack){
    83. if(stack==NULL){
    84. return;
    85. }
    86. free(stack);
    87. }
    88. int main(){
    89. Stack *stack=initstack();
    90. Stu p1={"洛羽晨",18,"人类"};
    91. Stu p2={"虚构康",20,"不详"};
    92. Stu p3={"丁真",23,"出生"};
    93. Stu p4={"谷爱凌",22,"剑冢"};
    94. pushstack(stack,&p1);
    95. pushstack(stack,&p2);
    96. pushstack(stack,&p3);
    97. pushstack(stack,&p4);
    98. while(sizestack(stack)>0){
    99. Stu *p=(Stu *)topelement(stack);
    100. printf("name:%s,age=%d,breed=%s\n",p->name,p->age,p->breed);
    101. popstack(stack);
    102. }
    103. freestack(stack);
    104. return 0;
    105. }

    2.栈的链式存储结构:

    概念:上面讲的是栈的顺序存储结构,相当于一个线性表,只是操作位置有限制。链式存储结构也就是链表形式的栈。它和链表的结构是一样的,操作方式和上面的一样。

    操作:

    示例如下:

    1. #include "linkstack.h"
    2. typedef struct
    3. {
    4. char name[64];
    5. int age;
    6. int score;
    7. }Person;
    8. //打印函数
    9. void my_print(void *data)
    10. {
    11. Person *p=(Person *)data;
    12. printf("name:%s age:%d score:%d\n",p->name,p->age,p->score);
    13. }
    14. int main()
    15. {
    16. //创建链表
    17. LinkStack *stack=init_linkstack();
    18. //获取链表长度
    19. printf("stack 长度:%d\n",size_linkstack(stack));
    20. //创建数据
    21. //创建数据
    22. Person p1={"aaa",10,80};
    23. Person p2={"bbb",11,81};
    24. Person p3={"ccc",12,82};
    25. Person p4={"ddd",13,83};
    26. //入栈
    27. push_linkstack(stack, &p1);
    28. push_linkstack(stack, &p2);
    29. //打印
    30. print_linkstack(stack, my_print);
    31. printf("\n");
    32. //入栈
    33. push_linkstack(stack, &p3);
    34. push_linkstack(stack, &p4);
    35. //打印
    36. print_linkstack(stack, my_print);
    37. printf("\n");
    38. //出栈
    39. void *data=pop_linkstack(stack);
    40. my_print(data);
    41. printf("\n");
    42. //打印
    43. print_linkstack(stack, my_print);
    44. printf("\n");
    45. //获取链表长度
    46. printf("stack 长度:%d\n",size_linkstack(stack));
    47. //返回第一个结点
    48. Person *p=(Person *)top_element(stack);
    49. printf("top_element:name-%s,age-%d,score-%d\n",p->name,p->age,p->score);
    50. //销毁
    51. free_linkstack(stack);
    52. return 0;
    53. }
    54. #include "linkstack.h"
    55. //初始链表
    56. LinkStack *init_linkstack(void)
    57. {
    58. LinkStack *stack=(LinkStack *)malloc(sizeof(LinkStack));
    59. stack->size=0;
    60. //头结点
    61. stack->head=(LinkNode *)malloc(sizeof(LinkNode));
    62. stack->head->data=NULL;
    63. stack->head->next=NULL;
    64. return stack;
    65. }
    66. //指定位置插入
    67. void push_linkstack(LinkStack *stack, void *data)
    68. {
    69. if(stack == NULL)
    70. {
    71. return ;
    72. }
    73. if(data == NULL)
    74. {
    75. return ;
    76. }
    77. //创建新的结点
    78. LinkNode *newnode=(LinkNode *)malloc(sizeof(LinkNode));
    79. newnode->data=data;
    80. newnode->next=NULL;
    81. //找结点
    82. //辅助指针变量
    83. LinkNode *pcurrent=stack->head;
    84. //新结点插入链表
    85. newnode->next=pcurrent->next;
    86. pcurrent->next=newnode;
    87. stack->size++;
    88. }
    89. //删除指定位置的值
    90. void *pop_linkstack(LinkStack *stack)
    91. {
    92. if(stack == NULL)
    93. {
    94. return NULL;
    95. }
    96. //找结点
    97. //辅助指针变量
    98. LinkNode *pcurrent=stack->head;
    99. //删除结点
    100. LinkNode *delnode=pcurrent->next;
    101. pcurrent->next=delnode->next;
    102. void *data=delnode->data;
    103. free(delnode);
    104. stack->size--;
    105. return data;
    106. }
    107. //获取链表长度
    108. int size_linkstack(LinkStack *stack)
    109. {
    110. return stack->size;
    111. }
    112. //返回栈顶元素数据域
    113. void *top_element(LinkStack *stack)
    114. {
    115. return stack->head->next->data;
    116. }
    117. //打印栈内所有内容
    118. void print_linkstack(LinkStack *stack, printlinknode print)
    119. {
    120. if(stack == NULL)
    121. {
    122. return ;
    123. }
    124. //辅助指针变量
    125. LinkNode *pcurrent=stack->head->next;
    126. while(pcurrent!=NULL)
    127. {
    128. print(pcurrent->data);
    129. pcurrent=pcurrent->next;
    130. }
    131. }
    132. //释放链表内存
    133. void free_linkstack(LinkStack *stack)
    134. {
    135. if(stack == NULL)
    136. {
    137. return ;
    138. }
    139. //辅助指针变量
    140. LinkNode *pcurrent=stack->head;
    141. while(pcurrent!=NULL)
    142. {
    143. //缓存下一个结点
    144. LinkNode *pnext=pcurrent->next;
    145. free(pcurrent);
    146. pcurrent=pnext;
    147. }
    148. //释放链表内存
    149. stack->size=0;
    150. free(stack);
    151. }
    152. #ifndef LINKLIST_H
    153. #define LINKLIST_H
    154. #include
    155. #include
    156. #include
    157. #endif
    158. //结点结构体
    159. typedef struct NODE
    160. {
    161. void *data;
    162. struct NODE *next;
    163. }LinkNode;
    164. //栈表结构体
    165. typedef struct
    166. {
    167. LinkNode *head;
    168. int size;
    169. }LinkStack;
    170. //打印函数指针
    171. typedef void(*printlinknode)(void *);
    172. //初始栈表
    173. LinkStack *init_linkstack(void);
    174. //入栈
    175. void push_linkstack(LinkStack *stack, void *data);
    176. //出栈
    177. void *pop_linkstack(LinkStack *stack);
    178. //获取链表长度
    179. int size_linkstack(LinkStack *stack);
    180. //返回第一个结点
    181. void *top_element(LinkStack *stack);
    182. //打印栈内结点
    183. void print_linkstack(LinkStack *stack, printlinknode print);
    184. //释放栈内存
    185. void free_linkstack(LinkStack *stack);

    2.队列的概念:

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

     

    队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中 删除, == 故队列又称为先进先出( FIFO—first in first out 线性表
    2.对队列的操作: 增删改查
    示例如下:
    1. #include
    2. #include
    3. #define MAX_SIZE 1024
    4. typedef struct
    5. {
    6. void *data[MAX_SIZE];
    7. int size;
    8. }Queue;
    9. //初始化
    10. Queue * init_queue(void)
    11. {
    12. Queue *queue=(Queue *)malloc(sizeof(Queue));
    13. for(int i=0;i
    14. {
    15. queue->data[i]=NULL;
    16. }
    17. queue->size=0;
    18. return queue;
    19. }
    20. //入队
    21. void push_queue(Queue *queue, void *data)
    22. {
    23. //数组左边当做对头
    24. if(queue==NULL)
    25. {
    26. return ;
    27. }
    28. if(data==NULL)
    29. {
    30. return ;
    31. }
    32. queue->data[queue->size]=data;
    33. queue->size++;
    34. }
    35. //返回对头元素
    36. void *front_queue(Queue *queue)
    37. {
    38. if(queue==NULL)
    39. {
    40. return NULL;
    41. }
    42. if(queue->size==0)
    43. {
    44. return NULL;
    45. }
    46. return queue->data[0];
    47. }
    48. //出队
    49. void pop_queue(Queue *queue)
    50. {
    51. //需要移动元素
    52. if(queue==NULL)
    53. {
    54. return ;
    55. }
    56. if(queue->size==0)
    57. {
    58. return ;
    59. }
    60. for(int i=0;isize-1;i++)
    61. {
    62. queue->data[i]=queue->data[i+1];
    63. }
    64. queue->size--;
    65. }
    66. //返回队尾元素
    67. void *back_queue(Queue *queue)
    68. {
    69. if(queue==NULL)
    70. {
    71. return NULL;
    72. }
    73. if(queue->size==0)
    74. {
    75. return NULL;
    76. }
    77. return queue->data[queue->size-1];
    78. }
    79. //返回大小
    80. int size_queue(Queue *queue)
    81. {
    82. if(queue==NULL)
    83. {
    84. return -1;
    85. }
    86. return queue->size;
    87. }
    88. //清空队列
    89. void clear_queue(Queue *queue)
    90. {
    91. if(queue==NULL)
    92. {
    93. return ;
    94. }
    95. while(queue->size>0)
    96. {
    97. queue->size--;
    98. queue->data[queue->size]=NULL;
    99. }
    100. }
    101. //销毁
    102. void free_queue(Queue *queue)
    103. {
    104. if(queue==NULL)
    105. {
    106. return ;
    107. }
    108. free(queue);
    109. }
    110. typedef struct
    111. {
    112. char name [64];
    113. int age;
    114. }Person;
    115. int main()
    116. {
    117. //创建队列
    118. Queue *queue=init_queue();
    119. //创建数据
    120. Person p1={"aaa",10};
    121. Person p2={"bbb",10};
    122. Person p3={"ccc",10};
    123. Person p4={"ddd",10};
    124. //入队
    125. push_queue(queue,&p1);
    126. push_queue(queue,&p2);
    127. push_queue(queue,&p3);
    128. push_queue(queue,&p4);
    129. //取出对尾元素
    130. Person *p=(Person *)back_queue(queue);
    131. printf("name:%s, age=%d\n",p->name,p->age);
    132. printf("\n");
    133. clear_queue(queue);
    134. printf("\n");
    135. //入队
    136. push_queue(queue,&p1);
    137. push_queue(queue,&p2);
    138. push_queue(queue,&p3);
    139. push_queue(queue,&p4);
    140. //输出
    141. while(size_queue(queue)>0)
    142. {
    143. //取出对头元素
    144. Person *p=(Person *)front_queue(queue);
    145. printf("name:%s, age=%d\n",p->name,p->age);
    146. //出队
    147. pop_queue(queue);
    148. }
    149. //销毁队列
    150. free_queue(queue);
    151. return 0;
    152. }

  • 相关阅读:
    stm32之dma
    标记蛋白用PEG衍生物Fmoc-PEG4-NHS ester,1314378-14-7
    每日一博 - 图解进程(Process)和线程(Thread)区别联系
    C++基础——第1章:C++初探
    antv G6在vue项目中的实践总结
    DataGridView 控件分页
    Inno Setup 选择安装路径的问题
    python的类属性和实例属性
    【ETL工具】本地环境IDEA远程DEBUG调试Flume代码
    【JavaSE】基础语法知识汇总
  • 原文地址:https://blog.csdn.net/m0_60247706/article/details/127794234