您的位置:首页 > 编程语言 > C语言/C++

C语言 复杂的栈(链表栈)

2016-03-01 13:35 507 查看
//复杂的栈--链表栈
#include<stdio.h>
#include<stdlib.h>

#define datatype int//定义链表栈数据类型
//定义链表栈结构
struct stacklink{
datatype data;
struct stacklink *pnext;
};

typedef struct stacklink StackLink;

//判断栈是否为空
int isempty(StackLink *phead);
//进栈
StackLink * push(StackLink *phead, datatype num);
//出栈
StackLink * pop(StackLink *phead, StackLink *pout);
//清空
StackLink * setempty(StackLink *phead);
//遍历栈中的数据
void findall(StackLink *phead);

//链表栈容量无限大,但是代价是增加链表遍历成本

void main(){
//定义链表栈的头指针
StackLink * phead = NULL;
//压栈
phead = push(phead, 1);
phead = push(phead, 2);
phead = push(phead, 3);
phead = push(phead, 4);
phead = push(phead, 5);
//打印栈中的数据
findall(phead);
//出栈
StackLink *pout = (StackLink *)malloc(sizeof(StackLink));
phead = pop(phead, pout);
printf("\n弹出的元素是%d;\n", pout->data);
free(pout);
////全部出栈
//while (phead!=NULL){
//    StackLink *pout = malloc(sizeof(StackLink));
//    phead = pop(phead, pout);
//    printf("\n弹出的元素是%d;\n", pout->data);
//    free(pout);
//}
printf("\n================================\n");
//打印栈中的数据
findall(phead);
printf("\n================================\n");
//清空栈内元素
phead = setempty(phead);
//打印栈中的数据
findall(phead);
system("pause");
}

//判断栈是否为空
int isempty(StackLink *phead){
if (phead == NULL)
{
return 1;
}
else{
return 0;
}
}

//进栈
StackLink * push(StackLink *phead, datatype num){
//分配内存空间
StackLink *p = (StackLink *)malloc(sizeof(StackLink));
StackLink *p1 = phead;
p->data = num;
p->pnext = NULL;
//判断栈是否为空
if (isempty(phead))
{
//栈为空
phead = p;
//注意:这里是给指针副本phead赋值,但是main()函数里phead的值并没有变化
//要在函数里修改一个指针的值,应该使用二级指针,但是根据代码优化原则,尽量不使用二级指针,
//因此我们将phead当做返回值返回
}
else{
while (p1->pnext != NULL){
p1 = p1->pnext;
}
p1->pnext = p;
//这里的phead->pnext会直接影响main()函数里phead的值,因为phead->pnext本质上等于(*phead).pnext
//修改的是phead指针指向数据的值,而不是修改phead本身
}
return phead;
}

//遍历栈中的数据
void findall(StackLink *phead){
StackLink *p = phead;
while (p != NULL){
printf("%d\n", p->data);
p = p->pnext;
}
}

//出栈
StackLink * pop(StackLink *phead, StackLink *pout){
if (phead == NULL)//判断栈是否为空
{
return NULL;
}
else{
pout->pnext = NULL;
//不为空
//出栈,每次弹出最后一个
//分两种情况
//1.只有一个元素,只有一个元素,只需要弹出头指针本身
if (phead->pnext == NULL)
{
//pout = phead; 错误,这样只是改变pout指向的地址,而free(phead)会彻底释放phead指向地址的内存
//结果就是pout也为NULL
pout->data = phead->data;

//注意:链表栈删除必须释放内存
free(phead);
phead = NULL;
//这个改变形参phead的值,所以只能返回phead,而有任何地方修改pout的值
return phead;
}
//2.多个元素,找到倒数第二个元素
else{
StackLink *p = phead;
while (phead->pnext->pnext != NULL){
phead = phead->pnext;
}
pout->data = phead->pnext->data;
//删除栈中最后一个元素
free(phead->pnext);
phead->pnext = NULL;
return p;
}

}
}

//清空
StackLink * setempty(StackLink *phead){
//清空的思路是,1,2,3,4,5通过头指针找到1,将2删除,把3移到2的位置上,再删除3
//不太清楚循环次数,所以用while
StackLink *p = NULL;
while (phead->pnext != NULL){//当第二个元素是NULL的时候,退出循环
//删除第二个
//p是第三个的指针
p = phead->pnext->pnext;
//开始删除第二个
free(phead->pnext);
phead->pnext = p;
}
//最后删除第一个元素
free(phead);
return NULL;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: