栈和队列的面试题

1.实现一个栈,要求实现出栈、入栈的操作,并且返回最小值的时间为O(1)

思路:

方法一:用两个站来实现,一个栈来实现入栈、出栈的操作,另一个栈用来记录最小值,每向栈1中入一个元素都与栈2中的栈顶元素比较,如果小于栈2的栈顶元素的话,将该元素放入栈1,栈2中,如果大于栈2中的元素的话,只向栈1中放入该元素,直到数组的元素全部放入栈1为止。

实现一个栈,要求实现入栈和出栈,并且在栈中找最小值的时间复杂度为O(1)

//方法一(用两个栈来实现)
//用一个栈来表示存放栈中的元素,栈2来记录最小的元素,循环下面的操作
// 1.取一个元素,将该元素入栈1,然后将栈1栈顶的元素和栈2栈顶的元素比较
// 2.如果栈2此时为空的话,将该元素入栈2,如果栈2有元素的话,如果栈1的栈顶元素比栈2栈顶的元素小的话,也直接入栈2,如果栈1中栈顶的元素大的话不用入栈2
// 直到数组的元素全部入栈为止,此时取栈2中栈顶元素就是该栈中元素的最小值
void StackFind(Stack *FirstStack, Stack *SecondStack, DataType *str, DataType size)
{
	DataType ret = 0;
	int i = 0;
	while(i < size)
	{
		//入栈
		PushStack(FirstStack, str[i]);
		if(SecondStack->top == 0 || SecondStack->array[SecondStack->top-1] > FirstStack->array[FirstStack->top-1])
		{
			PushStack(SecondStack, FirstStack->array[FirstStack->top-1]);
		}
		i++;
	}
	//出栈
	PopStack(FirstStack);
	//最小值
	ret = SecondStack->array[SecondStack->top-1];
}
//将一个栈中的数据装入另一个栈中
void  ExchangeData(Stack *cur, Stack* ret)
{
	assert(cur && ret);
	while(cur->top > 0)
	{
		PushStack(ret, cur->array[cur->top-1]);
		PopStack(cur);
	}
}

//入栈
void PushStackMin(StackMin *cur, DataType a, DataType MinData)
{
	assert(cur);
	cur->array[cur->top].data  = a;
	cur->array[cur->top].min = MinData;
	cur->top++;
}
//出栈
void PopStackMin(StackMin *cur)
{
	assert(cur);
	cur->top--;
}

方法二:将栈改成可以存放结构体的栈,结构体中包含数组的元素和一个记录最小值的变量,

1.首先如果栈为空的话,将数组的元素入栈,且将最小值,改为该元素。

2.如果栈不为空的话,先将数组元素与栈顶记录最小值的变量比较,如果大于最小值得的话,将该元素入栈,并且最小值不变,如过小于最小值的话,将记录最小值的变量更新。

直到元素全部入栈为止。此时返回栈顶的最小值变量即可。


//方法2(用一个栈来实现)
//用一个栈来实现的话,将每个存储元素的空间分为两个部分,一部分用来存储数据,另一个用来记录现在栈中的最小值
//1.如果栈为空的话,将元素入栈,并且将最小的元素标记为该元素
//2.如果栈不为空的话,将该元素与栈顶的存放的标记元素比较,如果小于标记的元素的话,将该元素入栈,且将该处的标记改为该元素。如果大于标记元素的话,将该元素入栈后,标记元素为原来的标记元素。
//直到数组的元素全部入栈为止,此时栈顶存放的标记元素为该数组的最小元素
DataType StackFind2(StackMin *cur, DataType *str, DataType size)
{
	int i = 0;
	DataType MinData = str[0];
	while(i < size)
	{
		if(str[i] <  MinData)
		{
			MinData = str[i];
		}
		PushStackMin(cur, str[i], MinData);
		i++;
	}
	return cur->array[cur->top-1].min;
}

 

2.使用两个栈来实现一个队列

思路:用两个栈来实现,栈是先进后出,而队列是先进先出,所以用栈1来表示入队列,用栈2来表示出队列

入队列:如果栈2不为空的话,将栈2中的元素 放入栈1中,如果栈2中的元素为空的话,直接向栈1中入元素

出队列:如果栈1不为空的话,将栈 1的元素经过出栈、入栈操作放入栈2中,然后将栈2出栈。(因为栈1中的序列放入栈2中后序列的顺序发生变化,原来栈底的元素变成栈2中的元素,所以直接 出栈即可)

队列中的元素个数:两个栈中的元素个数之和

队列是否为空:两个栈中的元素个数是否为0

//初始化栈
void InitStack(Stack *p)
{
	assert(p);
	p->top = 0;
}

//入栈
void PushStack(Stack *cur, DataType data)
{
	assert(cur);
	cur->array[cur->top] = data;
	cur->top++;
}

//出栈
void PopStack(Stack *cur)
{
	assert(cur);
	cur->top--;
}
				//使用两个栈实现一个队列
				//栈1用来入新的数据,栈2用来出队列
				//
