数据结构——栈

98 阅读2分钟

栈的性质

1 是一种特殊的线性表,只允许在固定的一端进行插入和删除元素.

2 进行插入删除操作的一端叫栈顶,另一端叫栈底。出入数据都在栈顶

image.png

image.png

3 栈的插入操作叫入栈/进栈/压栈.

栈的删除操作叫出栈;

4 栈中的数据元素遵循先进后出(或后进先出)的原则,

即先入栈的数据后出栈,后入栈的数据会先出栈.

栈的实现

用链表或数组实现栈?

链表和数组都可用来实现栈,但相对而言数组会更好。

1 分析用数组实现栈

首先,数组的尾插尾删效率高,可以用尾部作为栈顶;

其次,用数组cpu高速缓存命中率高.

唯一缺点是扩容的消耗.

2 分析用链表实现栈

缺点是cpu高速缓存命中率较低.

用带头双向循环链表,将哨兵位作栈底,在后面进行尾插或尾删来实现栈;

也可以用单链表来实现

image.png

采用数组来实现栈

定义栈的结构体

typedef int SKDataType;
typedef struct stack
{
	SKDataType* data;      //存放数据的动态空间
	int top;               //标识栈顶,也能代表栈的数据量,也能标识最后一个数据的下一个位置
	int capacity;          //容量
}SK;

栈的初始化和销毁

#define InitialCapacity 3
void StackInit(SK* stack)//给定初始空间
{
	assert(stack);
	SKDataType* tmp = (SKDataType*)malloc(sizeof(SKDataType) * InitialCapacity);
	assert(tmp);
	stack->data = tmp;
	stack->capacity = InitialCapacity;
	stack->top = 0;
}

void StackDestory(SK* stack)//只需free掉结构体内部动态申请的空间,然后其它数据置0
{
	assert(stack);
	free(stack->data);
	stack->data = NULL;
	stack->top = stack->capacity = 0;
}

入栈

void StackPush(SK* stack, SKDataType x)//栈的性质规定它只能在栈顶插入数据,这里只能尾插
{
	assert(stack);
	if (stack->top == stack->capacity)
	{
		//扩容
		//内存块的大小记得乘以类型大小
		SKDataType* tmp = (SKDataType*)realloc(stack->data, stack->capacity * 2 * sizeof(SKDataType));
		assert(tmp);
		stack->capacity *= 2;
		stack->data = tmp;
	}
	stack->data[stack->top] = x;
	stack->top++;
}

出栈

void StackPop(SK* stack)
{
	assert(stack);
	assert(!StackEmpty(stack));//栈里的数据不能为空
	stack->top--;
}

其它函数

SKDataType StackTop(SK* stack)//取栈顶的元素
{
	assert(stack);
	assert(!StackEmpty(stack));
	return stack->data[stack->top - 1];
}

bool StackEmpty(SK* stack)//判断栈是否为空
{
	assert(stack);
	return stack->top == 0;
}
int StackSize(SK* stack)//栈里的元素数目
{
	assert(stack);
	return stack->top;
}