一个数组实现两个栈(共享栈)

本文介绍了一种使用单一数组实现两个栈的数据结构方法,通过两边向中间生长的方式避免空间浪费,并详细解析了其扩容机制和核心操作,如push、pop及获取栈顶元素等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:一个数组实现两个栈,简单的来想就是要把一个数组分成两部分

方式一:

 

 下标为0的位置是stack1的栈底,下标为1的位置是stack2的栈底,stack1的元素放在下标为偶数的位置,stack2的元素放在下标为奇数的位置。这种分法有一个缺点就是容易造成空间浪费,假如stack1只有2个元素,而stack2有10个元素,最后使用的总空间还是20,但其实只存了12个元素。

方式二:

从中间向两边生长的方式

方式三:

两边向中间生长的方式

下面代码实现的是方式三

//TStack.h
#pragma once


//一个数组实现两个栈

//两边往中间生长的方式
typedef struct TStack {
	int  *array;
	int	 top1;
	int  top2;
	int capacity;
}TStack;

void TStackInit(TStack* pTS);        //初始化
void TStackDestroy(TStack* pTS);     //销毁
void ExpanfIfRequired(TStack* pTS);  //扩容
void Push_1(TStack* pTS, int data);  //向栈1添加数据
void Push_2(TStack* pTS, int data);  //向栈2添加数据
void Pop_1(TStack* pTS);             //栈1出栈
void Pop_2(TStack* pTS);             //栈2出栈
int Top_1(TStack* pTS);              //获取栈1的栈顶元素
int Top_2(TStack* pTS);              //获取栈2的栈顶元素
int Size_1(TStack* pTS);             //获取栈1元素个数
int Size_2(TStack* pTS);             //获取栈2元素个数

void TestTStack();                   //测试函数
//TStack.c
#include "TStack.h"
#include <assert.h>
#include "Stack.h"
#include <stdio.h>
void TStackInit(TStack* pTS)
{
	if (pTS == NULL) {
		return;
	}
	pTS->capacity = 10;
	pTS->array = (int*)malloc(sizeof(int)*pTS->capacity);
	pTS->top1 = 0;
	pTS->top2 = pTS->capacity - 1;
}
void TStackDestroy(TStack* pTS)
{
	assert(pTS);
	pTS->capacity = 0;
	pTS->top1 = 0;
	pTS->top2 = 0;
	free(pTS->array);
	pTS->array = NULL;
}
void ExpanfIfRequired(TStack* pTS)
{
	//断言
	assert(pTS);
	//栈1指针没有超过栈2指针,不需要扩容
	if (pTS->top1 <= pTS->top2) {
		return;
	}
	//扩容
	int newCapacity = (pTS->capacity) * 2;
	int* newArray = (int*)malloc(sizeof(int)*newCapacity);
	//判断新数组空间是否开辟成功
	assert(newArray);
	//进行数据搬移
	for (int i = 0; i < pTS->top1; i++) {
		newArray[i] = pTS->array[i];
	}
	//栈2进行搬移 [top1, capcacity),原数组
	for (int j = pTS->top1; j < pTS->capacity; j++) {
		int k = j + pTS->capacity;
		newArray[k] = pTS->array[j];
	}
	//更新数组
	pTS->top2 += pTS->capacity;
	pTS->capacity = newCapacity;

	//销毁原数组
	free(pTS->array);
	pTS->array = newArray;
}
void Push_1(TStack* pTS, int data)
{
	ExpanfIfRequired(pTS);
	pTS->array[pTS->top1] = data;
	pTS->top1++;
}
void Push_2(TStack* pTS, int data)
{
	ExpanfIfRequired(pTS);
	pTS->array[pTS->top2] = data;
	pTS->top2--;
}
void Pop_1(TStack* pTS)
{
	pTS->top1--;
}
void Pop_2(TStack* pTS)
{
	pTS->top2++;
}
int Top_1(TStack* pTS)
{
	return pTS->array[pTS->top1 - 1];
}
int Top_2(TStack* pTS)
{
	return pTS->array[pTS->top2 + 1];
}
int Size_1(TStack* pTS)
{
	return pTS->top1;
}
int Size_2(TStack* pTS)
{
	return pTS->capacity - (pTS->top2) - 1;
}

//测试函数
void TestTStack()
{
	TStack stack;
	TStackInit(&stack);

	Push_1(&stack, 1);
	Push_1(&stack, 2);
	Push_1(&stack, 3);
	Push_1(&stack, 4);
	Push_1(&stack, 5);
	Push_1(&stack, 6);
	Push_1(&stack, 7);

	Push_2(&stack, 101);
	Push_2(&stack, 102);
	Push_2(&stack, 103);
	for (int i = 0; i < (&stack)->capacity; i++) {
		printf("%d ",(&stack)->array[i]);
	}
	printf("\n");
	// 触发扩容
	Push_2(&stack, 104);
	Push_2(&stack, 105);

	for (int i = 0; i < (&stack)->capacity; i++) {
		printf("%d ", (&stack)->array[i]);
	}
}

 

 

### 如何在单个数组实现两个 为了在一个数组实现两个,可以采用双端的方式。具体来说,在同一个数组两端分别设置两个底指针,一个指向数组起始位置作为第一个的底部(记作`bottom1`),另一个指向数组末尾作为第二个的顶部(记作`top2`)。当向任一中添加新元素时,相应调整该顶端的位置;而移除元素则相反。 #### 定义数据结构 定义一个包含这两个共享使用的数组以及各自独立维护的顶索引变量: ```c #define MAX_SIZE 100 // 假设最大容量为100 typedef struct { int data[MAX_SIZE]; int top1; /* 1 的顶 */ int top2; /* 2 的顶 */ } TwoStacks; ``` 初始化函数用于设定初始状态下的两个为空的状态: ```c void initTwoStacks(TwoStacks *ts) { ts->top1 = -1; // 初始化1为空 ts->top2 = MAX_SIZE; // 初始化2为空 } ``` #### 实现基本操作 ##### 插入元素 对于每个而言,插入意味着增加新的项并更新对应的顶指示器。需要注意的是要检查是否有足够的空间来容纳新增加的项目。 ```c int pushToStack1(TwoStacks *ts, int value){ if(ts->top1 + 1 >= ts->top2){return 0;} // 如果没有可用的空间,则失败 ts->data[++(ts->top1)] = value; return 1; } int pushToStack2(TwoStacks *ts, int value){ if(ts->top1 >= ts->top2 - 1){return 0;} // 如果没有可用的空间,则失败 ts->data[--(ts->top2)] = value; return 1; } ``` ##### 删除元素 从指定的弹出最上面的一项,并减少相应的顶计数器。 ```c int popFromStack1(TwoStacks *ts, int *value){ if(ts->top1 == -1){return 0;} // 当前已经为空 *value = ts->data[(ts->top1)--]; return 1; } int popFromStack2(TwoStacks *ts, int *value){ if(ts->top2 == MAX_SIZE){return 0;} // 当前已经为空 *value = ts->data[(ts->top2)++]; return 1; } ``` 通过这种方式可以在单一的一维数组内有效地管理两个独立运作但又相互关联的数据集合——即实现了所谓的“双向增长”的双模型[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值