当前位置:   article > 正文

C++11 数据结构6 栈的链式存储,实现,测试

C++11 数据结构6 栈的链式存储,实现,测试

栈顶放在链表的头部

栈顶放在链表的头部还是尾部呢?

需要栈 是特殊的线性表,那么我们回忆一下 线性表的链式存储的插入和删除的写法,就应该能理清线性表的头部做为栈顶 合适  还是 线性表的尾部 作为栈顶合适

插入算法 核心代码

  1. //正式插入数据,
  2. int i = 0;
  3. LinkListNode *curSeqListNode = &(tempseqlist->head);//让curSeqListNode 指向 链表的头部
  4. for (int i = 0; i < pos; ++i) {
  5. curSeqListNode = curSeqListNode->next;
  6. }
  7. node->next = curSeqListNode->next;
  8. curSeqListNode->next = node;
  9. tempseqlist->length++;
  10. return ret;

删除算法 核心代码

  1. //辅助指针变量curSeqListNode,指向的位置是链表的头部
  2. LinkListNode *curSeqListNode = &(tempseqlist->head);//让curSeqListNode 指向 链表的头部
  3. int i = 0;
  4. for (i = 0; i < pos; ++i) {
  5. curSeqListNode = curSeqListNode->next;
  6. }
  7. retSeqListNode = curSeqListNode->next; //先将要删除的节点缓存出来
  8. curSeqListNode->next = retSeqListNode->next;// 删除的节点的next中保存着 “要删除元素的下一个元素”,让curseqlistnode->next 指向
  9. tempseqlist->length--;
  10. return retSeqListNode;

从这两个算法都能看出,如果要在pos 位置插入元素 或者 删除元素,那么先要遍历到pos 位置,因此我们在 线性表的头部 做为 栈顶 比较合理。因此不管是插入元素,或者是删除元素,都是对线性表的头部的第一个元素进行处理。

