栈顶放在链表的头部还是尾部呢?
需要栈 是特殊的线性表,那么我们回忆一下 线性表的链式存储的插入和删除的写法,就应该能理清线性表的头部做为栈顶 合适 还是 线性表的尾部 作为栈顶合适
插入算法 核心代码
- //正式插入数据,
- int i = 0;
- LinkListNode *curSeqListNode = &(tempseqlist->head);//让curSeqListNode 指向 链表的头部
- for (int i = 0; i < pos; ++i) {
- curSeqListNode = curSeqListNode->next;
- }
- node->next = curSeqListNode->next;
- curSeqListNode->next = node;
- tempseqlist->length++;
- return ret;
删除算法 核心代码
- //辅助指针变量curSeqListNode,指向的位置是链表的头部
- LinkListNode *curSeqListNode = &(tempseqlist->head);//让curSeqListNode 指向 链表的头部
-
- int i = 0;
- for (i = 0; i < pos; ++i) {
- curSeqListNode = curSeqListNode->next;
- }
- retSeqListNode = curSeqListNode->next; //先将要删除的节点缓存出来
- curSeqListNode->next = retSeqListNode->next;// 删除的节点的next中保存着 “要删除元素的下一个元素”,让curseqlistnode->next 指向
- tempseqlist->length--;
- return retSeqListNode;
从这两个算法都能看出,如果要在pos 位置插入元素 或者 删除元素,那么先要遍历到pos 位置,因此我们在 线性表的头部 做为 栈顶 比较合理。因此不管是插入元素,或者是删除元素,都是对线性表的头部的第一个元素进行处理。
- #ifndef __006LINKSTACK_H__
- #define __006LINKSTACK_H__
-
- typedef void LinkStack; //链表的返回值,需要使用void *
-
- typedef struct LinkStackNode { //链表节点
- struct LinkStackNode *next;
- }LinkStackNode;
-
- // 初始化,建立一个空的链表
- //返回值不为NULL,表示创建成功。
- //返回值为NULL,表示创建失败。
- LinkStack* LinkStack_Create();
-
- //销毁该线性表
- //返回值为1,表示成功。
- //返回值为-1,表示失败。
- int LinkStack_Destory(LinkStack *list);
-
- //清空seqlist
- //返回值为1,表示成功。
- //返回值为-1,表示失败。
- int LinkStack_Clear(LinkStack *list);
-
- // 返回线性表List存在的元素个数
- //返回值 >=0 表示:该list存在的元素个数
- //<0 表示error
- int LinkStack_Length(LinkStack *list);
-
-
-
- //从LinkStack 中获取栈顶位置的数据,实际上是 栈的第一个链表的数据
- //返回值:为存储在该位置的元素
- //返回NULL 表示有问题
- LinkStackNode* LinkStack_Get(LinkStack *list);
-
-
- //给LinkStack中指定位置插入数据,
- //参数LinkStackNode为要插入的数据
- //参数 pos 为要插入的位置
- //成功返回1
- //失败 返回<0
-
- int LinkStack_Insert(LinkStack *list, LinkStackNode *node);
-
-
- //从LinkStack 中删除栈顶位置的元素,实际上删除的链表的除了头结点的第一个元素
- //参数 pos
- //返回值为 删除的元素
- //返回NULL 表示出现了error
- LinkStackNode* LinkStack_Delete(LinkStack *list);
-
- //判断当前linkstack 是否为null,如果为null,则返回1
- //如果不为NULL,则返回-1;
- int isEmptyLinkStack(LinkStack *list);
- #endif
- #include "006linkstack.h"
- #include "stdlib.h"
- #include "stdio.h"
- #include "string.h"
-
- typedef struct LinkStack {
- LinkStackNode head;
- int length;// 该链表的大小
- }TLinkStack;
-
- // 初始化,建立一个空的链表
- //返回值不为NULL,表示创建成功。
- //返回值为NULL,表示创建失败。
- LinkStack* LinkStack_Create() {
- TLinkStack * ts = (TLinkStack *)malloc(sizeof(TLinkStack));
- if (ts == NULL) {
- printf("LinkStack_Create error list==NULL\n");
- return NULL;
- }
- memset(ts, 0, sizeof(TLinkStack));
- ts->head.next = NULL;
- ts->length = 0;
-
- return ts;
- }
-
- //销毁该线性表
- //返回值为1,表示成功。
- //返回值为-1,表示失败。
- int LinkStack_Destory(LinkStack *list) {
- int ret = 1;
- if (list ==NULL) {
- ret = -1;
- printf("func LinkStack_Destory error bacesue list = NULL return ret = -1\n");
- return ret;
- }
- TLinkStack * ts = list;
- free(ts);
- ts = NULL;
- list = NULL;
- return ret;
- }
-
- //清空seqlist
- //返回值为1,表示成功。
- //返回值为-1,表示失败。
- int LinkStack_Clear(LinkStack *list) {
- int ret = 1;
- if (list == NULL) {
- ret = -1;
- printf("func LinkStack_Clear error bacesue list = NULL return ret = -1\n");
- return ret;
- }
- TLinkStack * ts = list;
- ts->head.next = NULL;
- ts->length = 0;
- return ret;
- }
-
- // 返回线性表List存在的元素个数
- //返回值 >=0 表示:该list存在的元素个数
- //<0 表示error
- int LinkStack_Length(LinkStack *list) {
- int ret = 0;
- if (list == NULL) {
- ret = -1;
- printf("func LinkStack_Length error bacesue list = NULL return ret = -1\n");
- return ret;
- }
- TLinkStack * ts = list;
- return ts->length;
- }
-
-
-
- //从LinkStack 中获取指定位置的数据
- //参数pos:LinkStack中的位置
- //返回值:为存储在该位置的元素
- //返回NULL 表示有问题
- LinkStackNode* LinkStack_Get(LinkStack *list) {
- LinkStackNode* ret = NULL;
- if (list == NULL) {
- ret = NULL;
- printf("func LinkStack_Get error bacesue list = NULL return ret = NULL\n");
- return ret;
- }
- TLinkStack * ts = list;
- if (ts->length==0) {
- ret = NULL;
- printf("func LinkStack_Get error bacesue ts->length = 0 return ret = NULL\n");
- return ret;
- }
- return ts->head.next;
- }
-
-
- //给LinkStack中指定位置插入数据,
- //参数LinkStackNode为要插入的数据
- //参数 pos 为要插入的位置
- //成功返回1
- //失败 返回<0
-
- int LinkStack_Insert(LinkStack *list, LinkStackNode *node) {
- int ret = 1;
- if (list == NULL) {
- ret = -1;
- printf("func LinkStack_Insert error bacesue list = NULL return ret = -1\n");
- return ret;
- }
- TLinkStack * ts = list;
- node->next = ts->head.next;
- ts->head.next = node;
- ts->length++;
- return ret;
- }
-
-
- //从LinkList 中删除指定位置的元素
- //参数 pos
- //返回值为 删除的元素
- //返回NULL 表示出现了error
- LinkStackNode* LinkStack_Delete(LinkStack *list) {
- LinkStackNode* ret = NULL;
- if (list == NULL) {
- ret = NULL;
- printf("func LinkStack_Delete error bacesue list = NULL return ret = NULL\n");
- return ret;
- }
- TLinkStack * ts = list;
- if (ts->length == 0) {
- ret = NULL;
- printf("func LinkStack_Delete error bacesue ts->length = 0 return ret = NULL\n");
- return ret;
- }
- LinkStackNode * delnode = ts->head.next;
- ts->head.next = delnode->next;
- ts->length--;
- return delnode;
-
- }
-
- //判断当前linkstack 是否为null,如果为null,则返回1
- //如果不为NULL,则返回0;
- //有error 则返回-1
- int isEmptyLinkStack(LinkStack *list) {
- int ret = 0;
- if (list == NULL) {
- ret = -1;
- printf("func isEmptyLinkStack error bacesue list = NULL return ret = -1\n");
- return ret;
- }
- TLinkStack * ts = list;
- int length = ts->length;
- if (length>0) {
- ret = 0;
- }
- else {
- ret = 1;
- }
- return ret;
- }
-
- #define _CRT_SECURE_NO_WARNINGS
- #define _CRTDBG_MAP_ALLOC
- #include "iostream"
- #include <stdio.h>
- #include <stdlib.h>
-
- extern "C" {
- #include "006linkstack.h"
- }
-
- typedef struct Teacher {
- LinkStackNode linkstacknode;
- int age;
- char name[128];
- char *othername;
- char **stuname; //一个老师下面有5个学生
- }Teacher;
-
- int main() {
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
-
- int ret = 0;
- //初始化队列,要动态的创建SeqStack,根据user设定的大小创建
- //int stacksize ,表示user 要创建栈的大小
- //创建失败返回NULL
- LinkStack* linkstack = LinkStack_Create();
- if (linkstack == NULL) {
- ret = -1;
- printf("func LinkStack_Create error because linkstack = NULL return ret =-1\n");
- return ret;
- }
- ret = isEmptyLinkStack(linkstack);
- printf("isEmptyLinkStack = ret %d\n", ret);
-
- ret = LinkStack_Length(linkstack);
- printf("LinkStack_Length = ret %d\n", ret);
-
- Teacher tea1;
- tea1.age = 20;
- strcpy(tea1.name, (const char*)"tea1");
-
- tea1.othername = (char *)malloc(sizeof(char) * 128);
- memset(tea1.othername, 0, sizeof(char) * 128);
- strcpy(tea1.othername, (const char*)"tea1othername");
-
- tea1.stuname = (char **)malloc(sizeof(char *) * 5);
- memset(tea1.stuname, 0, sizeof(char *) * 5);
- for (size_t i = 0; i < 5; i++)
- {
- tea1.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
- memset(tea1.stuname[i], 0, sizeof(char) * 128);
- sprintf(tea1.stuname[i], "tea1stuname%d", i + 1);
- }
-
-
-
- Teacher tea2;
- tea2.age = 22;
-
- strcpy(tea2.name, (const char*)"tea2");
-
- tea2.othername = (char *)malloc(sizeof(char) * 128);
- memset(tea2.othername, 0, sizeof(char) * 128);
- strcpy(tea2.othername, (const char*)"tea2othername");
-
- tea2.stuname = (char **)malloc(sizeof(char *) * 5);
- memset(tea2.stuname, 0, sizeof(char *) * 5);
- for (size_t i = 0; i < 5; i++)
- {
- tea2.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
- memset(tea2.stuname[i], 0, sizeof(char) * 128);
- sprintf(tea2.stuname[i], "tea2stuname%d", i + 1);
- }
-
-
-
- Teacher tea3;
- tea3.age = 33;
- strcpy(tea3.name, (const char*)"tea3");
-
- tea3.othername = (char *)malloc(sizeof(char) * 128);
- memset(tea3.othername, 0, sizeof(char) * 128);
- strcpy(tea3.othername, (const char*)"tea3othername");
-
- tea3.stuname = (char **)malloc(sizeof(char *) * 5);
- memset(tea3.stuname, 0, sizeof(char *) * 5);
- for (size_t i = 0; i < 5; i++)
- {
- tea3.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符
- memset(tea3.stuname[i], 0, sizeof(char) * 128);
- sprintf(tea3.stuname[i], "tea3stuname%d", i + 1);
- }
-
- ret = LinkStack_Insert(linkstack, (LinkStackNode * )&tea1);
- if (ret < 0) {
- printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea1) func error ret =%d \n", ret);
- return ret;
- }
-
- ret = LinkStack_Insert(linkstack, (LinkStackNode *)&tea2);
- if (ret < 0) {
- printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea2) func error ret =%d \n", ret);
- return ret;
- }
-
- ret = LinkStack_Insert(linkstack, (LinkStackNode *)&tea3);
- if (ret < 0) {
- printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea3) func error ret =%d \n", ret);
- return ret;
- }
-
- printf("-after-\n");
- ret = isEmptyLinkStack(linkstack);
- printf("isEmptyLinkStack = ret %d\n", ret);
-
- ret = LinkStack_Length(linkstack);
- printf("LinkStack_Length = ret %d\n", ret);
-
-
-
- while (LinkStack_Length(linkstack) > 0) {
- Teacher * temptea = (Teacher *)LinkStack_Get(linkstack);
- if (temptea == NULL) {
- printf("can not get find teacher\n");
- }
- printf("temptea->age = %d,temptea->name = %s,temptea->othername=%s\n",
- temptea->age,
- temptea->name,
- temptea->othername);
- for (size_t j = 0; j < 5; j++)
- {
- printf("temptea->stuname[%d] = %s, ",
- j, temptea->stuname[j]);
- }
- Teacher * deltea = (Teacher *)LinkStack_Delete(linkstack);
- if (deltea == NULL) {
- printf("LinkStack_Delete seqstack error\n");
- }
- if (deltea->othername != NULL) {
- free(deltea->othername);
-
- }
- if (deltea->stuname != NULL) {
- for (size_t i = 0; i < 5; i++)
- {
- if (deltea->stuname[i] != NULL) {
- free(deltea->stuname[i]);
- }
- }
- free(deltea->stuname);
- deltea->stuname = NULL;
- }
-
- printf("\n");
- }
- printf("sss\n");
-
- //销毁栈
- //成功 返回1 表示成功销毁栈
- //失败 返回-1 表示该函数执行的时候有问题
- ret = LinkStack_Destory(linkstack);
-
-
- return 0;
-
-
-
-
-
- }
//几乎所有的编译器都具有检测括号是否匹配的能力,
//那么如何实现编译器中的符号成对检测?如下字符串:
//5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(
//算法思路
//
//从第一个字符开始扫描
//当遇见普通字符时忽略,
//当遇见左括号时压入栈中
//当遇见右括号时从栈中弹出栈顶符号,并进行匹配
//匹配成功:继续读入下一个字符
//匹配失败:立即停止,并报错
//结束:
//成功 : 所有字符扫描完毕,且栈为空
// 失败:匹配失败或所有字符扫描完毕但栈非空
//总结:
//当需要检测成对出现但又互不相邻的事物时可以使用栈“后进先出”的特性
- #define _CRT_SECURE_NO_WARNINGS
- #define _CRTDBG_MAP_ALLOC
- #include "iostream"
- #include <stdio.h>
- #include <stdlib.h>
-
-
- //几乎所有的编译器都具有检测括号是否匹配的能力,
- //那么如何实现编译器中的符号成对检测?如下字符串:
- //5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(
- //算法思路
- //
- //从第一个字符开始扫描
- //当遇见普通字符时忽略,
- //当遇见左括号时压入栈中
- //当遇见右括号时从栈中弹出栈顶符号,并进行匹配
- //匹配成功:继续读入下一个字符
- //匹配失败:立即停止,并报错
- //结束:
- //成功 : 所有字符扫描完毕,且栈为空
- // 失败:匹配失败或所有字符扫描完毕但栈非空
-
- //总结:
- //当需要检测成对出现但又互不相邻的事物时可以使用栈“后进先出”的特性
-
- char *err1 = (char *)"无法找到对应的右括号的 左括号";
- char *err2 = (char *)"该 左括号 没有对应的有括号";
- extern "C" {
- #include "004seqstack.h"
- }
-
- int isLeft( char ch) {
- if ('(' == ch) {
- return 1;
- }
- return 0;
- }
-
- int isRight(char ch) {
- if (')' == ch) {
- return 1;
- }
- return 0;
- }
-
- void printerror(char* err,char *str, char *ptemp) {
- printf("err start");
- printf(err);
- printf("原始字符串如下\n");
- printf(str);
- printf("\n");
- printf("error位置如下\n");
-
- int num = ptemp - str;
- while (num > 0 ) {
- printf(" ");
- --num;
- }
- printf("|\n");
- printf("err end");
- }
-
- void testchar(char *str) {
- SeqStack * seqstack = createSeqStack(1024);
- if (seqstack ==NULL) {
- printf("func testchar error because seqstack==NULL\n");
- return;
- }
-
- if (str == NULL) {
- printf("testchar func error because str==NULL\n");
- return;
- }
- char *ptemp = str;//让辅助指针变量指向传递过来的str
- while (*(ptemp) != '\0') {
- if (isLeft(*ptemp)) { 当遇见左括号时压入栈中.判断是否是符号,如果是 左括号 符号,则要进栈,
- push_SeqStack(seqstack,ptemp);
-
- }
- if (isRight(*ptemp)) {//当遇见右括号时从栈中弹出栈顶符号,并进行匹配
- //如果这时候栈中啥也没有,就有问题,直接break;
- if (size_SeqStack(seqstack) == 0) {
- printerror(err1,str,ptemp);
- break;
- }
- pop_SeqStack(seqstack);
- }
- ptemp++;
- }
- //当将整个字符串都弄完成后,检查栈中是否有元素,如果栈中有元素,说明有左括号没有匹配
- while (size_SeqStack(seqstack) > 0 ) {
- printerror(err2, str, (char *)top_SeqStack(seqstack));
- pop_SeqStack(seqstack);
- }
- }
-
- int main() {
- int ret = 0;
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
- //char* sourcestr = (char *)"5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(";
- char* sourcestr = (char *)"5 + 5 * (6) + 9 / 3 * 1 - (1 + 3(";
- testchar(sourcestr);
-
- return ret;
- }