问题:实现一个栈,要求含有函数push, pop, min,并且他们的时间复杂度都是O(1)。
解决思路:如图1所示,在普通栈的基础上,增加当前最小节点的指针currentMinNode,以及指向下一个最小节点的指针
nextMinNode。当push元素到栈里面时,如果新元素小于栈中的currentMinNode,需要更新当前最小元素指针currentMinNode,
使它指向新元素;如果新元素不小于currentMinNode,和普通栈一样直接添加新节点。当从栈中POP元素时,如果当前栈顶
节点的nextMinNode为空,则和普通栈一样直接删除栈顶节点;如果当前栈顶节点的nextMinNode不为空,则更新currentMinNode
指向栈顶节点的nextMinNode,然后再删除栈顶节点。本文主要说明求栈中最小值的情形,实际上,这里的处理思路可以很方便的迁移到求栈中最大值的情形。
图1 含有MIN函数的栈的结构
含有MIN函数的栈的C语言实现源码如下,这里栈中可存储的数据是简单的INT类型。
/*
* File: stack.h
* Purpose: implementation of stack which having MIN function in c
* Author: puresky
*/
#ifndef _STACK_H
#define _STACK_H
typedef struct StackNodeStruct StackNode;
struct StackNodeStruct
{
int _data;
struct StackNodeStruct *_next;
struct StackNodeStruct *_nextMinNode;
};
typedef struct StackStruct Stack;
struct StackStruct
{
StackNode *_top;
StackNode *_currentMinNode;
int _count;
};
Stack *stack_new();
void stack_free(Stack *st);
void stack_push(Stack *st, int data);
int stack_top(Stack *st);
int stack_pop(Stack *st);
int stack_min(Stack *st);
int stack_size(Stack *st);
int stack_empty(Stack *st);
void stack_print(Stack *st);
#endif
/*
* File: stack.c
* Purpose: implementation of stack in c
* Author: puresky
*/
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
StackNode *stack_node_new(int data)
{
StackNode *stn = (StackNode *)malloc(sizeof(StackNode));
stn->_data = data;
stn->_next = NULL;
stn->_nextMinNode = NULL;
return stn;
}
void stack_node_free(StackNode *stn)
{
if(stn)
{
free(stn);
}
}
Stack *stack_new()
{
Stack *st = (Stack *)malloc(sizeof(Stack));
st->_count = 0;
st->_top = NULL;
st->_currentMinNode = NULL;
return st;
}
void stack_free(Stack *st)
{
StackNode *stn;
StackNode *iter;
if(st)
{
iter = st->_top;
while(iter)
{
stn = iter;
iter = iter->_next;
stack_node_free(stn);
}
}
}
void stack_push(Stack *st, int data)
{
StackNode *stn = stack_node_new(data);
stn->_next = st->_top;
st->_top = stn;
st->_count++;
if(st->_currentMinNode == NULL)
{
st->_currentMinNode = stn;
}
else if(stn->_data < st->_currentMinNode->_data)
{
stn->_nextMinNode = st->_currentMinNode;
st->_currentMinNode = stn;
}
else
{
stn->_nextMinNode = NULL;
}
printf("push %d\n", data);
}
int stack_top(Stack *st)
{
if(st->_top)
{
return st->_top->_data;
}
fprintf(stderr, "top error : stack is empty!\n");
return -1;
}
int stack_pop(Stack *st)
{
int ret;
StackNode *stn;
if(st->_top)
{
if(st->_top->_nextMinNode)
{
st->_currentMinNode = st->_top->_nextMinNode;
}
ret = st->_top->_data;
stn = st->_top;
st->_top = st->_top->_next;
stack_node_free(stn);
st->_count--;
printf("pop %d\n", ret);
return ret;
}
fprintf(stderr, "pop error : stack is empty!\n");
return -1;
}
int stack_min(Stack *st)
{
if(st->_top)
{
return st->_currentMinNode->_data;
}
fprintf(stderr, "min error : stack is emtpy!\n");
return -1;
}
int stack_size(Stack *st)
{
return st->_count;
}
int stack_empty(Stack *st)
{
if(st->_top == NULL)
return 1;
return 0;
}
void stack_print(Stack *st)
{
StackNode *ptr = st->_top;
printf("--------------------------------------------------\n");
printf("stack size:%d\n", st->_count);
printf("stack min:%d\n", st->_currentMinNode->_data);
while(ptr)
{
printf("%d ", ptr->_data);
ptr = ptr->_next;
}
printf("\n--------------------------------------------------\n\n");
}
/*
* File: main.c
* Purpose: To test the stack
* Author: puresky
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "stack.h"
#define MAX_NUM 20
#define N 10
void init_stack(Stack *st, int size)
{
int i, j;
for(i = 0; i < size; ++i)
{
j = rand() % MAX_NUM;
stack_push(st, j);
}
}
int main(int argc, char **argv)
{
Stack *st = stack_new();
srand(time(NULL));
init_stack(st, N);
stack_print(st);
stack_pop(st);
stack_pop(st);
stack_pop(st);
stack_pop(st);
stack_pop(st);
stack_print(st);
stack_free(st);
system("pause");
return 0;
}