当前位置: 首页> 文旅> 艺术 > 栈 | 队列

栈 | 队列

时间:2025/7/13 18:53:14来源:https://blog.csdn.net/m0_72137961/article/details/141967344 浏览次数:0次

系统栈主要保存以下内容:

1.局部变量,2.函数的形参和返回值 3.函数的调用关系

一、栈

1.基本概念

栈是一种特殊的线性表,具有线性结构。表尾为栈顶,表头为栈顶。遵循先进后出原则,只能在栈顶进行插入和删除操作。

2.基本操作

栈的插入操作为入栈(进栈)。栈的删除操作为出栈。如下:

3.栈的顺序存储结构

     它使用一个一维数组来存储栈中的数据元素,数组的下标小的一端作为栈底,另一端作为栈顶。栈顶位置随入栈和出栈操作而变化,因此需要一个整型变量‌top来记录当前栈顶元素在数组中的位置。不多做介绍。

      分类:①满增栈     ②满减栈     ③空增栈     ④空减栈

基本类型类型说明出入栈操作
满增栈栈顶不为空,存储地址由低到高

入栈:栈顶++  入栈数据

出栈:出栈数据,栈顶--

满减栈栈顶不为空,存储地址由高到低

入栈:栈顶--  入栈数据

出栈:出栈数据,栈顶++

空增栈栈顶为空,存储地址由低到高

入栈:入栈数据,栈顶++

出栈:栈顶--,出栈数据

空减栈栈顶为空,存储地址由高到低

入栈:入栈数据,栈顶--

出栈:栈顶++,出栈数据

4.栈的链式存储结构

本质为单向链表。对于链栈来说,基本不存在栈满的情况。除非内存中已经没有可以使用的空间。

基本操作:

#include"link.h"
#include<stdio.h>
Stack_t *create_stack() //创建栈
{Stack_t*slink = malloc(sizeof(Stack_t));if(slink == NULL){perror("fail malloc\n");return NULL;}slink->ptop = NULL;slink->clen = 0;return slink;
}
int is_empty_stack(Stack_t*slink)//判空
{return slink->ptop == NULL;
}
int push_stack(Stack_t*slink,Datatype data)//入栈
{Snode_t *pnode = malloc(sizeof(Snode_t));if(NULL == pnode){perror("fail malloc\n");return -1;}pnode->data = data;pnode->pnext = NULL;pnode->pnext = slink->ptop;slink->ptop = pnode;slink->clen++;return 0;
}
void stack_for_each(Stack_t*slink)//遍历打印
{Snode_t*p = slink->ptop;while(p ){printf("%d\n",p->data);p = p->pnext;}printf("\n");
}
int pop_stack(Stack_t*slink,Datatype * data)//出栈
{if (is_empty_stack(slink))return 0;Snode_t *pdel = slink->ptop;slink->ptop = pdel->pnext;if (data != NULL){*data = pdel->data;}free(pdel);slink->clen--;return 1;
}
int get_stack_top(Stack_t*slink,Datatype *data)//获取栈顶的值
{if(is_empty_stack(slink)){return 0;}Snode_t*p = slink->ptop;*data = p->data;return 1;
}
void clear_stack(Stack_t*slink)//清空栈
{while(!is_empty_stack(slink)){pop_stack(slink,NULL);}
}	
void destroy_stack(Stack_t*slink)//销毁栈
{clear_stack(slink);free(slink);
}

栈的数据类型声明

typedef int Datatype;
typedef struct Snode
{Datatype data;struct Snode*pnext;
}Snode_t;
typedef struct Stack
{Snode_t*ptop;int clen;
}Stack_t;
extern Stack_t *create_stack();
extern int push_stack(Stack_t*slink,Datatype data);
extern int pop_stack(Stack_t*slink,Datatype * data);
extern int get_stack_top(Stack_t*slink,Datatype *data);
extern void clear_stack(Stack_t*slink);
extern void destroy_stack(Stack_t*slink);
extern void stack_for_each(Stack_t*slink);

5.循环栈与链队栈的比较

①在时间复杂度上是一样的,均为0(1)。

②空间性能,顺序栈需要事先确定一个固定的长度,可能会存在内存空间浪费的问题,但它的优势是存取时定位很方便,而链栈则要求每个元素都有指针域,这同时也增加了一些内存开销,但对于栈的长度无限制。所以它们的区别和线性表中讨论的一样,如果栈的使用过程中元素变化不可预料,有时很小,有时非常大,那么最好是用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。

二、队列

1.概念

队列:允许从一端插入数据,另一端删除数据的线性存储结构(FIFO)

管道的本质也是队列,队列主要用于缓存数据

2.基本操作

插入操作为入队操作(队尾) 删除操作为出队操作(队头)

3.顺序队列