相关代码:

  1. #ifndef __006LINKSTACK_H__
  2. #define __006LINKSTACK_H__
  3. typedef void LinkStack; //链表的返回值,需要使用void *
  4. typedef struct LinkStackNode { //链表节点
  5. struct LinkStackNode *next;
  6. }LinkStackNode;
  7. // 初始化,建立一个空的链表
  8. //返回值不为NULL,表示创建成功。
  9. //返回值为NULL,表示创建失败。
  10. LinkStack* LinkStack_Create();
  11. //销毁该线性表
  12. //返回值为1,表示成功。
  13. //返回值为-1,表示失败。
  14. int LinkStack_Destory(LinkStack *list);
  15. //清空seqlist
  16. //返回值为1,表示成功。
  17. //返回值为-1,表示失败。
  18. int LinkStack_Clear(LinkStack *list);
  19. // 返回线性表List存在的元素个数
  20. //返回值 >=0 表示:该list存在的元素个数
  21. //<0 表示error
  22. int LinkStack_Length(LinkStack *list);
  23. //从LinkStack 中获取栈顶位置的数据,实际上是 栈的第一个链表的数据
  24. //返回值:为存储在该位置的元素
  25. //返回NULL 表示有问题
  26. LinkStackNode* LinkStack_Get(LinkStack *list);
  27. //给LinkStack中指定位置插入数据,
  28. //参数LinkStackNode为要插入的数据
  29. //参数 pos 为要插入的位置
  30. //成功返回1
  31. //失败 返回<0
  32. int LinkStack_Insert(LinkStack *list, LinkStackNode *node);
  33. //从LinkStack 中删除栈顶位置的元素,实际上删除的链表的除了头结点的第一个元素
  34. //参数 pos
  35. //返回值为 删除的元素
  36. //返回NULL 表示出现了error
  37. LinkStackNode* LinkStack_Delete(LinkStack *list);
  38. //判断当前linkstack 是否为null,如果为null,则返回1
  39. //如果不为NULL,则返回-1
  40. int isEmptyLinkStack(LinkStack *list);
  41. #endif

  1. #include "006linkstack.h"
  2. #include "stdlib.h"
  3. #include "stdio.h"
  4. #include "string.h"
  5. typedef struct LinkStack {
  6. LinkStackNode head;
  7. int length;// 该链表的大小
  8. }TLinkStack;
  9. // 初始化,建立一个空的链表
  10. //返回值不为NULL,表示创建成功。
  11. //返回值为NULL,表示创建失败。
  12. LinkStack* LinkStack_Create() {
  13. TLinkStack * ts = (TLinkStack *)malloc(sizeof(TLinkStack));
  14. if (ts == NULL) {
  15. printf("LinkStack_Create error list==NULL\n");
  16. return NULL;
  17. }
  18. memset(ts, 0, sizeof(TLinkStack));
  19. ts->head.next = NULL;
  20. ts->length = 0;
  21. return ts;
  22. }
  23. //销毁该线性表
  24. //返回值为1,表示成功。
  25. //返回值为-1,表示失败。
  26. int LinkStack_Destory(LinkStack *list) {
  27. int ret = 1;
  28. if (list ==NULL) {
  29. ret = -1;
  30. printf("func LinkStack_Destory error bacesue list = NULL return ret = -1\n");
  31. return ret;
  32. }
  33. TLinkStack * ts = list;
  34. free(ts);
  35. ts = NULL;
  36. list = NULL;
  37. return ret;
  38. }
  39. //清空seqlist
  40. //返回值为1,表示成功。
  41. //返回值为-1,表示失败。
  42. int LinkStack_Clear(LinkStack *list) {
  43. int ret = 1;
  44. if (list == NULL) {
  45. ret = -1;
  46. printf("func LinkStack_Clear error bacesue list = NULL return ret = -1\n");
  47. return ret;
  48. }
  49. TLinkStack * ts = list;
  50. ts->head.next = NULL;
  51. ts->length = 0;
  52. return ret;
  53. }
  54. // 返回线性表List存在的元素个数
  55. //返回值 >=0 表示:该list存在的元素个数
  56. //<0 表示error
  57. int LinkStack_Length(LinkStack *list) {
  58. int ret = 0;
  59. if (list == NULL) {
  60. ret = -1;
  61. printf("func LinkStack_Length error bacesue list = NULL return ret = -1\n");
  62. return ret;
  63. }
  64. TLinkStack * ts = list;
  65. return ts->length;
  66. }
  67. //从LinkStack 中获取指定位置的数据
  68. //参数pos:LinkStack中的位置
  69. //返回值:为存储在该位置的元素
  70. //返回NULL 表示有问题
  71. LinkStackNode* LinkStack_Get(LinkStack *list) {
  72. LinkStackNode* ret = NULL;
  73. if (list == NULL) {
  74. ret = NULL;
  75. printf("func LinkStack_Get error bacesue list = NULL return ret = NULL\n");
  76. return ret;
  77. }
  78. TLinkStack * ts = list;
  79. if (ts->length==0) {
  80. ret = NULL;
  81. printf("func LinkStack_Get error bacesue ts->length = 0 return ret = NULL\n");
  82. return ret;
  83. }
  84. return ts->head.next;
  85. }
  86. //给LinkStack中指定位置插入数据,
  87. //参数LinkStackNode为要插入的数据
  88. //参数 pos 为要插入的位置
  89. //成功返回1
  90. //失败 返回<0
  91. int LinkStack_Insert(LinkStack *list, LinkStackNode *node) {
  92. int ret = 1;
  93. if (list == NULL) {
  94. ret = -1;
  95. printf("func LinkStack_Insert error bacesue list = NULL return ret = -1\n");
  96. return ret;
  97. }
  98. TLinkStack * ts = list;
  99. node->next = ts->head.next;
  100. ts->head.next = node;
  101. ts->length++;
  102. return ret;
  103. }
  104. //从LinkList 中删除指定位置的元素
  105. //参数 pos
  106. //返回值为 删除的元素
  107. //返回NULL 表示出现了error
  108. LinkStackNode* LinkStack_Delete(LinkStack *list) {
  109. LinkStackNode* ret = NULL;
  110. if (list == NULL) {
  111. ret = NULL;
  112. printf("func LinkStack_Delete error bacesue list = NULL return ret = NULL\n");
  113. return ret;
  114. }
  115. TLinkStack * ts = list;
  116. if (ts->length == 0) {
  117. ret = NULL;
  118. printf("func LinkStack_Delete error bacesue ts->length = 0 return ret = NULL\n");
  119. return ret;
  120. }
  121. LinkStackNode * delnode = ts->head.next;
  122. ts->head.next = delnode->next;
  123. ts->length--;
  124. return delnode;
  125. }
  126. //判断当前linkstack 是否为null,如果为null,则返回1
  127. //如果不为NULL,则返回0
  128. //error 则返回-1
  129. int isEmptyLinkStack(LinkStack *list) {
  130. int ret = 0;
  131. if (list == NULL) {
  132. ret = -1;
  133. printf("func isEmptyLinkStack error bacesue list = NULL return ret = -1\n");
  134. return ret;
  135. }
  136. TLinkStack * ts = list;
  137. int length = ts->length;
  138. if (length>0) {
  139. ret = 0;
  140. }
  141. else {
  142. ret = 1;
  143. }
  144. return ret;
  145. }

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #define _CRTDBG_MAP_ALLOC
  3. #include "iostream"
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. extern "C" {
  7. #include "006linkstack.h"
  8. }
  9. typedef struct Teacher {
  10. LinkStackNode linkstacknode;
  11. int age;
  12. char name[128];
  13. char *othername;
  14. char **stuname; //一个老师下面有5个学生
  15. }Teacher;
  16. int main() {
  17. _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
  18. int ret = 0;
  19. //初始化队列,要动态的创建SeqStack,根据user设定的大小创建
  20. //int stacksize ,表示user 要创建栈的大小
  21. //创建失败返回NULL
  22. LinkStack* linkstack = LinkStack_Create();
  23. if (linkstack == NULL) {
  24. ret = -1;
  25. printf("func LinkStack_Create error because linkstack = NULL return ret =-1\n");
  26. return ret;
  27. }
  28. ret = isEmptyLinkStack(linkstack);
  29. printf("isEmptyLinkStack = ret %d\n", ret);
  30. ret = LinkStack_Length(linkstack);
  31. printf("LinkStack_Length = ret %d\n", ret);
  32. Teacher tea1;
  33. tea1.age = 20;
  34. strcpy(tea1.name, (const char*)"tea1");
  35. tea1.othername = (char *)malloc(sizeof(char) * 128);
  36. memset(tea1.othername, 0, sizeof(char) * 128);
  37. strcpy(tea1.othername, (const char*)"tea1othername");
  38. tea1.stuname = (char **)malloc(sizeof(char *) * 5);
  39. memset(tea1.stuname, 0, sizeof(char *) * 5);
  40. for (size_t i = 0; i < 5; i++)
  41. {
  42. tea1.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
  43. memset(tea1.stuname[i], 0, sizeof(char) * 128);
  44. sprintf(tea1.stuname[i], "tea1stuname%d", i + 1);
  45. }
  46. Teacher tea2;
  47. tea2.age = 22;
  48. strcpy(tea2.name, (const char*)"tea2");
  49. tea2.othername = (char *)malloc(sizeof(char) * 128);
  50. memset(tea2.othername, 0, sizeof(char) * 128);
  51. strcpy(tea2.othername, (const char*)"tea2othername");
  52. tea2.stuname = (char **)malloc(sizeof(char *) * 5);
  53. memset(tea2.stuname, 0, sizeof(char *) * 5);
  54. for (size_t i = 0; i < 5; i++)
  55. {
  56. tea2.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
  57. memset(tea2.stuname[i], 0, sizeof(char) * 128);
  58. sprintf(tea2.stuname[i], "tea2stuname%d", i + 1);
  59. }
  60. Teacher tea3;
  61. tea3.age = 33;
  62. strcpy(tea3.name, (const char*)"tea3");
  63. tea3.othername = (char *)malloc(sizeof(char) * 128);
  64. memset(tea3.othername, 0, sizeof(char) * 128);
  65. strcpy(tea3.othername, (const char*)"tea3othername");
  66. tea3.stuname = (char **)malloc(sizeof(char *) * 5);
  67. memset(tea3.stuname, 0, sizeof(char *) * 5);
  68. for (size_t i = 0; i < 5; i++)
  69. {
  70. tea3.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
  71. memset(tea3.stuname[i], 0, sizeof(char) * 128);
  72. sprintf(tea3.stuname[i], "tea3stuname%d", i + 1);
  73. }
  74. ret = LinkStack_Insert(linkstack, (LinkStackNode * )&tea1);
  75. if (ret < 0) {
  76. printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea1) func error ret =%d \n", ret);
  77. return ret;
  78. }
  79. ret = LinkStack_Insert(linkstack, (LinkStackNode *)&tea2);
  80. if (ret < 0) {
  81. printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea2) func error ret =%d \n", ret);
  82. return ret;
  83. }
  84. ret = LinkStack_Insert(linkstack, (LinkStackNode *)&tea3);
  85. if (ret < 0) {
  86. printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea3) func error ret =%d \n", ret);
  87. return ret;
  88. }
  89. printf("-after-\n");
  90. ret = isEmptyLinkStack(linkstack);
  91. printf("isEmptyLinkStack = ret %d\n", ret);
  92. ret = LinkStack_Length(linkstack);
  93. printf("LinkStack_Length = ret %d\n", ret);
  94. while (LinkStack_Length(linkstack) > 0) {
  95. Teacher * temptea = (Teacher *)LinkStack_Get(linkstack);
  96. if (temptea == NULL) {
  97. printf("can not get find teacher\n");
  98. }
  99. printf("temptea->age = %d,temptea->name = %s,temptea->othername=%s\n",
  100. temptea->age,
  101. temptea->name,
  102. temptea->othername);
  103. for (size_t j = 0; j < 5; j++)
  104. {
  105. printf("temptea->stuname[%d] = %s, ",
  106. j, temptea->stuname[j]);
  107. }
  108. Teacher * deltea = (Teacher *)LinkStack_Delete(linkstack);
  109. if (deltea == NULL) {
  110. printf("LinkStack_Delete seqstack error\n");
  111. }
  112. if (deltea->othername != NULL) {
  113. free(deltea->othername);
  114. }
  115. if (deltea->stuname != NULL) {
  116. for (size_t i = 0; i < 5; i++)
  117. {
  118. if (deltea->stuname[i] != NULL) {
  119. free(deltea->stuname[i]);
  120. }
  121. }
  122. free(deltea->stuname);
  123. deltea->stuname = NULL;
  124. }
  125. printf("\n");
  126. }
  127. printf("sss\n");
  128. //销毁栈
  129. //成功 返回1 表示成功销毁栈
  130. //失败 返回-1 表示该函数执行的时候有问题
  131. ret = LinkStack_Destory(linkstack);
  132. return 0;
  133. }