//出队列
//出队列时,如果栈2没有数据的话,将栈1中的数据装入栈2中,然后出栈
void PopQueue(Stack *FirstStack, Stack *SecondStack)
{
	assert(FirstStack && SecondStack);
	//判断栈2是否为空有数据
	if(SecondStack->top == 0)
		ExchangeData(FirstStack, SecondStack);
	PopStack(SecondStack);
}
//入队列
//查看栈1中是否有数据,如果没有将栈2中的数据到回栈1中
void PushQueue(Stack *FirstStack, Stack *SecondStack, DataType data)
{
	assert(FirstStack && SecondStack);
	if(FirstStack->top == 0)
	{
		ExchangeData(FirstStack, SecondStack);
	}
	PushStack(FirstStack, data);
}

//队头
DataType  QueueTailNode(Stack *FirstStack, Stack *SecondStack)
{
	assert(FirstStack && SecondStack);
	//判断栈2是否为空有数据
	if(SecondStack->top == 0)
		ExchangeData(FirstStack, SecondStack);
	return SecondStack->array[SecondStack->top-1]; 
}

//队尾
DataType  QueueNoTailNode(Stack *FirstStack, Stack *SecondStack)
{
	assert(FirstStack && SecondStack);
	//判断栈1是否为空有数据
	if(FirstStack->top == 0)
		ExchangeData(SecondStack, FirstStack);
	return FirstStack->array[FirstStack->top-1]; 
}

//判空

DataType QueueEmpty(Stack *FirstStack, Stack *SecondStack)
{
	assert(FirstStack && SecondStack);
    if( FirstStack->top + SecondStack->top == 0)
	     return 0;
}

//长度
DataType QueueNum(Stack *FirstStack, Stack *SecondStack)
{
	assert(FirstStack && SecondStack);
	return FirstStack->top + SecondStack->top;
}

3.使用两个队列来实现一个栈

思路:首先创建两条空队列

入栈时:首先确定哪一个队列是非空的,向非空的队列中插入元素,如果两条队列全部非空的话,随便哪一条都可以。

出栈时:将非空队列进行出队列、入队列等操作,把非空队列中的元素放入空队列中。然后进行出队列操作

栈中的元素个数:遍历两个队列,将两个对列的元素个数返回

栈是否为空:判断两个 队列是否为空

//用两个队列实现一个栈


//入栈
//查看哪一个队列不为空,将数据插入此队列中


//构建一个节点
Node* BuyQueueNode(DataType data)
{
	Node *NewNode = (Node*)malloc(sizeof(Node));
	if(NewNode == NULL)
	{
		perror("malloc:");
		exit(0);
	}
	NewNode->data = data;
	NewNode->next = NULL;
	return NewNode;
}
//判空
DataType QueueEmpty(Queue *cur)
{
	assert(cur);
	if(NULL == cur->front || NULL== cur->rear)
	{
		return 0;
	}
	return 1;
}

//队头元素
DataType QueueOneNode(Queue* cur)
{
	return cur->front->data;
}

//队尾元素
DataType QueueLateNode(Queue *cur)
{
	return cur->rear->data;
}
//初始化队列
void InitQueue(Queue *cur)
{
	cur->front = NULL;
	cur->rear = cur->front;
}
//出队列
void PopQueue(Queue *cur)
{
	Node *ret = cur->front;
//	assert(cur);
	if(!QueueEmpty(cur))
	{
		return;
	}
	if(cur->front == cur->rear)
	{
		(cur)->front = NULL;
		cur->rear = NULL;
		free(ret);
		ret = NULL;
	}
	else
	{
		(cur)->front = (cur)->front->next;
		free(ret);
		ret = NULL;
	}
}
//入队列
void PushQueue(Queue *cur, DataType  data)
{
	assert(cur);
	if(cur->front == NULL)
	{
		(cur)->front = BuyQueueNode(data);
		(cur)->rear = (cur)->front;
	}
	else
	{
		(cur)->rear->next = BuyQueueNode(data);
		(cur)->rear = (cur)->rear->next;
	}
}
//入栈
void PushStack(Queue *FirQueue, Queue *SecQueue, DataType data)
{
	if(!QueueEmpty(FirQueue))
	{
		PushQueue(SecQueue ,data);
	}
	else
	{
		PushQueue(FirQueue, data);
	}
}

int StackEmpty(Queue *FirQueue, Queue *SecQueue)
{
	if(QueueEmpty(FirQueue)&&QueueEmpty(SecQueue))
	{
		return 1;
	}
	return 0;
}

void MoveQueue(Queue *cur, Queue *ret)
{
	while(ret->front != ret->rear)
	{
		PushQueue(cur, ret->front->data);
		PopQueue(ret);
	}
}

