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;
}