相关应用:实现编译器中的符号成对检测

//几乎所有的编译器都具有检测括号是否匹配的能力,
//那么如何实现编译器中的符号成对检测?如下字符串:
//5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(
//算法思路
//
//从第一个字符开始扫描
//当遇见普通字符时忽略,
//当遇见左括号时压入栈中
//当遇见右括号时从栈中弹出栈顶符号,并进行匹配
//匹配成功:继续读入下一个字符
//匹配失败:立即停止,并报错
//结束:
//成功 : 所有字符扫描完毕,且栈为空
//    失败:匹配失败或所有字符扫描完毕但栈非空

//总结:
//当需要检测成对出现但又互不相邻的事物时可以使用栈“后进先出”的特性

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #define _CRTDBG_MAP_ALLOC
  3. #include "iostream"
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. //几乎所有的编译器都具有检测括号是否匹配的能力,
  7. //那么如何实现编译器中的符号成对检测?如下字符串:
  8. //5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(
  9. //算法思路
  10. //
  11. //从第一个字符开始扫描
  12. //当遇见普通字符时忽略,
  13. //当遇见左括号时压入栈中
  14. //当遇见右括号时从栈中弹出栈顶符号,并进行匹配
  15. //匹配成功:继续读入下一个字符
  16. //匹配失败:立即停止,并报错
  17. //结束:
  18. //成功 : 所有字符扫描完毕,且栈为空
  19. // 失败:匹配失败或所有字符扫描完毕但栈非空
  20. //总结:
  21. //当需要检测成对出现但又互不相邻的事物时可以使用栈“后进先出”的特性
  22. char *err1 = (char *)"无法找到对应的右括号的 左括号";
  23. char *err2 = (char *)"该 左括号 没有对应的有括号";
  24. extern "C" {
  25. #include "004seqstack.h"
  26. }
  27. int isLeft( char ch) {
  28. if ('(' == ch) {
  29. return 1;
  30. }
  31. return 0;
  32. }
  33. int isRight(char ch) {
  34. if (')' == ch) {
  35. return 1;
  36. }
  37. return 0;
  38. }
  39. void printerror(char* err,char *str, char *ptemp) {
  40. printf("err start");
  41. printf(err);
  42. printf("原始字符串如下\n");
  43. printf(str);
  44. printf("\n");
  45. printf("error位置如下\n");
  46. int num = ptemp - str;
  47. while (num > 0 ) {
  48. printf(" ");
  49. --num;
  50. }
  51. printf("|\n");
  52. printf("err end");
  53. }
  54. void testchar(char *str) {
  55. SeqStack * seqstack = createSeqStack(1024);
  56. if (seqstack ==NULL) {
  57. printf("func testchar error because seqstack==NULL\n");
  58. return;
  59. }
  60. if (str == NULL) {
  61. printf("testchar func error because str==NULL\n");
  62. return;
  63. }
  64. char *ptemp = str;//让辅助指针变量指向传递过来的str
  65. while (*(ptemp) != '\0') {
  66. if (isLeft(*ptemp)) { 当遇见左括号时压入栈中.判断是否是符号,如果是 左括号 符号,则要进栈,
  67. push_SeqStack(seqstack,ptemp);
  68. }
  69. if (isRight(*ptemp)) {//当遇见右括号时从栈中弹出栈顶符号,并进行匹配
  70. //如果这时候栈中啥也没有,就有问题,直接break;
  71. if (size_SeqStack(seqstack) == 0) {
  72. printerror(err1,str,ptemp);
  73. break;
  74. }
  75. pop_SeqStack(seqstack);
  76. }
  77. ptemp++;
  78. }
  79. //当将整个字符串都弄完成后,检查栈中是否有元素,如果栈中有元素,说明有左括号没有匹配
  80. while (size_SeqStack(seqstack) > 0 ) {
  81. printerror(err2, str, (char *)top_SeqStack(seqstack));
  82. pop_SeqStack(seqstack);
  83. }
  84. }
  85. int main() {
  86. int ret = 0;
  87. _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
  88. //char* sourcestr = (char *)"5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(";
  89. char* sourcestr = (char *)"5 + 5 * (6) + 9 / 3 * 1 - (1 + 3(";
  90. testchar(sourcestr);
  91. return ret;
  92. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/489148
推荐阅读
相关标签
  

闽ICP备14008679号