4-29 c语言之栈,队列,双向链表
今天学习了数据结构中栈,队列的知识
相对于单链表来说,栈和队列就是添加的方式不同,队列就相当于排队,先排队的先出来(FIFO),而栈就相当于弹夹,先压进去的子弹后出来(FILO)。
首先看一下栈(Stack)的实现
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALES 0
typedef struct NODE
{
int i;
struct NODE *pNext; //指向的是 上一个从栈顶刚压入的结点
}Stack;
typedef int BOOL; //因为c语言里没有布尔类型,所以用int模拟一下
void Push(Stack **pTop,int i);
BOOL IfEmpty(Stack *pTop);
Stack *Pop(Stack **pTop); //出栈操作
int main()
{
Stack *pTop = NULL; }
void Push(Stack **pTop,int i) //压栈操作
{
Stack *pTemp = (Stack *)malloc(sizeof(Stack));
pTemp->i = i;
pTemp->pNext = NULL; pTemp->pNext = *pTop;
*pTop = pTemp; return;
}
BOOL IfEmpty(Stack *pTop) //因为c++的STL容器里存在判断栈是否为空的操作,在这模拟一下
{
if(pTop == NULL)
return TRUE;
return FALES;
}
Stack *Pop(Stack **pTop)
{
Stack *pPop = NULL;
if(IfEmpty(*pTop))
{
return NULL;
}
else
{
pPop = *pTop;
*pTop = (*pTop)->pNext;
return pPop;
}
}
其次队列(Queue)的实现非常简单,队列压入的实现就和单链表尾添加一样,而弹出就和单链表头删除是一样的,只不过不需要free直接返回队首指针即可;
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef struct NODE
{
int i;
struct NODE *pNext;
}Queue;
typedef int BOOL;
int GetId();
void QueueIn(Queue **ppHead,Queue **ppEnd);
BOOL IfEmpty(Queue *pHead);
Queue *QueueOut(Queue **ppHead,Queue **ppEnd);
int main()
{
Queue *pHead = NULL;
Queue *pEnd = NULL;
Queue *p = NULL; QueueIn(&pHead,&pEnd);
QueueIn(&pHead,&pEnd);
QueueIn(&pHead,&pEnd);
p = QueueOut(&pHead,&pEnd); return ; }
int GetId()
{
static int i = ;
i++;
return i;
}
void QueueIn(Queue **ppHead,Queue **ppEnd)
{
Queue *pTemp = (Queue *)malloc(sizeof(Queue));
pTemp->i = GetId();
pTemp->pNext = NULL; if(*ppHead == NULL)
{
*ppHead = pTemp;
}
else
{
(*ppEnd)->pNext = pTemp;
}
*ppEnd = pTemp;
}
BOOL IfEmpty(Queue *pHead)
{
if(pHead == NULL)
return TRUE;
return FALSE;
}
Queue *QueueOut(Queue **ppHead,Queue **ppEnd)
{
Queue *pOut = NULL;
if(IfEmpty(*ppHead) == TRUE)
return NULL;
else
{
pOut = *ppHead;
*ppHead = (*ppHead)->pNext;
return pOut;
}
}
那么栈和栈区又有什么区别呢?先看这样一段程序
#include<stdio.h>
int main()
{
int i = 1;
printf("%d %d\n ",i,i++); return ;
}
可能一打眼看 就认为是1 1,但测试后发现是 2 1,这就不免让人联想到先进后出的特点了,由于printf是一个标准输出库函数,i 和 i++都算做是两个实参,在函数中,形参也是一个局部变量,在函数这个堆区中存在,按照图中出栈的顺序先B后A,那么先 i++ 出来为 1 ,i 其次出来就为2了(启示就是,在栈区中 若一个函数的参数用了同一个变量 ,记得栈的特点)
双向链表,故名思意就是有一个链表可正向可反向,也就是在添加每个结点的时候,加入一个指针,指向上一个结点的地址,代码如下:
#include<stdio.h>
#include<stdlib.h>
typedef struct NODE
{
int id;
struct NODE *pNext;
struct NODE *pLast; //指向上个结点
}List;
void AddNode(List **ppHead,List **ppEnd,int id);
int main()
{
List *pHead = NULL;
List *pEnd = NULL;
AddNode(&pHead,&pEnd,);
AddNode(&pHead,&pEnd,);
AddNode(&pHead,&pEnd,);
AddNode(&pHead,&pEnd,); while(pHead)
{
printf("%d\n",pHead->id);
pHead = pHead->pNext;
}
printf("\n"); while(pEnd)
{
printf("%d\n",pEnd->id);
pEnd = pEnd->pLast;
} }
void AddNode(List **ppHead,List **ppEnd,int id)
{
List *pTemp = (List *)malloc(sizeof(List));
pTemp->id = id;
pTemp->pLast = NULL;
pTemp->pNext = NULL; if(*ppHead == NULL)
{
*ppHead = pTemp;
*ppEnd = pTemp;
}
else
{
(*ppEnd)->pNext = pTemp;
pTemp->pLast = *ppEnd;
*ppEnd = pTemp;
}
return;
}
最后看到了有两个小问题
第一个 如何用两个栈实现一个队列 这个很简单,先全部压入第一个栈里,然后弹出再压出第二个栈里,最后弹出的就是队列的顺序,反反得正
#include<stdio.h>
#include<stdlib.h>
typedef struct NODE
{
int id;
struct NODE *pNext;
}
Stack;
void Push1(Stack **pTop1);
Stack *Pop1(Stack **pTop1);
void Push2(Stack **pTop2,Stack *pNode);
Stack *Pop2(Stack **pTop2);
Stack *QueueOut(Stack **pTop1,Stack **pTop2);
void InitStack(Stack **pTop1,int n);
int IfEmpty(Stack *pTop1);
int GetId();
int main()
{
Stack *pTop1 = NULL;
Stack *pTop2;
Stack *pTemp = NULL;
InitStack(&pTop1,);
pTemp = QueueOut(&pTop1,&pTop2);
while(pTop2)
{
pTemp = QueueOut(&pTop1,&pTop2);
} return ;
}
int GetId()
{
static int i = ;
i++;
return i;
}
void InitStack(Stack **pTop1,int n)
{
int i;
for(i = ;i < n;i++)
{
Push1(pTop1);
}
return;
}
void Push1(Stack **pTop1)
{
Stack *pTemp = (Stack *)malloc(sizeof(Stack));
pTemp->id = GetId();
pTemp->pNext = NULL; pTemp->pNext = *pTop1;
*pTop1 = pTemp; return;
}
Stack *Pop1(Stack **pTop1)
{
Stack *pPop = NULL;
if(*pTop1 == NULL)
{
return NULL;
}
else
{
pPop = *pTop1;
*pTop1 = (*pTop1)->pNext;
return pPop;
}
}
void Push2(Stack **pTop2,Stack *pNode)
{
pNode->pNext = *pTop2;
*pTop2 = pNode; return; }
Stack *Pop2(Stack **pTop2)
{
Stack *pPop = NULL;
if(*pTop2 == NULL)
{
return NULL;
}
else
{
pPop = *pTop2;
*pTop2 = (*pTop2)->pNext;
return pPop;
}
}
int IfEmpty(Stack *pTop1)
{
if(pTop1 == NULL)
return ;
return ;
}
Stack *QueueOut(Stack **pTop1,Stack **pTop2)
{
while(IfEmpty(*pTop1) != )
Push2(pTop2,Pop1(pTop1)); return Pop2(pTop2);
}
第二个,如何快速的找到链表里倒数第n个结点,设置两个指针指向头,一个先往后走k个结点,然后一起走,当先走的那个到达尾结点时,后走的也就是倒数第k个结点了
#include<stdio.h>
#include<stdlib.h>
typedef struct NODE
{
int id;
struct NODE *pNext;
}List;
int GetId();
void AddNode(List **ppHead,List **ppEnd);
List *Search(List *pHead,List *pEnd,int n);
int main()
{
List *pHead = NULL;
List *pEnd = NULL;
List *pTemp = NULL;
int i;
for(i = ;i < ;i++)
AddNode(&pHead,&pEnd);
pTemp = Search(pHead,pEnd,);
printf("%d\n",pTemp->id); }
int GetId()
{
static int i = ;
i++;
return i;
}
void AddNode(List **ppHead,List **ppEnd)
{
List *pTemp = (List *)malloc(sizeof(List));
pTemp->id = GetId();
pTemp->pNext = NULL; if(*ppHead == NULL)
{
*ppHead = pTemp;
}
else
{
(*ppEnd)->pNext = pTemp; }
*ppEnd = pTemp;
}
List *Search(List *pHead,List *pEnd,int n)
{
int i;
List *pFast = pHead;
List *pSlow = pHead;
for(i = ;i < n;i++)
{
pFast = pFast->pNext;
}
while(pFast)
{
pSlow = pSlow->pNext;
pFast = pFast->pNext;
}
return pSlow; }
2019-04-29 22:32:52 编程菜鸟自我反省,大佬勿喷,谢谢!!!
4-29 c语言之栈,队列,双向链表的更多相关文章
- C语言实现,队列可伸缩
两个栈实现一个队列,C语言实现,队列可伸缩,容纳任意数目的元素. 一.思路:1.创建两个空栈A和B:2.A栈作为队列的入口,B栈作为队列的出口:3.入队列操作:即是入栈A:4.出队列操作:若栈B为空, ...
- C语言函数调用栈
C语言函数调用栈 栈溢出(stack overflow)是最常见的二进制漏洞,在介绍栈溢出之前,我们首先需要了解函数调用栈. 函数调用栈是一块连续的用来保存函数运行状态的内存区域,调用函数(calle ...
- Leetcode栈&队列
Leetcode栈&队列 232.用栈实现队列 题干: 思路: 栈是FILO,队列是FIFO,所以如果要用栈实现队列,目的就是要栈实现一个FIFO的特性. 具体实现方法可以理解为,准备两个栈, ...
- java 集合 Connection 栈 队列 及一些常用
集合家族图 ---|Collection: 单列集合 ---|List: 有存储顺序 , 可重复 ---|ArrayList: 数组实现 , 查找快 , 增删慢 ---|LinkedList: 链表实 ...
- Java 容器之 Connection栈队列及一些常用
集合家族图 ---|Collection: 单列集合 ---|List: 有存储顺序 , 可重复 ---|ArrayList: 数组实现 , 查找快 , 增删慢 ---|LinkedList: 链表实 ...
- java面向对象的栈 队列 优先级队列的比较
栈 队列 有序队列数据结构的生命周期比那些数据库类型的结构(比如链表,树)要短得多.在程序操作执行期间他们才被创建,通常用他们去执行某项特殊的任务:当完成任务之后,他们就会被销毁.这三个数据结构还有一 ...
- C++实现一个简单的双栈队列
双栈队列的原理是用两个栈结构模拟一个队列, 一个栈A模拟队尾, 入队的元素全部压入此栈, 另一个栈B模拟队首, 出队时将栈A的元素弹入栈B, 将栈B的栈顶元素弹出 此结构类似汉诺塔, 非常经典, 这里 ...
- 栈&队列&并查集&哈希表(julyedu网课整理)
date: 2018-11-25 08:31:30 updated: 2018-11-25 08:31:30 栈&队列&并查集&哈希表(julyedu网课整理) 栈和队列 1. ...
- 《数据结构与算法分析:C语言描述》复习——第三章“线性表、栈和队列”——双向链表
2014.06.14 20:17 简介: 双向链表是LRU Cache中要用到的基本结构,每个链表节点左右分别指向上一个和下一个节点,能够自由地左右遍历. 图示: 实现: // My implemen ...
随机推荐
- ubuntu 部署 wiki.js
1. 安装node (还是官网的东西靠谱,虽然是english) https://github.com/nodesource/distributions/blob/master/README.md ...
- 小程序点击按钮清空input
大致的思路是先给标签input设置一个value <input value="{{value}}" placeholder="最大输入长度10"/> ...
- mac搭配Nginx服务器常见问题
推流服务器主要是使用了开源的nginx和rtmp模块,网上也有很多资料,不过对有些可能出现的问题没有很好的总结. 安装brew 使用Mac进行开发很久的老司机应该对这个工具很熟悉了.brew是一个第三 ...
- 慢工出细活 JS 等待加载效果
实例可以直接运行查看效果.很方便快捷 <html> <head> <meta http-equiv="content-Type" content=&q ...
- scrapy框架的日志等级和请求传参
日志等级 请求传参 如何提高scrapy的爬取效率 一.Scrapy的日志等级 - 在使用scrapy crawl spiderFileName运行程序时,在终端里打印输出的就是scrapy的日志信息 ...
- CentOS6.5上安装MySQL
1.查看操作系统的相关信息 2.查看系统上所有MySQL的rpm包并删除 [root@master ~]# rpm -qa | grep -i mysql [root@masterc ~]# yum ...
- 如何在Linux系统下挂载光盘
工具/原料 Linux 方法/步骤 找到光盘的完整路径名.在命令行输入:ls -l /dev | grep cdrom. 可以看到光盘的名字叫做:cdrom1.然后在命令行执行: mount /d ...
- PHP 框架
LARAVEL/LUMEN, CI ,THINKPHP, YII ,SYMFONY YAF, PHALCON ,ICE FRAMEWORK
- linux下安装mysql解决乱码、时间差、表的大小写问题
编辑vi /etc/mysql/my.cnf,有的则是:/etc/my.cnf,加入 [client]default-character-set=utf8mb4 [mysql]default-char ...
- Oracle数据库-sqlplus命令下出现SP2-0640: Not connected
可以正常登录sqlplus,通过sys as sysdba 但在sql>输入语句,反馈如下 解决方法: sql>输入conn sys/as sysdba Enter password: c ...