浅谈C语言数据结构——链式堆栈
看到标题点进来的朋友,应该对黑客这个名词很敏感吧?我想应该是这样的,但是你们知道作为一名黑客需要学习哪些知识吗?小编不是什么大佬,但小编可以明确的告诉你,学习C语言是必不可少的一步,为什么?因为C语言是一个非常“底层”的语言,也是应用最广泛的编程语言。你可以这样理解,最底层的是机器语言,紧接着的是汇编,然后就是C语言。
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/a33381b8072f45de906ac6b737f1c695.webp?x-oss-process=image/resize,w_1400/format,webp)
这是机器语言,看不懂?我也看不懂
学习C语言的过程中,数据结构是必须要掌握的,今天小编就跟大家讲一下数据结构中的堆栈——链式堆栈。
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/642086371eae4d63ad422776529d65cb.webp?x-oss-process=image/resize,w_1400/format,webp)
今天要讲的链式堆栈,对于一些刚入门的小伙伴可能比较难以理解,因为链式堆栈涉及到C语言中最令人头疼的知识点——指针。在小编看来,链式堆栈就相当于对指针进行操作,为什么呢?请看下文↓
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/b51c5aafce5041daa3b19a89990e5956.webp?x-oss-process=image/resize,w_1400/format,webp)
小编给大家推荐一个学习氛围超好的地方,C/C++交流企鹅裙:870963251!适合在校大学生,小白,想转行,想通过这个找工作的加入。裙里有大量学习资料,有大神解答交流问题,每晚都有免费的直播课程
创建节点
我们创建一个结构体来充当堆栈的一个节点,这个结构体有一个数据域和一个指针域,数据域用来储存数据,这里小编用来储存整型数据,指针域用来指明栈顶的下一个节点。不理解的可以看下图↓
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/fb655e5e096542ba80f1a63a324b5620.webp?x-oss-process=image/resize,w_1400/format,webp)
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/17b42fe0e77b4926b3f9379dcd279332.webp?x-oss-process=image/resize,w_1400/format,webp)
这是我们创建的堆栈节点
我们的栈顶指示器永远指向左边(上图)的第一个节点,最左边的节点为栈顶,最右边的节点为栈底,堆栈数据的添加和删除都是在栈顶进行的,遵循“后进先出、先进后出”的原则。节点创建完毕之后,我们来创建我们需要的函数,这些函数并不是必要的,在这里小编只是用来给大家做示例。
堆栈属于一种数据结构,实现它并不意味着我们一定要写某种形式的代码,某种形式的函数才能实现,堆栈是一种数据元素与数据元素之间的逻辑关系,我们只要实现这种逻辑关系就可以了,不论以什么形式实现。
初始化并创建第一个节点
小编这次示例中一共有4个函数,这四个函数分别实现初始化堆栈、出栈、入栈、遍历栈堆。我们先创建“初始化栈堆”函数,这个函数很简单,它创建一个堆栈的第一个节点,并将它初始化(存入第一个数据)。具体实现步骤看下图↓
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/e04712d25b9644e991ffc167893ff994.webp?x-oss-process=image/resize,w_1400/format,webp)
head变量是一个全局变量,它用来指明当前堆栈的栈顶,充当栈顶指示器,我们利用栈顶指示器来增加或删除堆栈节点。head是一个指向“堆栈节点类型(inn)”的指针,在创建栈顶指示器或者堆栈节点时候,要注意变量的作用域,因为你创建的函数很可能无法改变它的值,怎么避免呢?这就要用到指针了,因为你可以指明某个变量的地址,这样一来函数就可以根据它的地址来对变量进行操作了。
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/e17ff7a733ad4c14ac7c2db5ecb2931a.webp?x-oss-process=image/resize,w_1400/format,webp)
入栈
入栈函数也非常的简单,稍稍认真看一会就能明白了。细心的小伙伴可能会问,为什么要用malloc()函数来申请一块inn类型大小的内存呢,直接申明一个inn类型变量,用head的next成员指向它不就行了吗?答案是:“我们接下来要用free()函数来释放内存”,看不懂这里?没关系,当你用源码练习的时候你就知道了!
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/387cc8ac2775412aa0dfe8cadd59e2b8.webp?x-oss-process=image/resize,w_1400/format,webp)
出栈
出栈函数和入栈函数是有一点关系的,因为出栈函数中的free()函数能释放掉入栈函数动态申请的内存。出栈函数仅仅是一些指针与指针之间的转换而已,没有涉及到一些新的知识,理解这个函数仅仅需要你理解指针就可以了。具体的实现步骤就看下图吧,小编也不知道怎么表达出来,你们看着源码就能理解了。
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/a47760494b1941c4b901be9a00bbfa5f.webp?x-oss-process=image/resize,w_1400/format,webp)
遍历栈堆
便利堆栈函数,这个函数的功能是用来遍历整个堆栈,并打印出堆栈节点的数据,供我们观察我们的程序,是否按照我们预先设计的路线实现。这个函数也是一些指针之间的转换,不是特别难,仔细看就能看出他的工作原理了。
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/0cb4eb89aa524f629f09bd89e65605ec.webp?x-oss-process=image/resize,w_1400/format,webp)
值得注意的是,这个函数中有一个rec指针,这个指针是用来干嘛的呢?它是用来将栈顶指示器“复位”的,通过观察我们可以看到,这个函数是使用栈顶指示器(head指针)来遍历整个堆栈的,所以栈顶指示器会一步步的移到“栈底”,如果我们不将栈顶指示器“复位(调回栈顶)”,那么接下来的堆栈操作就没有相应的栈顶指示器了。
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/ea5f8b7e720c45299e99d06ab827c22b.webp?x-oss-process=image/resize,w_1400/format,webp)
下图是程序运行结果↓
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/c95b0fff1dcb4565a736a21db707db22.webp?x-oss-process=image/resize,w_1400/format,webp)
![](https://ucc.alicdn.com/ld4xwbsxjzdda/developer-article643746/20241020/ac2c97a27e964f138a1d61590292ada9.webp?x-oss-process=image/resize,w_1400/format,webp)