源码文件地址 :http://download.csdn.net/detail/mcu_tian/9530628
由前面:http://blog.csdn.net/mcu_tian/article/details/51493081所述
链表实现的栈在操作过程中频繁的pop和push会伴随着频繁的malloc和free,伴随着很大的系统开销。
基于此,在此实现中,通过实现一个空闲节点链表,将pop之后的链表节点不释放,而是放入空闲链表freeNodePtr中
当栈进行push操作的时候,先从空闲节点链表中中取出空闲节点加入栈链表中,若是空闲链表中,没有节点,则调用malloc,申请内存节点。
栈是否空栈只要判断指向栈顶指针是否为空即可。
实现的操作有pop、push、reset、isempty、create、dispose等基本函数,实现了链表节点 stacknode,以及栈的结构体ListIntStack等,具体如下
结构体
链表元素节点结构体
<pre name="code" class="cpp">struct StackIntNode //元素节点 { struct StackIntNode *pre; struct StackIntNode *next; int num;//元素节点值 };
typedef struct StackIntNode *StackNodePtr; typedef struct StackIntNode StackNode;
//栈结构体
struct ListIntStack//栈结构体
{
StackNodePtr topPtr;//栈顶
StackNodePtr freeNodePtr;//空闲链表
int lenght;//栈元素个数
};
typedef struct ListIntStack *ListStack;
函数
创建栈函数
该函数的主要功能为栈创建一个结构体对象,初始化后返回结构体对象指针。
<pre name="code" class="cpp">ListStack CreateListStack(int num) //创建链表栈
{
StackNodePtr tmpPtr;
ListStack s;
s = (ListStack)malloc(sizeof(struct ListIntStack));
if(s == NULL)
{
printf("creat list stact falied");
return NULL;
}
s->topPtr = NULL;
s->freeNodePtr = NULL;
s->lenght = 0;
return s;
}
释放栈函数
该函数的主要功能是1:链表节点释放,链表节点在栈链表中和free两个链表中 2:释放栈的结构体对象
void DisposeListStack(ListStack *ls)
{
StackNodePtr tmpPtr;
int count_num = 0; //计算一共有多少个节点被释放
tmpPtr = (*ls)->topPtr;
while(tmpPtr != NULL) //释放栈链表
{
(*ls)->topPtr = (*ls)->topPtr->pre;
free(tmpPtr);
tmpPtr = (*ls)->topPtr;
++count_num;
}
tmpPtr = (*ls)->freeNodePtr;//释放free链表
while(tmpPtr != NULL)
{
(*ls)->freeNodePtr = (*ls)->freeNodePtr->next;
free(tmpPtr);
tmpPtr = (*ls)->freeNodePtr;
++count_num;
}
free(*ls);
(*ls) = NULL;
printf("dispose count_num is %d\n",count_num);
}
是否为空栈
int IsListStackEmpty(ListStack ls)
{
return ls->topPtr == NULL;
}
栈push操作函数
栈的push操作,先判断空闲链表上时候有空闲节点,若有,则从空闲链表中取下节点,或则调用malloc申请
int ListStackPush(ListStack ls,int *element)//成功返回1,否则为-1,element 指向的为入栈的数据的指针
{
StackNodePtr tmp;
if(ls->freeNodePtr != NULL)
{
tmp = ls->freeNodePtr;
ls->freeNodePtr = ls->freeNodePtr->next;
if(ls->freeNodePtr != NULL)
{
ls->freeNodePtr->pre = NULL;
}
tmp->num = *element;
if(IsListStackEmpty(ls))
{
ls->topPtr = tmp;
tmp->next = tmp->pre = NULL;
}
else
{
ls->topPtr->next = tmp;
tmp->pre = ls->topPtr;
ls->topPtr=ls->topPtr->next;
tmp->next = NULL;
}
}
else
{
tmp = malloc(sizeof(StackNode));
if(tmp == NULL)
{
printf("malloc failed\n");
return -1;
}
tmp->num = *element;
if(ls->topPtr == NULL)
{
ls->topPtr = tmp;
tmp->next = NULL;
tmp->pre = NULL;
return 1;
}
ls->topPtr->next = tmp;
tmp->pre = ls->topPtr;
tmp->next = NULL;
ls->topPtr = ls->topPtr->next;
}
++ls->lenght;
return 1;
}
栈pop函数以及reset函数
该函数将栈链表总的栈顶元素取下来,放入到空闲链表中。
int ListstackPop(ListStack ls)//操作成功返回1.失败返回-1
{
StackNodePtr tmpPtr;
if(IsListStackEmpty(ls))
{
printf("list stack pop failed\n");
return -1;
}
tmpPtr = ls->topPtr;
ls->topPtr = ls->topPtr->pre;
if(ls->topPtr != NULL)
{
ls->topPtr->next = NULL;
}
tmpPtr->pre = NULL;
if(ls->freeNodePtr == NULL)
{
ls->freeNodePtr = tmpPtr;
}
else
{
ls->freeNodePtr->pre = tmpPtr;
tmpPtr->next = ls->freeNodePtr;
ls->freeNodePtr = ls->freeNodePtr->pre;
}
--ls->lenght;
return 1;
}
//迭代调用pop,直到栈为空
int ListStackReset(ListStack ls)
{
while(!IsListStackEmpty(ls))
{
if(ListstackPop(ls) != 1)
{
return -1;
}
}
return 1;
}
读栈链表的栈顶元素
int ListStackTop(ListStack ls,int *element)//将栈顶的值,放入到element指针指向的变量中
{
if(IsListStackEmpty(ls))
{
printf("Top is NULL\n");
return -1;
}
*element = ls->topPtr->num;
return 1;
}