使用不当会出现存在假溢出现象,一般使用循环队列,充分利用循环空间。

4.链式队列

初始化:

typedef int QDataType;
typedef struct qnode
{QDataType data;struct qnode *pnext;
}QNode_t;
typedef struct queue
{QNode_t *pfront;QNode_t *prear;int clen;pthread_mutex_t mutex;
}Queue_t;

基本操作:

#include"link.h"
#include<stdio.h>
Queue_t*create_queue()
{Queue_t *qlink = malloc(sizeof(QNode_t));if(qlink == NULL){perror("error malloc 1\n");return NULL;}qlink->pfront = NULL;qlink->prear = NULL;pthread_mutex_init(&(qlink->mutex),NULL);qlink->clen = 0;return qlink;
}
int is_empty_queue(Queue_t*qlink)
{if(NULL == qlink->pfront && qlink->prear == NULL){return 1;}return 0;
}
int push_queue(Queue_t *qlink,QDataType data)
{QNode_t * pnode = malloc(sizeof(QNode_t));pnode->data = data;pnode->pnext = NULL;if(pnode == NULL){perror("error malloc2\n");return -1;}if(is_empty_queue(qlink)){qlink->pfront = pnode;qlink->prear = pnode;}else{QNode_t * p = qlink->prear;p->pnext = pnode;qlink->prear = pnode;qlink->clen++;}
}
int pop_queue(Queue_t *qlink,QDataType  * data)
{QNode_t *del = qlink->pfront;if(is_empty_queue(qlink)){return -1;}if(qlink->clen == 1){qlink->pfront = NULL;qlink->prear = NULL;}qlink->pfront = del->pnext;if(data != NULL){*data = del->data;}free(del);qlink->clen--;return 1;
}
void print_for_each(Queue_t*qlink)
{QNode_t*p = qlink->pfront;while(p){printf("%d\n",p->data);p = p->pnext;}printf("........................\n");
}
int get_queue_pop(Queue_t*qlink,QDataType *data)
{if(is_empty_queue(qlink)){return -1;}QNode_t*p = qlink->pfront;*data = p->data;
}
void clear_queue_pop(Queue_t*qlink)
{while(!is_empty_queue(qlink)){pop_queue(qlink,NULL);}
}
void destroy_queue(Queue_t*qlink)
{clear_queue_pop(qlink);free(qlink);
}

5.循环队列与链队列的比较

①从时间上,其实它们的基本操作都是常数时间,即都为0(1)的,不过循环队列是事先申请好空间,使用期间不释放,而对于链队列,每次申请和释放结点也会存在一些时间开销,如果入队出队频繁,则两者还是有细微差异。

②空间上来说,循环队列必须有一个固定的长度,所以就有了存储元素个数和空间浪费的问题。而链队列不存在这个问题,尽管它需要一个指针域,会产生一些空间上的开销,但也可以接受。所以在空间上,链队列更加灵活。

三、问答。

1.程序运行过程中的栈区和数据结构的栈有什么区别?

程序运行过程中的栈区和数据结构中的栈是两个不同的概念,它们分别属于内存管理和数据结构领域。

  • 数据结构中的栈‌是一种后进先出(LIFO)的数据结构,它只允许在栈顶进行数据的添加(压栈)或移除(出栈)操作。数据结构中的栈是一种抽象数据类型,用于管理数据的存储和访问方式,它不直接涉及物理内存的分配和管理‌。

  • 程序运行过程中的栈区‌则是指内存中的一个特定区域,用于存储局部变量、函数调用的上下文信息等。在程序运行时,操作系统或运行时环境会自动管理这部分内存的分配和释放。栈区的特点是快速分配和释放内存,但空间大小通常受到限制,且只能从栈顶进行操作‌。

简而言之,数据结构中的栈是一种抽象数据类型,用于组织和管理数据;而程序运行过程中的栈区是内存中的一个具体区域,用于存储程序执行时的临时数据和函数调用信息,这两者在计算机科学中各有其用途和重要性‌。

2.队列和栈有什么区别?

①规则不同

1. 队列:先进先出(First In First Out)FIFO

2. 栈:先进后出(First In Last Out )FILO

②对插入和删除操作的限定不同

1. 队列:只能在表的一端进行插入,并在表的另一端进行删除;

2. 栈:只能在表的一端插入和删除。

③遍历数据速度不同

1. 队列:基于地址指针进行遍历,而且可以从头部或者尾部进行遍历,但不能同时遍历,无需开辟空间,因为在遍历的过程中不影响数据结构,所以遍历速度要快;

2. 栈:只能从顶部取数据,也就是说最先进入栈底的,需要遍历整个栈才能取出来,而且在遍历数据的同时需要为数据开辟临时空间,保持数据在遍历前的一致性。

关键字:栈 | 队列

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: