栈和队列(1)——栈的相关操作

1.栈的结构

        栈是一种特殊的线性表,只能允许在固定的一端进行插入删除操作,在操作过程中,进行数据插入删除的一端就是栈顶,另一端即为栈底。栈中的数据遵循后进先出,即LIFO。

        下面进行对栈的插入元素和删除元素的简单演示。

上图形象地展示出栈LIFO的特性。下文使用数组实现栈,相比之下单链表实现栈由于单链表操作的容易程度只适合头插头删,这样使得栈顶只能是链表表头。双向链表自然可以实现,但是操作不易,这里不考虑。介绍一下栈的代码结构。

typedef struct Stack{
    int top;
    int size;
    STDataType *a;
}Stack;

其中三个结构体成员是栈栈顶元素,栈的当前数据个数,栈的首元素地址。

void STInit(ST* pst){
    pst->size = 0;
    pst->top= 0;
    pst->a = NULL;
}

上述函数是栈的初始化,不多赘述。

void STDestroy(ST* pst){
    assert(pst);
    if(pst->a != NULL){
        free(pst->a);
        pst->a = NULL;
    }
    size = top = 0;
}

上述函数是对栈的销毁操作,如果不及时对栈进行销毁的话,可能会导致内存泄漏,内存泄漏是很严重的问题并且编译器不会对其“特殊照顾”报错,需要自行进行销毁。

2.栈的插入删除

        对于一个经典的数据结构,插入和删除是必不可少的,对于实现LIFO功能的插入删除其实很简单。

2.1 插入

经典的问题就是插入需要判满,判满的操作已经出现过数次。其次就是这个栈初始化设置时的魔鬼细节。下面我用一幅图演示。在本文中Init函数给top初始赋值为0,如果是0的话,代码如下图相同,先赋值,再加一,完成一次赋值top指向的是当前元素的下一个位置;如果top赋值为-1,先加一,再赋值,如下图注释所示,此时top指向当前元素。

        

void STPush(ST* pst, STDataType x){
    assert(pst);
    if(pst->size == ps->top){
        int newcapacity = (pst->capacity == 0) ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL) {
			perror("realloc fail!");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
    }
    pst->a[pst->top] = x;
    pst->top++;
//    pst->a[++pst->top] = x;
}

2.1 删除

对于栈的删除操作,首要判断就是栈是否空,以下为删除代码,只需将栈顶指针向下移位即可。

void STPop(ST* pst) {
	assert(pst);
	assert(pst->top > 0);

	pst->top--;
}

3.栈的其余操作

1.判断栈空

bool STEmpty(ST* pst){
    assert(pst);

    return pst->top == 0;
}

2.取栈顶元素

取栈顶元素的操作在栈的使用中比较常见,由于top指向的元素是当前元素的下一个位置,故返回的元素即栈顶是top-1位置上的元素。

STDataType STTop(ST* pst) {
	assert(pst);
	assert(pst->top > 0);

	return pst->a[pst->top - 1];
}

3.计算栈的大小

int STSize(ST* pst) {
	assert(pst);

	return pst->top;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值