栈区-----顺序栈------队列

栈(Stack)是一种遵循后进先出(LIFO, Last In First Out)原则的有序集合。这种数据结构只允许在栈顶进行添加(push)或删除(pop)元素的操作。换句话说,最新添加的元素会被最先移除。栈的这种特性使得它在多种编程和应用场景中非常有用,比如函数调用、括号匹配、表达式求值、页面访问历史等。

只允许从一端进行数据的插入和删除的线性存储结构

顺序栈:类似数组

满增栈,满减栈,空增栈,空减栈

空栈,满栈:栈顶所在位置是否存有元素

增栈,减栈:栈的增长方向

                        增栈:内存低地址-----》内存高地址

链式栈:类似链表

链式栈是一种基于单链表的数据存储结构,它通过单链表的方式来实现栈的所有操作。链式栈的主要特点和优势如下:

特点

  1. 动态分配内存:链式栈不需要像顺序栈那样在创建时就分配固定大小的数组空间,而是根据需要动态地分配和释放内存,因此更适合元素数量不确定的情况。
  2. 操作灵活:由于链式栈采用链表结构,因此在栈顶进行插入(入栈)和删除(出栈)操作时,只需改变相关节点的指针指向,而无需移动其他元素,这使得操作更加灵活和高效。
  3. 空间利用率高:链式栈能够克服用数组实现的顺序栈在空间利用率上的不足,特别是在元素数量远小于数组容量时,链式栈可以节省大量未使用的空间。

 栈的基本操作

1.创建栈:
Stack_t *create_stack()
{
    Stack_t *stack = (Stack_t*)malloc(sizeof(Stack_t));
    if(stack ==NULL)
    {
        perror("fail malloc");
        return NULL;
    }
    stack->ptop = NULL;
    stack->clen = 0;
    return  stack;
}
2. 将一个元素添加到栈顶
int push_stack(Stack_t *stack,DataType data)
{
    SNode_t *pstack = (SNode_t *)malloc(sizeof(SNode_t));
    if(pstack ==NULL)
    {
        perror("fail malloc");
        return -1;
    }
    pstack->data = data;
    pstack->pnext = NULL;

    pstack->pnext = stack->ptop;
    stack->ptop = pstack;

    stack->clen++;
    return 0;
}
3. 移除栈顶的元素,并返回这个元素。如果栈为空,则可能抛出异常或返回特殊值
int is_empty_stack(Stack_t *stack)
{
    return stack->ptop == NULL;
}

int pop_stack(Stack_t *stack ,DataType *data)
{

    if(is_empty_stack(stack))
        return 0;
    SNode_t *pstack = stack->ptop;
    stack->ptop = pstack->pnext;
    if(data != NULL)
    {
        *data= pstack->data;
    }

    free(pstack);
    stack->clen--;
    return 0;
}
 4.返回栈顶元素
int get_stack_top(Stack_t*stack,DataType *data)
{
    if(stack == NULL)
        return 0;
    SNode_t *pstack = stack->ptop;
    *data = pstack->data;
    return 0;
}

 5.清空栈
void clear_stack(Stack_t* stack)
{
    DataType e;
    while(!is_empty_stack(stack))
    {
        pop_stack(stack, &e);
    }
}

void destroy_stack(Stack_t * stack)
{
    clear_stack(stack);
    free(stack);
}

6.打印栈的内容

void print_stack(Stack_t *stack)
{
    SNode_t *p = stack->ptop;
    while(p != NULL)
    {
        printf("%d  ", p->data);
        p = p->pnext;
    }
    printf("\n");
}

队列

一、队列的基本概念

  • 定义:队列是一种只允许在一端(队尾)进行插入操作,而在另一端(队头)进行删除操作的线性表。队尾是允许插入的一端,队头是允许删除的一端。
  • 特点:队列具有有序性和先进先出的特性,即最先进入队列的元素将最先被删除。

二、队列的基本操作 

1.创建队列:
Queue_t *create_queue()
{
	Queue_t *pque = malloc(sizeof(Queue_t));
	if (NULL == pque)
	{
		perror("fail malloc");
		return NULL;
	}
	pque->pfront = NULL;
	pque->prear = NULL;
	pque->clen = 0;

	pthread_mutex_init(&(pque->mutex), NULL);

	return pque;
}
2.入队:若队列未满,将新元素加入队列的队尾。
int is_empty_queue(Queue_t *pque)
{
	return NULL == pque->pfront;
}
int push_queue(Queue_t *pque, QDataType data)
{
	QNode_t *pnode = malloc(sizeof(QNode_t));
	if (NULL == pnode)
	{
		perror("fail malloc");
		return -1;
	}
	pnode->data = data;
	pnode->pnext = NULL;

	if (is_empty_queue(pque))
	{
		pque->pfront = pnode;
		pque->prear = pnode;
	}
	else
	{
		pque->prear->pnext = pnode;
		pque->prear = pnode;
	}
	pque->clen++;
	
	return 0;
}
3.出队:若队列非空,删除并返回队列的队头元素。
int pop_queue(Queue_t *pque, QDataType *pdata)
{
	if (is_empty_queue(pque))
		return 0;
	
	QNode_t *pdel = pque->pfront;
	pque->pfront = pdel->pnext;
	if (pdata != NULL)
	{
		*pdata = pdel->data;
	}
	free(pdel);
	if (NULL == pque->pfront)
	{
		pque->prear = NULL;
	}
	
	pque->clen--;

	return 1;
}
3.读队头元素:若队列非空,返回队列的队头元素,但不删除它
int get_queue_front(Queue_t *pque, QDataType *pdata)
{
	if (is_empty_queue(pque))
		return 0;
	if (NULL == pdata)
		return 0;
	
	*pdata = pque->pfront->data;

	return 1;
}
 4.打印队列
void queue_for_each(Queue_t *pque)
{
	QNode_t *p = pque->pfront;
	while (p != NULL)
	{
		printf("%d ", p->data);
		p = p->pnext;
	}
	printf("\n");
}
5.清空队列
void clear_queue(Queue_t *pque)
{
	while (!is_empty_queue(pque))
	{
		pop_queue(pque, NULL);
	}
}


void destroy_queue(Queue_t *pque)
{
	clear_queue(pque);
	free(pque);
}

栈与队列对比

队列
插入操作 在队尾进行,称为入队 在栈顶进行,称为进栈或压栈
删除操作 在队头进行,称为出队 在栈顶进行,称为出栈或退栈
访问方式 通常只能通过队头和队尾访问元素,不支持随机访问 只能访问栈顶元素,不支持随机访问

应用场景

  • 队列:由于其先进先出的特性,队列常用于需要保持元素顺序的场合。例如,在操作系统中用于任务调度、消息传递等;在计算机网络中用于数据包的传输等。此外,队列还常用于缓冲数据,如串口接收数据时可以使用环形队列来存储数据。
  • :由于其后进先出的特性,栈常用于需要逆序操作的场合。例如,在函数调用时保存和恢复寄存器状态、存储局部变量、传递函数参数等;在深度优先搜索遍历等算法中也有广泛应用。此外,栈还可以用于实现括号匹配、逆序打印等算法。

 

你可能感兴趣的:(数据结构)