双向带环带头结点的链表实现栈

1. 数据结构

    利用带头结点带环的结点实现栈的相关操作.因此, 每一个结点包括了一个前驱, 一个后继, 还有一个数据成员

typedef char DLinkStackType;typedef struct DLinkStack
{DLinkStackType data;struct DLinkStack* next;struct DLinkStack* prev;
}DLinkStack;
2. 初始化

    初始化即就是先给对应的结点申请一块内存, 然后将结点的数据成员置为 0 (个人所好), 然后将头结点的前驱后继依次指向空.

void DLinkStackInit(DLinkStack** stack)
{if(stack == NULL || *stack == NULL){return;//非法输入}*stack = (DLinkStack*)malloc(sizeof(DLinkStack));(*stack) -> next = *stack;(*stack) -> prev = *stack;(*stack) -> data = 0;
}

这里写图片描述

3. 入栈

    将每一个结点从链表的尾部插入,即先创建一个新结点, 然后修改新结点和最后一个结点的指向, 将新结点插入链表, 然后修改头结点和新结点的指向, 便实现了入栈操作

void DLinkStackPush(DLinkStack* stack, DLinkStackType value)
{if(stack == NULL){return;}DLinkStack* new_node = CreatNewNode(value);DLinkStack* prev = stack -> prev;prev -> next = new_node;new_node -> prev = prev;new_node -> next = stack;stack -> prev = new_node;
}

这里写图片描述

4. 出栈

    将每一个结点链表的尾部删除, 即修改倒数第二个结点和头结点的指向, 然后将倒数第一个结点删除, 这样便可以完成出栈

void DLinkStackPop(DLinkStack* stack)
{if(stack == NULL){return;//非法输入}if(stack -> next == stack){return;//空栈}DLinkStack* to_delete = stack -> prev;DLinkStack* prev = to_delete -> prev;//stack vs prevstack -> prev = prev;prev -> next = stack;DLinkStackNodeDestroy(to_delete);to_delete = NULL;
}

这里写图片描述

5. 创建结点
DLinkStack* CreatNewNode(DLinkStackType value)
{DLinkStack* new_node = (DLinkStack*)malloc(sizeof(DLinkStack));new_node -> data = value;new_node -> next = NULL;new_node -> prev = NULL;return new_node;
}
6. 取栈顶元素

    每次将头结点的下一个结点的数据返回, 即就完成了取栈顶元素

int DLinkStackGetFront(DLinkStack* stack, DLinkStackType* value)
{if(stack == NULL){return -1;//非法输入}if(stack -> next == stack){return -1;//空栈}*value = (stack -> prev) -> data;return 0;
}

这里写图片描述

7. 销毁栈

    从链表的第一个结点(stack -> next)开始, 依次删除每一个结点, 直到最后一个结点, 同时不要忘记将头结点(傀儡结点)也删除


void DLinkStackDestroy(DLinkStack** stack)
{if(stack == NULL){return;//非法输入}if((*stack) -> prev == *stack){DLinkStackNodeDestroy(*stack);*stack = NULL;}DLinkStack* next; DLinkStack* to_delete;int i = DLinkStackSize(*stack);for(; i > 0; i--){to_delete = (*stack) -> next;next = to_delete -> next;(*stack) -> next = next;next -> prev = *stack;DLinkStackNodeDestroy(to_delete);to_delete = NULL;}DLinkStackNodeDestroy(*stack);*stack = NULL;
}

这里写图片描述
    如有错误,还望大家能够随时提出, 大家共同进步

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++11 标准新特性:委派构造函数

https://www.ibm.com/developerworks/cn/rational/1508_chenjing_c11/index.html陈 晶2015 年 8 月 11 日发布WeiboGoogle用电子邮件发送本页面 1本文首先介绍了在委派构造函数提出之前类成员构造所面临的问题,再结合实例介绍了委派构造函数的用法,并说明…

顺序表实现队列

一. 队列相关概念 队列是只允许在一段进行插入元素, 在另一端进行删除元素的线性表,即只允许对队列进行尾插,头删的操作.队列具有先进先出, 后进后出的特性.          1.初始化 void SeqQueInit(SeqQue* q) {if(q NULL){return;//非法输入}q -> head 0;q -> …

链表实现队列

上篇博客是用顺序表实现队列, 现在用双向带头结点带环链表实现对队列的出队列, 入队列, 取队首元素, 以及销毁队列的相关操作 1.初始化链表 void DLinkQueInit(DLinkQue** q) {if(q NULL){return;//非法输入}if(*q NULL){return;//非法输入带头结点的链表至少有一个傀儡结点…

HDU - 1796——容斥原理+二进制枚举

【题目描述】 Now you get a number N, and a M-integers set, you should find out how many integers which are small than N, that they can divided exactly by any integers in the set. For example, N12, and M-integer set is {2,3}, so there is another set {2,3,4,…

信号的基本概念以及信号的产生

一. 信号产生的场景 1. 用户输入命令, 在shell 启动一个前台进程      2. 当用户按一下 Ctrl C 的时候,从键盘产生一个硬件中断      3. 此时CPU 正在执行这个进程的带代码, 则该进程的执行代码暂停执行, CPU 从用户态切换到内核态处理该硬件中断.      4. 中断…

信号的阻塞

一. 阻塞信号 1.信号的相关概念     (1) 递达: 实际执行信号的处理动作称为信号的递达     (2) 未决: 信号从产生到递达之间的过程叫做信号的未决     (3) 阻塞: 进程可以选择阻塞某个信号, 被阻塞的信号产生时将保持在未决状态, 直到进程解除该信号的屏蔽, 才…

信号的捕捉以及SIGCHLD信号

一. 信号的捕捉定义 用户提供一个处理函数, 要求内核在处理信号时必须切换到用户态,执行这个函数, 这种方式就叫做信号的捕捉 二. 图解信号的捕捉过程 1. 由上图可以看出,当处理信号的执行动作时用户自定义的时候,此时就需返回该函数去调用该函数, 这就叫做信号的捕捉. 以前我…

最小栈的实现

所谓最小栈, 就是当前栈顶元素最小, 我们可以这样做, 每次在入栈之前, 将待入栈元素与栈顶元素相比, 每次现将待入栈的元素先入栈, 再将带入栈的元素和较小的元素入栈, 这样就可以保证每次栈顶元素是最小元素. 在出栈的时候规定每次出栈两个元素,这样就可以保证在出栈之后栈顶元…

用C++实现单链表的创建、逆置和输出 的两种方法

http://blog.csdn.net/lfeng_coding/article/details/47300563 题目描述:在已知单链表头节点的情况下,设计算法逆置单链表并输出 方法一:采用首先将头节点指向空,让其变为尾节点,然后利用中间节点 p、q 将其后的节点一…

两个栈实现一个队列

利用两个栈实现一个队列思路是这样的. 首先这个队列包含两个栈, 然后一个栈用来入队列, 一个栈用来出队列 typedef struct QueBy2Stack {SeqStack input;SeqStack output; }QueBy2Stack; 1. 初始化 void QueBy2StackInit(QueBy2Stack* stack) {if(stack NULL){return;//非法…

Linux--线程死锁

http://blog.csdn.net/gebushuaidanhenhuai/article/details/73799824 线程为什会死锁??“锁”又是什么东西?我们这篇博客主要讲一下为什么要给线程加锁,为什么会出现线程死锁,线程死锁怎么解决。 互斥锁 在我的上篇博…

两个队列实现一个栈

用两个队列实现一个栈的原理是这样的. 规定两个队列, 必须有一个队列是非空, 一个队列是空.每次入栈时必须往非空队列中入, 而每次出栈时, 必须将非空队列里的元素装到空队列中, 直到非空队列中只有一个元素时, 此时就将剩下的这个元素出栈即可. 而取栈顶元素时, 和出栈一样, 先…

Linux--生产者与消费者

http://blog.csdn.net/gebushuaidanhenhuai/article/details/74011636 基本概念 提到生产者和消费者,我们最有可能想到的是商店卖东西,顾客在货架上(缓冲区)买东西。 生产者消费者问题,其实是一个多线程同步问题的经典案例。该问…

进程的挂起以及可重入函数

相关接口     pause 函数用于将进程挂起. 如果信号的处理动作是终止进程, 则进程终止, pause 函数没有返回值; 如果信号的处理动作是忽略, 则进程被挂起, pause函数不返回, 如果信号的处理动作是捕捉, 则调用信号处理动作之后pause 返回 -1.来看一段代码 #include<s…

gdb调试多进程程序

1.gdb下调试多进程程序只需要以下几条命令即可              除此之外还可以查看正在调试的进程 info inferiors, 同时也可以将当前正在调试的进程切换到另外一个进程中让其取运行     2.代码调试演示 #include<stdio.h> #include<stdlib.h> #…

关于memcpy和memmove两函数的区别

http://blog.csdn.net/caowei840701/article/details/8491836 [cpp] view plaincopy <p> 关于memcpy和memmove两个c标准库函数&#xff0c;其功能都是将一块内存区域中的指定大小内容复制到目标内存中&#xff0c;在翻阅c标准库实现的源代码我们发现他们是有区别的。&…

判断字符串出栈合法性

先来看说一下思路 接下来就是写代码了 int StackOrder(SeqStack* stack, char* input, char* output, int size_input, int size_output) {if(stack NULL || input NULL || output NULL){return 0;}int i_input 0;int j_output 0;SeqStackType value;for(; j_output <…

共享栈

1.定义 所谓共享栈就是利用一个数组实现两个栈. 先来看一下共享栈的数据结构 typedef struct SharedStack {int top1;int top2;SeqStackType* data; }SharedStack; 2. 初始化 void SharedStackInit(SharedStack* stack) {if(stack NULL){return;//非法输入}stack -> top…

迷宫求解(递归)

首先来看一下迷宫简易图                                  我们用 0 来表示该位置是墙, 用 1 来表示该位置是路. 所以, 我们在处理迷宫问题的时候可以将其看成一个二维数组即可, 而对应的每一条路我们可以用坐标的形式将其表示, 所以还需要…

数据结构练习——双向链表

http://www.cnblogs.com/-Lei/archive/2012/04/10/2440399.html 复习一下数据结构。。。。说不准下个星期就用上了 只不过写的很简单&#xff0c;没有封装 DoubleLinkList.h #ifndef GUARD_DoubleLinkList_h #define GUARD_DoubleLinkList_h#include <stdio.h>struct Li…