//出栈
void PopStack(Queue *FirQueue, Queue *SecQueue)
{
	assert(FirQueue&&SecQueue);
	if(!QueueEmpty(FirQueue))
	{
		MoveQueue(FirQueue,SecQueue);
		PopQueue(SecQueue);
	}
	else
	{
		MoveQueue(SecQueue, FirQueue);
		PopQueue(FirQueue);
	}
}
//栈顶元素
DataType StackOneNode(Queue *FirQueue, Queue *SecQueue)
{
	if(QueueEmpty(FirQueue))
	{
		return QueueLateNode(FirQueue);
	}
	else
	{
		return QueueLateNode(SecQueue);
	}
}
DataType CountCell(Queue *cur)
{
	Node *ret = cur->front;
	DataType count = 0;
	while(ret != NULL)
	{
		ret = ret->next;
		count++;
	}
	return count;
}
//栈有多少个元素
DataType StackNum(Queue *FirQueue, Queue *SecQueue)
{
	if(!QueueEmpty(FirQueue))
	{
		return CountCell(SecQueue);
	}
	else
	{
		return CountCell(FirQueue);
	}
}

4.元素出栈和入栈的合法性

思路:用一个下标 i 指向出栈序列,用另一个下标 j 指向入站序列

首先按照入栈的序列往栈中插入元素,如果栈顶的元素与出栈序列中下标 i 指向的数据相同的话,停止入栈。

然后将栈顶的元素出栈,i 向后移动

循环上面的操作,如果出现栈顶的元素与出战序列中的下表指向的元素不相同时,代表元素的出栈和入栈不合法

 

//判断元素出栈的先后顺序是否正确

//初始化栈

void InitStack(Stack *p)
{
	assert(p);
	p->top = 0;
}

//入栈
void PushStack(Stack *cur, DataType data)
{
	assert(cur);
	cur->array[cur->top] = data;
	cur->top++;
}

//出栈
void PopStack(Stack *cur)
{
	assert(cur);
	cur->top--;
}

DataType PopStackOrder(Stack *cur, DataType *str1, DataType *str2, DataType size1, DataType size2)
{
	DataType i = 0;
	DataType j = 0;
        //比较一个个出栈序列的元素
	while(i < size2)
	{
                //如果栈顶的元素与出栈序列中下标 i 指向的元素不相等 且入站序列没遍历完时。
		while(j < size1 && cur->array[cur->top-1] != str2[i])
		{
			PushStack(cur, str1[j]);
			j++;
		}
                //如果栈顶的元素与出栈序列中下标 i 指向的元素相等时,将栈顶的元素出栈
		if(cur->array[cur->top-1] == str2[i])
			PopStack(cur);
                //如果栈顶的元素与出栈序列中下标 i 指向的元素不相等,代表此时入栈序列已经遍历完,而出栈序列还没遍历完		
                else if(cur->array[cur->top-1] != str2[i])
			return 0;
		i++;
	}
	return 1;
}  

5.一个数组实现两个栈

思路:将数组的首地址做一个栈的栈底,用数组的末尾做另一个栈的栈底。这样两个一个数组会被两个栈使用。

//用一个数组来表是两个栈(共享)
//用数组的头表是栈1的栈底,用数组的尾表示栈2的栈底
//初始化
void Init2Stack( DataType *top1, DataType *top2)
{
	 top1 = 0;//栈1的元素个数
	 top2 = 0;//栈2的元素个数
}

//入栈
void PushStack(DataType (*str)[10], DataType Number, DataType data, DataType *top1, DataType *top2)
{
	if(Number == 1 && *top1 + *top2 <= 9)
	{
		(*str)[*top1] = data;
		*top1 +=1;
	}
	else if(Number == 2 && *top1 + *top2 <= 9)
	{
		(*str)[9-*top2] = data;
		*top2 +=1;
	}
}

//出栈
void PopStack(DataType (*str)[10], DataType Number, DataType *top1, DataType *top2)
{
	if(Number == 1  && *top1 > 0)
	{
		*top1-=1;
	}
	else if(Number == 2 && *top2 > 0)
	{
		*top2-=1;
	}
}

//栈中的元素个数
DataType  NumStack(DataType (*str)[10], DataType Number, DataType *top1, DataType *top2)
{
	if(Number == 1)
		return *top1;
	else
		return *top2;
}

//取栈顶元素
DataType FirstStackNode(DataType (*str)[10], DataType Number, DataType *top1, DataType *top2)
{
	if(Number == 1 && *top1 != 0)
		return (*str)[*top1-1];
	else if(Number == 2 && *top2 != 0)
		return (*str)[9-*top2+1];
}
//取栈低元素
DataType LastStackNode(DataType (*str)[10], DataType Number, DataType *top1, DataType *top2)
{
	if(Number == 1 && *top1 != 0)
		return (*str)[0];
	else if(Number == 2 && *top2 != 0)
		return (*str)[9];
}
//判空
DataType StackEmpty(DataType (*str)[10], DataType Number, DataType *top1, DataType *top2)
{
	if(Number == 1 && *top1 == 0)
	{
		return 1;
	}
	else if(Number == 2 && *top2 == 0)
	{
		return 1;
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值