这两天再学习了数据结构的栈和队列,思想很简单,可能是学习PHP那会没有直接使用栈和队列,写的太少,所以用具体代码实现的时候出现了各种错误,感觉还是C语言功底不行。栈和队列不论在面试中还是笔试中都很重要,下面就介绍一下这两天栈和队列的学习经验

一:栈的学习

基础东西:栈是在表尾进行插入和删除的线性表,由此可知表尾是栈顶,表头为栈底,没有任何元素的栈是空栈。根据栈的结构可以知道:栈修改是按后进先出的原则进行的(LIFO),基本操作有插入、删除、初始化、取栈顶元素,判断是否是空栈等等。

栈的表示和实现:和上一节介绍过的线性表相似栈有两种表示方法(顺序表示和链式表示)因为和线性表类似(特殊的线性表)我只介绍顺序栈的就可以了。

顺序栈:利用一组连续的地址来依次存储栈的各个元素(从栈底到栈顶),用top指针指示栈顶元素,base指针指示栈底元素,所以top=base可以作为空栈的判断。插入一个元素top++,出栈一个元素top--,所以非空栈的指针始终在栈顶元素的下一个位置

顺序栈的结构体表示:

  1. //栈的顺序存储表示
  2. typedef struct{
  3. SElemType *base;//在栈构造之前和销毁后值是NULL
  4. SElemType *top;
  5. int stacksize; //已分配的存储空间
  6. }SqStack;

  下面是我练习的代码,实现了栈的定义、栈的初始化、进栈操作、出栈操作、得到栈顶元素、遍历栈。需要注意的是出栈操作和得到栈顶元素的操作是有区别的,希望对大家栈的学习和回顾有所帮助。代码都是自己练习过的,可以直接运行

  1. /**
  2. * 栈
  3. * @author:zhaoyafei
  4. * @time:2015-6-16
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. //预定义常量
  10. #define OK 1
  11. #define OVERFLOW -2
  12. #define ERROR 0
  13.  
  14. #define STACK_INIT_SIZE 100 //存储空间的初始分配量
  15. #define STACKINCREMENT 10 //存储空间的分配增量stackincrement
  16.  
  17. typedef int SElemType;
  18.  
  19. //栈的顺序存储表示
  20. typedef struct{
  21. SElemType *base;//在栈构造之前和销毁后值是NULL
  22. SElemType *top;
  23. int stacksize; //已分配的存储空间
  24. }SqStack;
  25.  
  26. //栈的初始化操作
  27.  
  28. int InitStack(SqStack &S){
  29. S.base = (int *)malloc(STACK_INIT_SIZE * sizeof(SqStack));
  30. if(!S.base){
  31. exit(OVERFLOW);//分配空间失败
  32. }
  33. S.top = S.base;
  34. S.stacksize = STACK_INIT_SIZE;
  35. return OK;
  36. }
  37.  
  38. //进栈操作
  39. int Push(SqStack &S, int e){
  40. if(S.top - S.base >= S.stacksize){//栈空间已经满
  41. S.base = (int *)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(SqStack));
  42. if(!S.base){
  43. exit(OVERFLOW);//分配失败
  44. }
  45. S.top = S.base + S.stacksize;
  46. S.stacksize += STACKINCREMENT;
  47. }
  48. *S.top++ = e;
  49. return OK;
  50. }
  51.  
  52. //出栈
  53. int Pop(SqStack &S,int &e){
  54. if(S.top != S.base){
  55. e = * --S.top;
  56. return OK;
  57. }else{
  58. exit(OVERFLOW);
  59. }
  60. }
  61.  
  62. //得到顶部元素
  63. void GetElem(SqStack S, int &e){
  64. if(S.top != S.base){
  65. e = * (S.top - );
  66. }else{
  67. exit(OVERFLOW);
  68. }
  69. }
  70.  
  71. //打印出栈各个元素
  72. void PrintfStack(SqStack S){
  73. while(*(S.top-) && S.top != S.base){//证明不是空栈,且有值
  74. S.top = S.top - ;
  75. printf("%d ",*S.top);
  76. }
  77. printf("\n");
  78. }
  79.  
  80. int main(){
  81. int e,i;
  82. int TextData[] = {,,,,,};
  83. SqStack Sa,Sb;
  84. InitStack(Sa);//初始化栈Sa;
  85. for(i = ; i < ; i++){
  86. Push(Sa,TextData[i]);
  87. }
  88. printf("**************栈基本操作*************\n");
  89. //初始化数据
  90. printf("初始化后的Sa:");
  91. PrintfStack(Sa);
  92.  
  93. //得到栈顶元素
  94. GetElem(Sa,e);
  95. printf("Sa栈顶元素是:%d\n",e);
  96.  
  97. //初始化数据
  98. printf("顶部出栈后Sa:");
  99. Pop(Sa,e);
  100. PrintfStack(Sa);
  101. }

二:队列的学习:

队列和栈相反,是一种先进先出(FIFO)的线性表,只能在一端进行插入,一端进行删除

基础:在队列中,进行出入的一端称作队尾,允许删除的一端称作队首。和线性表差不多可以用顺序和链式表示。

双端队列:双端队列是限定插入和删除的操作在表的两端进行的线性表,用的不是很多。

循环队列:百度上解释:”将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量“,其实就是把队列首尾相连,但是要有一定的要求,不是想怎么连就怎么连。

下面给出链表的结构体:

  1. //单链队列
  2. typedef struct QNode{
  3. QElemType data;
  4. struct QNode *next;
  5. }QNode, *QueuePtr;
  6.  
  7. typedef struct{
  8. QueuePtr front;
  9. QueuePtr rear;
  10. }LinkQueue;
  11.  
  12. //循环队列
  13. typedef struct{
  14. QElemType *base;
  15. int front;
  16. int rear;
  17. }SqQueue;

  下面这段代码练习了队列的基本操作:队列结构体定义(比栈的稍微复杂一点)、在队尾插入新元素、删除队头元素、销毁队列、打印队列、循环队列的定义等等,这部分牵涉到好多的指针操作,如果有些困难可以在纸上划出队列的结构,列出指针的操作前后变化,就容易多了(个人感觉如果线性表学好了,这些操作根本不在话下)。需要注意循环队列操作中取余操作:(Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;

废话不多说,下面直接给出具体实现的代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. //头文件
  4. #define ERROR -1
  5. #define OK 2;
  6. #define TRUE 1;
  7. #define OVERFLOW -2;
  8.  
  9. //最大队列长度
  10. #define MAXQSIZE 100
  11.  
  12. typedef int Status;
  13. typedef int QElemType;
  14.  
  15. //单链队列
  16. typedef struct QNode{
  17. QElemType data;
  18. struct QNode *next;
  19. }QNode, *QueuePtr;
  20.  
  21. typedef struct{
  22. QueuePtr front;
  23. QueuePtr rear;
  24. }LinkQueue;
  25.  
  26. //循环队列
  27. typedef struct{
  28. QElemType *base;
  29. int front;
  30. int rear;
  31. }SqQueue;
  32.  
  33. //********************************队列的基本操作*****************************
  34. //初始化队列
  35. Status InitQueue(LinkQueue &Q){
  36. Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));//动态分配空间
  37. if(!Q.front){
  38. exit(ERROR);//分配空间失败
  39. }
  40. Q.front->next = NULL;
  41. return OK;
  42. }
  43.  
  44. //在队尾插入新元素
  45. Status EnQueue(LinkQueue &Q, int e){
  46. QueuePtr p;
  47. p = (QueuePtr)malloc(sizeof(QNode));
  48. if(!p){
  49. exit(ERROR);//分配失败
  50. }
  51. p->data = e;
  52. p->next = NULL;
  53. Q.rear->next = p;
  54. Q.rear = p;
  55. return OK;
  56. }
  57.  
  58. void DestroyQueue(LinkQueue &Q){
  59. if(Q.front != Q.rear){
  60. while(Q.front){
  61. Q.rear = Q.front->next;
  62. free(Q.front);
  63. Q.front = Q.rear;
  64. }
  65. }
  66. }
  67.  
  68. //删除队头元素,并用e返回
  69. Status DeQueue(LinkQueue &Q, int &e){
  70. if(Q.front != Q.rear){//先判断队列是否为空
  71. QueuePtr p;
  72. e = Q.front->next->data;
  73. if(Q.front->next == Q.rear){//队列只有一个元素
  74. p = Q.rear;
  75. Q.rear = Q.front;
  76. Q.front->next = NULL;
  77. }else{
  78. p = Q.front->next;
  79. Q.front->next = p->next;
  80. p->next = NULL;
  81. }
  82. free(p);
  83. return OK;
  84. }
  85. }
  86.  
  87. //打印队列元素
  88. void PrintQueue(LinkQueue Q){
  89. if(Q.front != Q.rear){
  90. do{
  91. Q.front = Q.front->next;
  92. printf("%d ",Q.front->data);
  93. }while(Q.front->next);
  94. }
  95. printf("\n");
  96. }
  97.  
  98. //********************************循环队列的基本操作*****************************
  99. //初始化队列
  100. Status InitQueueXh(SqQueue &Q){
  101. Q.base = (int *)malloc(MAXQSIZE * sizeof(int));//动态分配空间
  102. if(!Q.base){
  103. exit(ERROR);//分配空间失败
  104. }
  105. Q.front = Q.rear = ;
  106. return OK;
  107. }
  108.  
  109. //在队尾插入新元素
  110. Status EnQueueXh(SqQueue &Q, int e){
  111. if((Q.rear + ) % MAXQSIZE == Q.front){
  112. exit(ERROR);//队循环列已满
  113. }
  114. Q.base[Q.rear] = e;
  115. Q.rear = (Q.rear + ) % MAXQSIZE;
  116. return OK;
  117. }
  118.  
  119. int DestroyQueueXh(SqQueue &Q){
  120. return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
  121. }
  122.  
  123. //删除队头元素,并用e返回
  124. Status DeQueueXh(SqQueue &Q, int &e){
  125. if(Q.front == Q.rear){//先判断队列是否为空
  126. return false;
  127. }
  128. e = Q.base[Q.front];
  129. Q.front = (Q.front + ) % MAXQSIZE;
  130. return OK;
  131. }
  132.  
  133. //打印队列元素
  134. void PrintQueueXh(SqQueue Q){
  135. if(Q.front != Q.rear){
  136. do{
  137. printf("%d ",Q.base[Q.front]);
  138. Q.front++;
  139. }while(Q.front != Q.rear);
  140. }
  141. printf("\n");
  142. }
  143.  
  144. //主方法
  145. int main(){
  146. int e, i;
  147. int Data[] = {,,,,,};
  148.  
  149. printf("****************队列的基本操作**************\n");
  150. //初始化队列
  151. LinkQueue Qa, Qb;
  152. InitQueue(Qa);
  153. //初始化Qa
  154. for(i = ; i < ; i++){
  155. EnQueue(Qa,Data[i]);
  156. }
  157. //打印Qa
  158. printf("Qa的各个元素:");
  159. PrintQueue(Qa);
  160.  
  161. //删除队首元素
  162. DeQueue(Qa,e);
  163. printf("删除Qa的队首元素:%d\n",e);
  164. printf("删除首元素后的Qa: ");
  165. PrintQueue(Qa);
  166. printf("销毁后的Qa: ");
  167. DestroyQueue(Qa);
  168. PrintQueue(Qa);
  169.  
  170. printf("**************循环队列的基本操作************\n");
  171. //初始化队列
  172. SqQueue QaXh, QbXh;
  173. InitQueueXh(QaXh);
  174. //初始化Qa
  175. for(i = ; i < ; i++){
  176. EnQueueXh(QaXh,Data[i]);
  177. }
  178. //打印Qa
  179. printf("QaXh的各个元素:");
  180. PrintQueueXh(QaXh);
  181.  
  182. //删除队首元素
  183. DeQueueXh(QaXh,e);
  184. printf("删除QaXh的队首元素:%d\n",e);
  185. printf("删除首元素后的QaXh: ");
  186. PrintQueueXh(QaXh);
  187. printf("得到QaXh的元素个数:%d\n",DestroyQueueXh(QaXh));
  188. }

C实现栈和队列的更多相关文章

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

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

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

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

  3. 剑指Offer面试题:6.用两个栈实现队列

    一.题目:用两个栈实现队列 题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能. 原文是使用 ...

  4. JavaScript数组模拟栈和队列

    *栈和队列:js中没有真正的栈和队列的类型              一切都是用数组对象模拟的 栈:只能从一端进出的数组,另一端封闭       FILO   何时使用:今后只要仅希望数组只能从一端进 ...

  5. 用JS描述的数据结构及算法表示——栈和队列(基础版)

    前言:找了上课时数据结构的教程来看,但是用的语言是c++,所以具体实现在网上搜大神的博客来看,我看到的大神们的博客都写得特别好,不止讲了最基本的思想和算法实现,更多的是侧重于实例运用,一边看一边在心里 ...

  6. JavaScript中的算法之美——栈、队列、表

    序 最近花了比较多的时间来学习前端的知识,在这个期间也看到了很多的优秀的文章,其中Aaron可能在这个算法方面算是我的启蒙,在此衷心感谢Aaron的付出和奉献,同时自己也会坚定的走前人这种无私奉献的分 ...

  7. Java数据结构和算法之栈与队列

    二.栈与队列 1.栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底(Bottom). (2)当表中没有元素时称为 ...

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

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

  9. 栈和队列的面试题Java实现【重要】

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

随机推荐

  1. 关于c++类的内存分配

    参考:这里 虽然有些地方错了,但是也可以一看,大概能加深对c++类相关的内存分配的了解 然后这还不算十分深入,更深入的可以看这里. 这本书是时候读一下了:<深度探索C++对象模型> (待续 ...

  2. 使用属性动画 — Property Animation

    属性动画,就是通过控制对象中的属性值产生的动画.属性动画是目前最高级的2D动画系统. 在API Level 11中添加.Property Animation号称能控制一切对象的动画,包括可见的和不可见 ...

  3. sublime text3下BracketHighlighter的配置方法

    st3的配置方法和st2是有区别的,所以网上搜索到的方法大多不能用,我google之后总结了一下. 一. 1.在st3中按preferences-->package settings--> ...

  4. Ceph RGW 的 OSPF负载均衡 + quagga的配置

      随着开源技术的发展,以及商业设备价格的不断攀升.大公司总是希望能使用开源的方案来替换过去使用的商业设备.比如之前大家用的很多的F5和A10,现在已经在逐步被LVS替换.传统的单个lvs的性能是比不 ...

  5. 【bzoj4517】 Sdoi2016—排列计数

    http://www.lydsy.com/JudgeOnline/problem.php?id=4517 (题目链接) 题意 求n个数中正好m个数位置不变的排列数. Solution $${错排公式: ...

  6. a版本冲刺第一天

    队名:Aruba   队员: 黄辉昌 李陈辉 林炳锋 鄢继仁 张秀锋 章  鼎 学号 昨天完成的任务 今天做的任务 明天要做的任务 困难点 体会 408 学习测试文档的编写 继续学习并借鉴,开始着手写 ...

  7. 刚开始用git遇到的无法提交变更的问题

    原来我在目录里打开命令行,git bash默认执行的目录是c:/users了,错误的使用了git init,把$HOME 路径下的所有文件载入 git 仓库了,删除$HOME 路径下的".g ...

  8. <<< javascript地址栏,代码

    不伤及服务器,可以用来测试项目效果 修改网页.不修改服务器端任何网页页面 javascript:document.body.contentEditable='true';document.design ...

  9. infragistics-webdatagrid

    infragistics-webdatagrid DataRow DataTable DataSet DataColumn stringBuilder append appendFormat 存储过程 ...

  10. 数据库性能优化常用sql脚本总结

    最近闲来无事,正好抽出时间,来总结总结 sql性能优化方面的一下小技巧,小工具.虽然都是些很杂的东西,但是我个人觉得,如果真的清楚了里面的一下指标,或许真的能抵半个DBA. 有些时候,找不到DBA或者 ...