数据结构_之顺序栈_链栈的原理和实现及栈的广泛应用

数据结构_之顺序栈_链栈的原理和实现及栈的广泛应用

1.Stack基本概念 

概念:

  首先它是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底。  

注意:

  栈是一种  特殊的线性表

    栈仅能在线性表的一端进行操作

  栈顶(Top):允许操作的一端

  栈底(Bottom):不允许操作的一端

 特性

  它的特殊之处在于限制了这个线性表的插入和删除的位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能栈底

l操作

   栈的插入操作,叫做进栈,也成压栈。类似子弹入弹夹(如下图所示)

   栈的删除操作,叫做出栈,也有的叫做弾栈,退栈。如同弹夹中的子弹出夹(如下图所示)

2.栈的常用操作

  l 创建栈

  l 销毁栈

  l 清空栈

  l 进栈

  l 出栈

  l 获取栈顶元素

  l 获取栈的大小

 

ADT 栈(stack)
Data
    通线性表。元素具有相同的类型,相邻的元素具有前驱和后继关系。
Operation
    // 初始化,建立一个空栈S
    InitStack(*S);
    // 若栈存在,则销毁它
    DestroyStack(*S);
    // 将栈清空
    ClearStack(*S);
    // 若栈为空则返回true,否则返回false
    StackEmpty(S);
    // 若栈存在且非空,用e返回S的栈顶元素
    GetTop(S,*e);
    // 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
    Push(*S,e);
    // 删除栈S中的栈顶元素,并用e返回其值
    Pop(*S, *e);
    // 返回栈S的元素个数
    StackLength(S);
endADT

 

 1 #ifndef _MY_STACK_H_
 2 #define _MY_STACK_H_
 3 
 4 typedef void Stack;
 5 
 6 Stack* Stack_Create();
 7 
 8 void Stack_Destroy(Stack* stack);
 9 
10 void Stack_Clear(Stack* stack);
11 
12 int Stack_Push(Stack* stack, void* item);
13 
14 void* Stack_Pop(Stack* stack);
15 
16 void* Stack_Top(Stack* stack);
17 
18 int Stack_Size(Stack* stack);
19 
20 #endif //_MY_STACK_H_
View Code

3.栈模型和链表模型关系分析

4.栈的顺序存储设计与实现

基本概念

  栈的顺序存储结构简称顺序栈,它是运算受限制的顺序表。顺序栈的存储结构是:利用一组地址连续的的存储单元依次存放自栈底到栈顶的数据元素同时附设指针top只是栈顶元素在顺序表中的位置。

 

设计与实现

  (1)因为栈是一种特殊的线性表所以栈的顺序存储可以通过顺序线性表来实现。

头文件:

#ifndef  __MY_SEQLIST_H__ 
#define __MY_SEQLIST_H__

typedef void SeqList;
typedef void SeqListNode;

SeqList* SeqStack_Create(int capacity);

void SeqStack _Destroy(SeqStack * list);

void SeqStack _Clear(SeqStack * list);

int SeqStack _Length(SeqStack * list);

int SeqStack _Capacity(SeqStack * list);

int SeqStack _Insert(SeqStack * list, SeqListNode* node, int pos);

SeqListNode* SeqList_Get(SeqList* list, int pos);

SeqListNode* SeqList_Delete(SeqList* list, int pos);

#endif  //__MY_SEQLIST_H__

案例详细代码:

seqlist.h

 1 #ifndef  __MY_SEQLIST_H__ 
 2 #define __MY_SEQLIST_H__
 3 
 4 // #define  ERR_BASE  0
 5 // #define ERR_PARAM   ERR_BASE -1;
 6 
 7 typedef void SeqList;
 8 typedef void SeqListNode;
 9 
10 SeqList* SeqList_Create(int capacity);
11 
12 void SeqList_Destroy(SeqList* list);
13 
14 void SeqList_Clear(SeqList* list);
15 
16 int SeqList_Length(SeqList* list);
17 
18 int SeqList_Capacity(SeqList* list);
19 
20 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);
21 
22 SeqListNode* SeqList_Get(SeqList* list, int pos);
23 
24 SeqListNode* SeqList_Delete(SeqList* list, int pos);
25 
26 
27 #endif  //__MY_SEQLIST_H__
View Code

seqstack.h

 1 // seqstack.h
 2 
 3 #ifndef _MY_SEQSTACK_H_
 4 #define _MY_SEQSTACK_H_
 5 
 6 typedef void SeqStack;
 7 
 8 SeqStack* SeqStack_Create(int capacity);
 9 
10 void SeqStack_Destroy(SeqStack* stack);
11 
12 void SeqStack_Clear(SeqStack* stack);
13 
14 int SeqStack_Push(SeqStack* stack, void* item);
15 
16 void* SeqStack_Pop(SeqStack* stack);
17 
18 void* SeqStack_Top(SeqStack* stack);
19 
20 int SeqStack_Size(SeqStack* stack);
21 
22 int SeqStack_Capacity(SeqStack* stack);
23 
24 #endif //_MY_SEQSTACK_H_
View Code

seqlist.c

  1 #include "stdlib.h"
  2 #include "stdio.h"
  3 #include "string.h"
  4 #include "seqlist.h"
  5 
  6 typedef struct _tag_SeqList
  7 {
  8     int capacity;
  9     int length;
 10     unsigned int *node ; // unsigned int nodeAarry[100]
 11     //void *node ;
 12 }TSeqList;
 13 
 14 //typdef的意思 把void 重新命名成SeqList
 15 
 16 /*
 17 void * SeqList_Create2(int capacity)
 18 {
 19     TSeqList *ret = NULL;
 20     ret = (TSeqList *)malloc(sizeof(TSeqList));
 21     if (ret == NULL)
 22     {
 23         return NULL;
 24     }
 25     ret->capacity = capacity;
 26     ret->node = (unsigned int *)malloc(sizeof(unsigned int ) * capacity);
 27     if (ret->node == NULL)
 28     {
 29         return NULL;
 30     }
 31     ret->length = 0;
 32     return ret;
 33 }
 34 */
 35 
 36 void * SeqList_Create(int capacity)
 37 {
 38     TSeqList *ret = NULL;
 39 
 40     if (capacity <= 0)
 41     {
 42         return NULL;
 43     }
 44     ret = (TSeqList *)malloc(sizeof(TSeqList) + sizeof(unsigned int ) * capacity );
 45     if (ret == NULL)
 46     {
 47         return NULL;
 48     }
 49     ret->capacity = capacity;
 50     ret->node = (unsigned int *)(ret + 1);
 51     
 52     ret->length = 0;
 53     return ret;
 54 }
 55 
 56 void SeqList_Destroy(SeqList* list)
 57 {
 58     if (list == NULL)
 59     {
 60         return ;
 61     }
 62     free(list);
 63     return ;
 64 }
 65 
 66 void SeqList_Clear(SeqList* list)
 67 {
 68     TSeqList *tlist = NULL;
 69     if (list == NULL)
 70     {
 71         return ;
 72     }
 73     tlist = (TSeqList *)list;
 74 
 75     tlist->length = 0;
 76     return ;
 77 }
 78 
 79 int SeqList_Length(SeqList* list)
 80 {
 81     TSeqList *tlist = list;
 82     if (list == NULL)
 83     {
 84         return -1;
 85     }
 86     return tlist->length;
 87 }
 88 
 89 int SeqList_Capacity(SeqList* list)
 90 {
 91     TSeqList *tlist = list;
 92     if (list == NULL)
 93     {
 94         return -1;
 95     }
 96     return tlist->capacity;
 97 }
 98 
 99 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
100 {
101     int i = 0;
102     TSeqList *tlist = list;
103 
104     if (list == NULL || node== NULL )
105     {
106         return -1;
107     }
108 
109     if (pos<0 || pos>=tlist->capacity )
110     {
111         return -2;
112     }
113 
114     //判断是否已经man
115     if (tlist->length >= tlist->capacity)
116     {
117         return -3;
118     }
119 
120     //容错
121     if (pos > tlist->length)
122     {
123         pos = tlist->length;
124     }
125     
126     //插入算法 有两步
127     //从插入的位置 后移元素 
128     //注意length能表示出现在数组的最后元素位置
129     //最后元素的下标为 tlist->node[length-1];
130     for (i=tlist->length; i>pos; i--)
131     {
132         tlist->node[i] = tlist->node[i-1];
133     }
134     //在pos位置插入元素
135     tlist->node[pos] = (unsigned int)node; //20140514这个地方不能加 (unsigned int *)
136     //如果你加*,说明你对    unsigned int *node ; // unsigned int nodeAarry[100]还没有理解 
137     tlist->length ++;
138 
139     return 0;
140 }
141 
142 SeqListNode* SeqList_Get(SeqList* list, int pos)
143 {
144     int i = 0;
145     TSeqList *tlist = list;
146     //if (list== NULL || pos<0 || pos>=tlist->length)
147     if (list== NULL || pos<0 || pos>tlist->length)
148     {
149         return NULL;
150     }
151     return (SeqListNode*)tlist->node[pos];
152 }
153 
154 SeqListNode* SeqList_Delete(SeqList* list, int pos)
155 {
156     int i = 0;
157     TSeqList *tlist = list;
158     SeqListNode* ret = NULL;
159     if (list == NULL || pos<0 || pos>tlist->length)
160     {
161         return NULL;
162     }
163     //缓存要删除的结点
164     ret = (SeqListNode*)tlist->node[pos];
165     //对链表进行移动
166     for (i=pos+1; i<tlist->length; i++)
167     {
168         tlist->node[i-1] = tlist->node[i];
169      }
170     tlist->length --;
171     return ret;
172 }
View Code

seqstack.c

 1 #include "stdio.h"
 2 #include "stdlib.h"
 3 #include "string.h"
 4 
 5 #include "seqstack.h"
 6 #include "seqlist.h"  //线性表的顺序存储头文件
 7 
 8 
 9 SeqStack* SeqStack_Create(int capacity)
10 {
11     return SeqList_Create(capacity);
12 }
13 
14 void SeqStack_Destroy(SeqStack* stack)
15 {
16      SeqList_Destroy(stack);
17 }
18 
19 void SeqStack_Clear(SeqStack* stack)
20 {
21      SeqList_Clear(stack);
22 }
23 
24 //往栈中放元素,相当于向线性表中放元素
25 int SeqStack_Push(SeqStack* stack, void* item)
26 {
27     return SeqList_Insert(stack, item, SeqList_Length(stack));
28 }
29 
30 //从栈中弹出元素,相当于从线性表中删除元素
31 void* SeqStack_Pop(SeqStack* stack)
32 {
33     return SeqList_Delete(stack, SeqList_Length(stack) -1);
34 }
35 
36 void* SeqStack_Top(SeqStack* stack)
37 {
38     return SeqList_Get(stack, SeqList_Length(stack)-1);;
39 }
40 
41 int SeqStack_Size(SeqStack* stack)
42 {
43     return SeqList_Length(stack);
44 }
45 
46 int SeqStack_Capacity(SeqStack* stack)
47 {
48     return SeqList_Capacity(stack);
49 }
View Code

seqstack动态库集成测试.c

 1 #include "stdio.h"
 2 #include "stdlib.h"
 3 #include "string.h"
 4 #include "seqstack.h"
 5 
 6 void main()
 7 {
 8 
 9     int a[20], i = 0;
10     int *pTmp = NULL;
11     SeqStack* stack = NULL;
12 
13     stack = SeqStack_Create(20);
14 
15     for (i=0; i<10; i++)
16     {
17         a[i] = i+1;
18         //SeqStack_Push(stack, &a[i]);
19         SeqStack_Push(stack, a+i);
20     }
21 
22     pTmp = (int *)SeqStack_Top(stack);
23     printf("top:%d \n", *pTmp);
24 
25     printf("capacity:%d \n", SeqStack_Capacity(stack));
26 
27     printf("size:%d \n", SeqStack_Size(stack));
28 
29     //元素出栈
30     while (SeqStack_Size(stack) > 0)
31     {
32         printf("pop:%d \n", *((int *)SeqStack_Pop(stack)) );
33     }
34 
35     SeqStack_Destroy(stack);
36 
37     system("pause");
38 }
View Code

  (2)不通过线性表实现(版本1)

SqStack.h

#ifndef _SQSTACK_H
#define _SQSTACK_H

#define MAXSIZE 50
typedef struct _SQSTACK
{
    int top;    // 栈顶指针
    unsigned int data[MAXSIZE];
}SqStack;

// 初始化,建立一个空栈S
void InitStack(SqStack *S);

// 将栈清空
void ClearStack(SqStack *S);

// 若栈为空则返回true,否则返回false
int StackEmpty(SqStack S);

// 若栈存在且非空,用e返回S的栈顶元素
void GetTop(SqStack S, void **e);

// 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
void Push(SqStack *S, void *e);

// 删除栈S中的栈顶元素,并用e返回其值
void Pop(SqStack *S, void **e);

// 返回栈S的元素个数
int StackLength(SqStack S);

#endif // _SQSTACK_H

SqStack.c

#include "SqStack.h"
#include <string.h>

void InitStack(SqStack *S)
{
    // 空栈
    S->top = -1;
    memset(S->data, 0, sizeof(S->data));
}

void ClearStack(SqStack *S)
{
    S->top = -1;
}

int StackEmpty(SqStack S)
{
    if (S.top == -1)
    {
        return 1;
    }
    return 0;
}

void GetTop(SqStack S, void **e)
{
    // 栈为空
    if (S.top == -1)
    {
        return;
    }
    *e = (void*)S.data[S.top];
}

void Push(SqStack *S, void *e)
{
    // 栈已经满了
    if (S->top == MAXSIZE - 1)
    {
        return;
    }
    // 栈顶上移
    S->top++;
    // 赋值
    S->data[S->top] = (unsigned int)e;
}

void Pop(SqStack *S, void **e)
{
    // 栈为空
    if (S->top == -1)
    {
        return;
    }
    // 赋值
    *e = S->data[S->top];
    // 栈顶指针下移
    S->top--;
}

int StackLength(SqStack S)
{
    return S.top + 1;
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "SqStack.h"


typedef struct stu
{
    int id;
    int age;
}Student;

void main()
{
    Student stu[10];

    // 定义栈变量
    SqStack st;
    // 初始化栈
    InitStack(&st);
    // 压栈
    for (int i = 0; i < 10; ++i)
    {
        stu[i].id = i;
        stu[i].age = i + 20;
        // 压栈
        Push(&st, (void*)&stu[i]);
    }

    printf("stack size = %d\n", StackLength(st));

    // 出栈
    while (StackEmpty(st) != 1)
    {
        Student* p;
        // 取栈顶元素
        GetTop(st, (void**)&p);
        printf("stack top elem id = %d, age=%d\n", p->id, p->age);

        // 删除栈顶元素
        Pop(&st, (void*)&p);
        printf("Delete stack elem id = %d, age=%d\n", p->id, p->age);
    }
    system("pause");
}

  (3)不通过线性表实现(版本2)

SeqStack.h

 1 #ifndef SEQSTACK_H
 2 #define SEQSTACK_H
 3 
 4 #include<stdlib.h>
 5 #include<stdio.h>
 6 
 7 //数组去模拟栈的顺序存储
 8 #define MAX_SIZE 1024
 9 #define SEQSTACK_TRUE 1
10 #define SEQSTACK_FALSE 0
11 
12 typedef struct SEQSTACK{
13     void* data[MAX_SIZE];
14     int size;
15 }SeqStack;
16 
17 //初始化栈
18 SeqStack* Init_SeqStack();
19 //入栈
20 void Push_SeqStack(SeqStack* stack,void* data);
21 //返回栈顶元素
22 void* Top_SeqStack(SeqStack* stack);
23 //出栈
24 void Pop_SeqStack(SeqStack* stack);
25 //判断是否为空
26 int IsEmpty(SeqStack* stack);
27 //返回栈中元素的个数
28 int Size_SeqStack(SeqStack* stack);
29 //清空栈
30 void Clear_SeqStack(SeqStack* stack);
31 //销毁
32 void FreeSpace_SeqStack(SeqStack* stack);
33 
34 
35 #endif
View Code

SeqStack.c

 1 #include"SeqStack.h"
 2 
 3 //初始化栈
 4 SeqStack* Init_SeqStack(){
 5 
 6     SeqStack* stack = (SeqStack*)malloc(sizeof(SeqStack));
 7     for (int i = 0; i < MAX_SIZE;i++){
 8         stack->data[i] = NULL;
 9     }
10     stack->size = 0;
11 
12     return stack;
13 }
14 //入栈
15 void Push_SeqStack(SeqStack* stack, void* data){
16 
17     if (stack == NULL){
18         return;
19     }
20     if (stack->size == MAX_SIZE){
21         return;
22     }
23     if (data == NULL){
24         return;
25     }
26 
27     stack->data[stack->size] = data;
28     stack->size++;
29 }
30 //返回栈顶元素
31 void* Top_SeqStack(SeqStack* stack){
32     if (stack == NULL){
33         return NULL;
34     }
35 
36     if (stack->size == 0){
37         return NULL;
38     }
39 
40     return stack->data[stack->size-1];
41 }
42 //出栈
43 void Pop_SeqStack(SeqStack* stack){
44     if (stack == NULL){
45         return;
46     }
47     if (stack->size == 0){
48         return;
49     }
50     stack->data[stack->size - 1] = NULL;
51     stack->size--;
52 }
53 //判断是否为空
54 int IsEmpty(SeqStack* stack){
55     if (stack == NULL){
56         return -1;
57     }
58 
59     if (stack->size == 0){
60         return SEQSTACK_TRUE;
61     }
62 
63     return SEQSTACK_FALSE;
64 }
65 //返回栈中元素的个数
66 int Size_SeqStack(SeqStack* stack){
67     return stack->size;
68 }
69 //清空栈
70 void Clear_SeqStack(SeqStack* stack){
71     if (stack == NULL){
72         return;
73     }
74     for (int i = 0; i < stack->size;i++){
75         stack->data[i] = NULL;
76     }
77     stack->size = 0;
78 }
79 //销毁
80 void FreeSpace_SeqStack(SeqStack* stack){
81 
82     if (stack == NULL){
83         return;
84     }
85 
86     free(stack);
87 }
View Code

栈的顺序存储.c

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <string.h>
 5 #include "SeqStack.h"
 6 
 7 typedef struct PERSON{
 8     char name[64];
 9     int age;
10 }Person;
11 
12 int main(void){
13     
14     //创建栈
15     SeqStack* stack = Init_SeqStack();
16 
17     //创建数据
18     Person p1 = { "aaa", 10 };
19     Person p2 = { "bbb", 20 };
20     Person p3 = { "ccc", 30 };
21     Person p4 = { "ddd", 40 };
22     Person p5 = { "eee", 50 };
23 
24     //入栈
25     Push_SeqStack(stack, &p1);
26     Push_SeqStack(stack, &p2);
27     Push_SeqStack(stack, &p3);
28     Push_SeqStack(stack, &p4);
29     Push_SeqStack(stack, &p5);
30 
31     //输出
32     while (Size_SeqStack(stack) > 0){
33         //访问栈顶元素
34         Person* person = (Person*)Top_SeqStack(stack);
35         printf("Name:%s Age:%d\n",person->name,person->age);
36         //弹出栈顶元素
37         Pop_SeqStack(stack);
38     }
39 
40     //释放内存
41     FreeSpace_SeqStack(stack);
42 
43     system("pause");
44     return 0;
45 }
View Code

5.栈的链式存储设计与实现

基本概念

  栈的链式存储结构简称链栈。

思考如下问题

  栈只是栈顶来做插入和删除操作,栈顶放在链表的头部还是尾部呢?

  由于单链表有头指针,而栈顶指针也是必须的,那干嘛不让他俩合二为一呢,所以比较好的办法就是把栈顶放在单链表的头部。另外都已经有了栈顶在头部了,单链表中比较常用的头结点也就失去了意义,通常对于链栈来说,是不需要头结点的。

设计与实现

  链栈是一种特殊的线性表,链栈可以通过链式线性表来实现。

   (1)链栈可以通过链式线性表来实现:

linklist.h

 1 #ifndef _MYLINKLIST_H_
 2 #define _MYLINKLIST_H_
 3 
 4 typedef void LinkList;
 5 /*
 6 typedef struct _tag_LinkListNode LinkListNode;
 7 struct _tag_LinkListNode
 8 {
 9     LinkListNode* next;
10 };
11 */
12 typedef struct _tag_LinkListNode
13 {
14     struct _tag_LinkListNode* next;
15 }LinkListNode;
16 
17 LinkList* LinkList_Create();
18 
19 void LinkList_Destroy(LinkList* list);
20 
21 void LinkList_Clear(LinkList* list);
22 
23 int LinkList_Length(LinkList* list);
24 
25 int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
26 
27 LinkListNode* LinkList_Get(LinkList* list, int pos);
28 
29 LinkListNode* LinkList_Delete(LinkList* list, int pos);
30 
31 #endif
View Code

linkstack.h

 1 #ifndef _MY_LINKSTACK_H_
 2 #define _MY_LINKSTACK_H_
 3 
 4 typedef void LinkStack;
 5 
 6 LinkStack* LinkStack_Create();
 7 
 8 void LinkStack_Destroy(LinkStack* stack);
 9 
10 void LinkStack_Clear(LinkStack* stack);
11 
12 int LinkStack_Push(LinkStack* stack, void* item);
13 
14 void* LinkStack_Pop(LinkStack* stack);
15 
16 void* LinkStack_Top(LinkStack* stack);
17 
18 int LinkStack_Size(LinkStack* stack);
19 
20 #endif //_MY_LINKSTACK_H_
View Code

linklist.c

  1 #include<stdio.h>
  2 #include "stdlib.h"
  3 #include "string.h"
  4 
  5 #include "linklist.h"
  6 
  7 typedef struct _tag_LinkList
  8 {
  9     //这个句柄里面,需要保存所有节点信息。需要有一个起始点
 10     //就是带头节点的链表。。。
 11     LinkListNode header;
 12     int length;
 13 }TLinkList;
 14 
 15 LinkList* LinkList_Create()
 16 {
 17     TLinkList *ret = (TLinkList *)malloc(sizeof(TLinkList));
 18     if (ret == NULL)
 19     {
 20         return NULL;
 21     }
 22     //memset(ret, 0, sizeof(TLinkList));
 23     ret->header.next = NULL;
 24     ret->length = 0;
 25     return ret;
 26 }
 27 
 28 void LinkList_Destroy(LinkList* list)
 29 {
 30     if (list == NULL)
 31     {
 32         return ;
 33     }
 34     free(list);
 35     return ;
 36 }
 37 
 38 void LinkList_Clear(LinkList* list)
 39 {
 40 
 41     TLinkList *tList =NULL;
 42     
 43     if (list == NULL)
 44     {
 45         return ;
 46     }
 47     tList = (TLinkList *)list;
 48     tList->length = 0;
 49     tList->header.next = NULL;
 50     return ;
 51 }
 52 
 53 int LinkList_Length(LinkList* list)
 54 {
 55 
 56     TLinkList *tList = (TLinkList *)list;
 57     if (tList == NULL)
 58     {
 59         return -1;
 60     }
 61 
 62     return tList->length;
 63 }
 64 
 65 int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)
 66 {
 67     int i = 0;
 68 
 69     TLinkList *tList  = NULL;
 70     LinkListNode *current = NULL;
 71 
 72     tList = (TLinkList *)list;
 73 
 74     if (list==NULL || node==NULL) //modify by bombing 2014.06.26
 75     {
 76         return -1;
 77     }
 78 
 79     //准备环境让辅助指针变量 指向链表头节点
 80     current = &tList->header;
 81     for (i=0; i<pos &&(current->next!=NULL); i++)
 82     {
 83         current = current->next;
 84     }
 85 
 86     //让node节点链接后续链表
 87     node->next = current->next ;
 88     //让前边的链表。链接node
 89     current->next = node;
 90     tList->length ++;    
 91     return 0;
 92 }
 93 
 94 LinkListNode* LinkList_Get(LinkList* list, int pos)
 95 {
 96 
 97     int i = 0;
 98 
 99     TLinkList *tList  = NULL;
100     LinkListNode *current = NULL;
101     LinkListNode *ret = NULL;
102     tList = (TLinkList *)list;
103 
104     if (list == NULL || pos <0 ||pos>=tList->length)
105     {
106         return NULL;
107     }
108     //准备环境让辅助指针变量 指向链表头节点
109     current = &tList->header;
110     for (i=0; i<pos &&(current->next!=NULL); i++)
111     {
112         current = current->next;
113     }
114     ret = current->next;
115 
116     return ret;
117 }
118 
119 LinkListNode* LinkList_Delete(LinkList* list, int pos)
120 {
121     int i = 0;
122 
123     TLinkList *tList  = NULL;
124     LinkListNode *current = NULL;
125     LinkListNode *ret = NULL;
126     tList = (TLinkList *)list;
127 
128     if (list == NULL || pos <0 ||pos>=tList->length)
129     {
130         return NULL;
131     }
132     //准备环境让辅助指针变量 指向链表头节点
133     current = &tList->header;
134     for (i=0; i<pos &&(current->next!=NULL); i++)
135     {
136         current = current->next;
137     }
138     ret = current->next;
139 
140     //删除算法
141     current->next =ret->next;
142     tList->length--;
143 
144     return ret;
145 }
View Code

linkstack.c

 1 #include "stdlib.h"
 2 #include "stdio.h"
 3 #include "string.h"
 4 #include "linkstack.h"
 5 #include "linklist.h"
 6 
 7 typedef struct _tag_LinkStackNode
 8 {
 9     LinkListNode node; //占位结构。。。只要定义一个和node节大小一样的数据即可
10     void *item;
11 }TLinkStackNode;
12 
13 //我要创建一个linkstack,准备用linklist去模拟实现
14 //相当于在 linkstack.c中写 linklist库的测试程序。。。。。。
15 LinkStack* LinkStack_Create()
16 {
17     //创建一个栈,通过线性表去模拟。。。(创建一个栈,相当于创建一个线性表)
18     return LinkList_Create();
19 }
20 
21 void LinkStack_Destroy(LinkStack* stack)
22 {
23     LinkStack_Clear(stack); //注意 destory的时候,需要把栈中的所有元素都清空
24     LinkList_Destroy(stack);
25 }
26 
27 void LinkStack_Clear(LinkStack* stack)
28 {
29     //LinkList_Clear(stack);
30     while (LinkStack_Size(stack) > 0)
31     {
32         LinkStack_Pop(stack); //在这个函数里面有内存释放函数
33     }
34     return ;
35 }
36 
37 //向栈中放元素,相当于 向线性表中插入一个元素
38 int LinkStack_Push(LinkStack* stack, void* item)
39 {
40     int ret = 0;
41     //需要item数据,转换成 linklist的业务节点
42     TLinkStackNode *pTe = (TLinkStackNode *)malloc(sizeof(TLinkStackNode));
43     if (pTe == NULL)
44     {
45         return -1;
46     }
47     pTe->item = item;
48 
49     //头插法 ,向线性表中插入元素,只不过是插入元素的时候,需要构造业务节点而已。。。。。。
50     ret = LinkList_Insert(stack, (LinkListNode *)(&pTe->node),0 );
51     if (ret != 0)
52     {
53         free(pTe);
54     }
55     return ret;
56 }
57 
58 void* LinkStack_Pop(LinkStack* stack)
59 {
60     void *myItem = NULL;
61     TLinkStackNode *pTmp = NULL;
62     pTmp = (TLinkStackNode *)LinkList_Delete(stack, 0);
63     if (pTmp == NULL)
64     {
65         return NULL;
66     }
67     myItem = pTmp->item;
68 
69     //注意向线性表中,插入元素的时,打造节点,分配内存;
70     //弹出元素时,需要释放节点内存,不要忘记
71 
72     if (pTmp != NULL)  
73     {
74         free(pTmp);
75     }
76     return myItem;
77 }
78 
79 void* LinkStack_Top(LinkStack* stack)
80 {
81     void *myItem = NULL;
82     TLinkStackNode *pTmp = NULL;
83     pTmp = (TLinkStackNode *)LinkList_Get(stack, 0);
84     if (pTmp == NULL)
85     {
86         return NULL;
87     }
88     myItem = pTmp->item;
89     return myItem;
90 }
91 
92 int LinkStack_Size(LinkStack* stack)
93 {
94     return LinkList_Length(stack);
95 }
View Code

linkstack集成测试.c

 1 #include "stdlib.h"
 2 #include "stdio.h"
 3 #include "string.h"
 4 #include "linkstack.h"
 5 
 6 void main()
 7 {
 8     int a[10],  i;
 9     LinkStack *stack = NULL;
10 
11     stack = LinkStack_Create();
12 
13     for (i=0; i<10; i++)
14     {
15         a[i] = i+1;
16         LinkStack_Push(stack, &a[i]);
17     }
18     printf("top: %d \n",  *((int *)LinkStack_Top(stack)));
19     printf("size: %d \n", LinkStack_Size(stack));
20 
21     //删除栈中所有元素
22     while (LinkStack_Size(stack) > 0)
23     {
24         printf("linkstack pop: %d \n",  *((int*)LinkStack_Pop(stack)) );
25     }
26     LinkStack_Destroy(stack);
27     
28     system("pause");
29 }
View Code

  (2)不通过线性表实现(版本1)

LinkStack.h

#ifndef LINKSTACK_H
#define LINKSTACK_H

#include <stdlib.h>
#include <stdio.h>

//链式栈的结点
typedef struct LINKNODE{
    struct LINKNODE* next;
}LinkNode;

//链式栈
typedef struct LINKSTACK{
    LinkNode head;
    int size;
}LinkStack;

//初始化函数
LinkStack* Init_LinkStack();
//入栈
void Push_LinkStack(LinkStack* stack, LinkNode* data);
//出栈
void Pop_LinkStack(LinkStack* stack);
//返回栈顶元素
LinkNode* Top_LinkStack(LinkStack* stack);
//返回栈元素的个数
int Size_LinkStack(LinkStack* stack);
//清空栈
void Clear_LinkStack(LinkStack* stack);
//销毁栈
void FreeSpace_LinkStack(LinkStack* stack);

#endif

LinkStack.c

#include"LinkStack.h"
//初始化函数
LinkStack* Init_LinkStack(){

    LinkStack* stack = (LinkStack*)malloc(sizeof(LinkStack));
    stack->head.next = NULL;
    stack->size = 0;

    return stack;
}
//入栈
void Push_LinkStack(LinkStack* stack, LinkNode* data){

    if (stack == NULL){
        return;
    }

    if (data == NULL){
        return;
    }
    
    data->next = stack->head.next;
    stack->head.next = data;
    stack->size++;
}
//出栈
void Pop_LinkStack(LinkStack* stack){
    if (stack == NULL){
        return;
    }

    if (stack->size == 0){
        return;
    }
    
    //第一个有效结点
    LinkNode* pNext = stack->head.next;
    stack->head.next = pNext->next;

    stack->size--;
}
//返回栈顶元素
LinkNode* Top_LinkStack(LinkStack* stack){
    if (stack == NULL){
        return NULL;
    }
    if (stack->size == 0){
        return NULL;
    }
    return stack->head.next;
}
//返回栈元素的个数
int Size_LinkStack(LinkStack* stack){
    if (stack == NULL){
        return -1;
    }
    return stack->size;
}
//清空栈
void Clear_LinkStack(LinkStack* stack){
    if (stack == NULL){
        return;
    }
    stack->head.next = NULL;
    stack->size = 0;
}
//销毁栈
void FreeSpace_LinkStack(LinkStack* stack){
    if (stack == NULL){
        return;
    }
    free(stack);
}

栈的链式存储.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "LinkStack.h"

typedef struct PERSON{
    LinkNode node;
    char name[64];
    int age;
}Person;

int main(void){
    
    //创建栈
    LinkStack* stack = Init_LinkStack();

    //创建数据
    Person p1, p2, p3, p4, p5;
    strcpy(p1.name, "aaa");
    strcpy(p2.name, "bbb");
    strcpy(p3.name, "ccc");
    strcpy(p4.name, "ddd");
    strcpy(p5.name, "eee");

    p1.age = 10;
    p2.age = 20;
    p3.age = 30;
    p4.age = 40;
    p5.age = 50;

    //入栈
    Push_LinkStack(stack, (LinkNode*)&p1);
    Push_LinkStack(stack, (LinkNode*)&p2);
    Push_LinkStack(stack, (LinkNode*)&p3);
    Push_LinkStack(stack, (LinkNode*)&p4);
    Push_LinkStack(stack, (LinkNode*)&p5);

    //输出
    while (Size_LinkStack(stack) > 0){
        
        //取出栈顶元素
        Person* p = (Person*)Top_LinkStack(stack);
        printf("Name:%s Age:%d\n",p->name,p->age);
        //弹出栈顶元素
        Pop_LinkStack(stack);
    }

    //销毁栈
    FreeSpace_LinkStack(stack);

    system("pause");
    return 0;
}

(3)不通过线性表实现(版本2)

 LinkStack.h

 1 #ifndef _LINKSTACK_H
 2 #define _LINKSTACK_H
 3 
 4 // 定义小链表节点
 5 typedef struct NODE
 6 {
 7     struct NODE* next;
 8 }Node;
 9 
10 // 链表结构体
11 typedef struct
12 {
13     // 栈顶指针
14     Node *top;
15     // 长度
16     int length;
17 }LinkStack;
18 
19 // 初始化,建立一个空栈S
20 void InitStack(LinkStack *S);
21 
22 // 将栈清空
23 void ClearStack(LinkStack *S);
24 
25 // 若栈为空则返回true,否则返回false
26 int StackEmpty(LinkStack S);
27 
28 // 若栈存在且非空,用e返回S的栈顶元素
29 void GetTop(LinkStack S, Node **e);
30 
31 // 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
32 void Push(LinkStack *S, Node *e);
33 
34 // 删除栈S中的栈顶元素,并用e返回其值
35 void Pop(LinkStack *S, Node **e);
36 
37 // 返回栈S的元素个数
38 int StackLength(LinkStack S);
39 
40 #endif    // _LINKSTACK_H
View Code

LinkStack.c

 1 #include "LinkStack.h"
 2 #include <stdio.h>
 3 
 4 void InitStack(LinkStack *S)
 5 {
 6     S->length = 0;
 7     S->top = NULL;
 8 }
 9 
10 void ClearStack(LinkStack *S)
11 {
12     while (S->length)
13     {
14         Node* p;
15         Pop(S, &p);
16     }
17 }
18 
19 int StackEmpty(LinkStack S)
20 {
21     if (S.length == 0)
22     {
23         return 1;
24     }
25     return 0;
26 }
27 
28 void GetTop(LinkStack S, Node **e)
29 {
30     // 空栈
31     if (S.length == 0)
32     {
33         return;
34     }
35     *e = S.top;
36 }
37 
38 // 栈顶是链表头部
39 void Push(LinkStack *S, Node *e)
40 {
41     // 节点e插入到链表的头部
42     e->next = S->top;
43     // top指针指向第一个节点
44     S->top = e;
45     // 长度+1
46     S->length++;
47 }
48 
49 void Pop(LinkStack *S, Node **e)
50 {
51     // 空栈
52     if (S->length == 0)
53     {
54         return;
55     }
56     // 删除第一个节点
57     Node* pDel = S->top;
58     // 赋值
59     *e = pDel;
60     // 栈顶指针后移
61     S->top = pDel->next;
62     // 长度减1
63     S->length--;
64 }
65 
66 int StackLength(LinkStack S)
67 {
68     return S.length;
69 }
View Code

main.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include "LinkStack.h"
 4 
 5 // 业务节点
 6 typedef struct stu
 7 {
 8     // 包含链表节点
 9     Node node;
10     int id;
11     int age;
12 }Student;
13 
14 void main()
15 {
16     Student stu[10];
17     // 链表结构变量
18     LinkStack st;
19     // 初始化栈
20     InitStack(&st);
21     // 初始化数组
22     for (int i = 0; i < sizeof(stu) / sizeof(Student); ++i)
23     {
24         stu[i].id = i;
25         stu[i].age = i + 20;
26         // 数据添加链表中
27         Push(&st, &stu[i].node);
28     
29 
30     printf("stack size = %d\n", StackLength(st));
31 
32     while (StackEmpty(st) != 1)
33     {
34         Node* p;
35         // 获取栈顶元素
36         GetTop(st, &p);
37         Student* pp = (Student*)p;
38         printf("elem id = %d, age=%d\n", pp->id, pp->age);
39 
40         // 删除
41         Pop(&st, &p);
42         pp = (Student*)p;
43         printf("Delete elem id = %d, age=%d\n", pp->id, pp->age);
44     }
45 }
View Code

6.栈的应用

案例1:就近匹配 

案例:

  几乎所有的编译器都具有检测括号是否匹配的能力,那么如何实现编译器中的符号成对检测?如下字符串:

   #include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0;} 

l 算法思路

  n 从第一个字符开始扫描

  n 当遇见普通字符时忽略,

  n 当遇见左符号时压入栈中

  n 当遇见右符号时从栈中弹出栈顶符号,并进行匹配

  n 匹配成功:继续读入下一个字符

  n 匹配失败:立即停止,并报错

  n 结束:

  n 成功: 所有字符扫描完毕,且栈为空

  n 失败:匹配失败或所有字符扫描完毕但栈非空

l 总结

  n当需要检测成对出现但又互不相邻的事物时可以使用栈“后进先出”的特性

  n 栈非常适合于需要“就近匹配”的场合

l 思考

  计算机的本质工作就是做数学运算,那计算机可以读入字符串

  “9 + (3 - 1) * 5 + 8 / 2”并计算值吗?

就近匹配.cpp

#include <iostream>
#include <stack>
using namespace std;

// 判断左括号
bool isLeft(char c)
{
    bool bl;
    switch (c)
    {
    case '[':
    case '(':
    case '{':
    case '<':
        bl = true;
        break;
    default:
        bl = false;
        break;
    }
    return bl;
}

bool isRight(char c)
{
    bool bl;
    switch (c)
    {
    case ']':
    case ')':
    case '}':
    case '>':
        bl = true;
        break;
    default:
        bl = false;
        break;
    }
    return bl;
}

bool match(char left, char right)
{
    bool bl;
    switch (left)
    {
    case '[':
        bl = right == ']';
        break;
    case '(':
        bl = right == ')';
        break;
    case '{':
        bl = right == '}';
        break;
    case '<':
        bl = right == '>';
        break;
    default:
        bl = false;
        break;
    }
    return bl;
}


void Jiujinpipei(const char* p)
{
    int i = 0;
    stack<char> st;
    while (p[i] != '\0')
    {
        // 如果是左括号
        if (isLeft(p[i]))
        {
            // 压栈
            st.push(p[i]);
        }
        // 右括号
        else if (isRight(p[i]))
        {
            if (!st.empty())
            {
                // 栈顶符号
                char top = st.top();
                // 匹配
                if (!match(top, p[i]))
                {
                    cout << "匹配失败!" << endl;
                    break;
                }
                st.pop();
            }
            else
            {
                cout << "缺少左括号..." << endl;
                break;
            }
        }
        i++;
    }
    if (p[i] == '\0' && st.empty())
    {
        cout << "匹配成功了...." << endl;
    }
    else
    {
        cout << "匹配失败!!!" << endl;
    }
}

void main()
{
    // 
    Jiujinpipei("#include <stdio.h> int main()  int a[4][4]; int (*p)[4]; p = a[0]; return 0;}");
    system("pause");
}
案例2:中缀表达式和后缀表达式

l 后缀表达式(由波兰科学家在20世纪50年代提出)

  n 将运算符放在数字后面 ===》 符合计算机运算

  n 我们习惯的数学表达式叫做中缀表达式===》符合人类思考习惯

l 实例

  n 5 + 4 => 5 4 +  

   n 1 + 2 * 3 => 1 2 3 * +  

  n 8 + ( 3 – 1 ) * 5 => 8 3 1 – 5 * +

l 中缀转后缀算法:

  遍历中缀表达式中的数字和符号:

  n 对于数字:直接输出

  n 对于符号:

    u 左括号:进栈  

    u 运算符号:与栈顶符号进行优先级比较

    •   若栈顶符号优先级低:此符号进栈  

        (默认栈顶若是左括号,左括号优先级最低)

    •   若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈

    l 右括号:将栈顶符号弹出并输出,直到匹配左括号

遍历结束:将栈中的所有符号弹出并输出

中缀转后缀伪代码 priority

transform(exp)
{
    创建栈S;
    i= 0while(exp[i] != ‘\0’)
{
        if(exp[i] 为数字)
        {
            Output(exp[i]);
        }
        else if(exp[i] 为符号)
        {
            while(exp[i]优先级 <= 栈顶符号优先级)
            {
                output(栈顶符号);
                Pop(S);
            }
            Push(S, exp[i]);
        }
        else if(exp[i] 为左括号)
        {
            Push(S, exp[i]);
        }
        else if(exp[i] 为右括号)
        {
            while(栈顶符号不为左括号)
            {
                output(栈顶符号);
                Pop(S);
            }
            从S中弹出左括号;
        }
        else
        {
            报错,停止循环;
        }
        i++;
}
while(size(S) > 0 && exp[i] == ‘\0’)
{
        output(栈顶符号);
        Pop(S);
}
}
View Code

l 动手练习

将我们喜欢的读的中缀表达式转换成计算机喜欢的后缀表达式

  中缀表达式: 8 + ( 3 – 1 ) * 5

  后缀表达式:  8 3 1 – 5 * +

中缀后缀表达式.cpp

#include <iostream>
#include <stack>
using namespace std;

bool isNumber(char c)
{
    return c >= '0' && c <= '9';
}

bool isLeft(char c)
{
    return c == '(';
}

bool isRight(char c)
{
    return c == ')';
}


bool isOperator(char c)
{
    return c == '+' || c == '-' || c == '*' || c == '/';
}

int priority(char c)
{
    int ret = 0;
    switch (c)
    {
    case '+':
    case '-':
        ret = 1;
        break;
    case '*':
    case '/':
        ret = 2;
        break;
    default:
        break;
    }
    return ret;
}

void Transform(const char* p)
{
    int i = 0;
    stack<char> st;
    while (p[i] != '\0')
    {
        // 数字
        if (isNumber(p[i]))
        {
            // 直接输出
            cout << p[i];
        }
        // 左括号
        else if (isLeft(p[i]))
        {
            // 进栈
            st.push(p[i]);
        }
        // 运算符
        else if (isOperator(p[i]))
        {
            // 优先级的比较 
            while (!st.empty() && priority(st.top()) >= priority(p[i]))
            {
                // 输出
                cout << st.top();
                st.pop();
            }
            // 进栈
            st.push(p[i]);
        }
        // 右括号
        else if (isRight(p[i]))
        {
            // 如果不是左括号, 弹出并输出
            while (!isLeft(st.top()))
            {
                cout << st.top();
                st.pop();
            }
            // 弹出左括号
            st.pop();
        }
        i++;
    }

    while (!st.empty())
    {
        cout << st.top();
        st.pop();
    }
}

void main()
{
    Transform("8+(3-1)*5");
    system("pause");
}
案例3 计算机如何基于后缀表达式计算

思考

  计算机是如何基于后缀表达式计算的?

  例如:8 3 1 – 5 * +

l 计算规则 

  遍历后缀表达式中的数字和符号

    n 对于数字:进栈

    n 对于符号:

      u 从栈中弹出右操作数

      u 从栈中弹出左操作数

      u 根据符号进行运算

      u 将运算结果压入栈中 

  遍历结束:栈中的唯一数字为计算结果

l 代码实现(伪代码) express

compute(exp)
{
    创建栈;
    int i = 0;
    while( exp[i] != ‘\0’)
    {
        if(exp[i]为数字)
        {
            Push(S, exp[i]);
        }
        else if(exp[i]为符号)
        {
1. 从栈顶弹出右操作数;
2. 从栈中弹出左操作数;
3. 根据符号进行运算;
4. Push(stack, 结果);
        }
        else
        {
            报错,停止循环;
        }
        i++;
    }
    if( Size(s) == 1 && exp[i] == ‘\0’)
    {
        栈中唯一的数字为运算结果;
    }
    返回结果;
}
View Code

demo03_后缀计算.c

#include <stdio.h>
#include "LinkStack.h"

int isNumber3(char c)
{
    return ('0' <= c) && (c <= '9');
}

int isOperator3(char c)
{
    return (c == '+') || (c == '-') || (c == '*') || (c == '/');
}

int value(char c)
{
    return (c - '0');
}

int express(int left, int right, char op)
{
    int ret = 0;

    switch(op)
    {
    case '+':
        ret = left + right;
        break;
    case '-':
        ret = left - right;
        break;
    case '*':
        ret = left * right;
        break;
    case '/':
        ret = left / right;
        break;
    default:
        break;
    }

    return ret;
}

int compute(const char* exp)
{
    LinkStack* stack = LinkStack_Create();
    int ret = 0;
    int i = 0;

    while( exp[i] != '\0' )
    {
        if( isNumber3(exp[i]) )
        {
            LinkStack_Push(stack, (void*)value(exp[i]));
        }
        else if( isOperator3(exp[i]) )
        {
            int right = (int)LinkStack_Pop(stack);
            int left = (int)LinkStack_Pop(stack);
            int result = express(left, right, exp[i]);

            LinkStack_Push(stack, (void*)result);
        }
        else
        {
            printf("Invalid expression!");
            break;
        }

        i++;
    }

    if( (LinkStack_Size(stack) == 1) && (exp[i] == '\0') )
    {
        ret = (int)LinkStack_Pop(stack);
    } 
    else 
    {
        printf("Invalid expression!");
    }

    LinkStack_Destroy(stack);

    return ret;
}

int main()
{
    printf("8 + (3 - 1) * 5  = %d\n", compute("831-5*+"));
    system("pause");
    return 0;
}

综合成一个项目:

linklist.h

 1 #ifndef _MYLINKLIST_H_
 2 #define _MYLINKLIST_H_
 3 
 4 typedef void LinkList;
 5 /*
 6 typedef struct _tag_LinkListNode LinkListNode;
 7 struct _tag_LinkListNode
 8 {
 9     LinkListNode* next;
10 };
11 */
12 typedef struct _tag_LinkListNode
13 {
14     struct _tag_LinkListNode* next;
15 }LinkListNode;
16 
17 LinkList* LinkList_Create();
18 
19 void LinkList_Destroy(LinkList* list);
20 
21 void LinkList_Clear(LinkList* list);
22 
23 int LinkList_Length(LinkList* list);
24 
25 int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
26 
27 LinkListNode* LinkList_Get(LinkList* list, int pos);
28 
29 LinkListNode* LinkList_Delete(LinkList* list, int pos);
30 
31 #endif
View Code

linkstack.h

 1 #ifndef _MY_LINKSTACK_H_
 2 #define _MY_LINKSTACK_H_
 3 
 4 typedef void LinkStack;
 5 
 6 LinkStack* LinkStack_Create();
 7 
 8 void LinkStack_Destroy(LinkStack* stack);
 9 
10 void LinkStack_Clear(LinkStack* stack);
11 
12 int LinkStack_Push(LinkStack* stack, void* item);
13 
14 void* LinkStack_Pop(LinkStack* stack);
15 
16 void* LinkStack_Top(LinkStack* stack);
17 
18 int LinkStack_Size(LinkStack* stack);
19 
20 #endif //_MY_LINKSTACK_H_
View Code

linkstack.c

 1 #include "stdlib.h"
 2 #include "stdio.h"
 3 #include "string.h"
 4 #include "linkstack.h"
 5 #include "linklist.h"
 6 
 7 typedef struct _tag_LinkStackNode
 8 {
 9     LinkListNode node; //占位结构。。。只要定义一个和node节大小一样的数据即可
10     void *item;
11 }TLinkStackNode;
12 
13 //我要创建一个linkstack,准备用linklist去模拟实现
14 //相当于在 linkstack.c中写 linklist库的测试程序。。。。。。
15 LinkStack* LinkStack_Create()
16 {
17     //创建一个栈,通过线性表去模拟。。。(创建一个栈,相当于创建一个线性表)
18     return LinkList_Create();
19 }
20 
21 void LinkStack_Destroy(LinkStack* stack)
22 {
23     LinkStack_Clear(stack); //注意 destory的时候,需要把栈中的所有元素都清空
24     LinkList_Destroy(stack);
25 }
26 
27 void LinkStack_Clear(LinkStack* stack)
28 {
29     //LinkList_Clear(stack);
30     while (LinkStack_Size(stack) > 0)
31     {
32         LinkStack_Pop(stack); //在这个函数里面有内存释放函数
33     }
34     return ;
35 }
36 
37 //向栈中放元素,相当于 向线性表中插入一个元素
38 int LinkStack_Push(LinkStack* stack, void* item)
39 {
40     int ret = 0;
41     //需要item数据,转换成 linklist的业务节点
42     TLinkStackNode *pTe = (TLinkStackNode *)malloc(sizeof(TLinkStackNode));
43     if (pTe == NULL)
44     {
45         return -1;
46     }
47     pTe->item = item;
48 
49     //头插法 ,向线性表中插入元素,只不过是插入元素的时候,需要构造业务节点而已。。。。。。
50     ret = LinkList_Insert(stack, (LinkListNode *)(&pTe->node),0 );
51     if (ret != 0)
52     {
53         free(pTe);
54     }
55     return ret;
56 }
57 
58 void* LinkStack_Pop(LinkStack* stack)
59 {
60     void *myItem = NULL;
61     TLinkStackNode *pTmp = NULL;
62     pTmp = (TLinkStackNode *)LinkList_Delete(stack, 0);
63     if (pTmp == NULL)
64     {
65         return NULL;
66     }
67     myItem = pTmp->item;
68 
69     //注意向线性表中,插入元素的时,打造节点,分配内存;
70     //弹出元素时,需要释放节点内存,不要忘记
71 
72     if (pTmp != NULL)  
73     {
74         free(pTmp);
75     }
76     return myItem;
77 }
78 
79 void* LinkStack_Top(LinkStack* stack)
80 {
81     void *myItem = NULL;
82     TLinkStackNode *pTmp = NULL;
83     pTmp = (TLinkStackNode *)LinkList_Get(stack, 0);
84     if (pTmp == NULL)
85     {
86         return NULL;
87     }
88     myItem = pTmp->item;
89     return myItem;
90 }
91 
92 int LinkStack_Size(LinkStack* stack)
93 {
94     return LinkList_Length(stack);
95 }
View Code

栈的应用后缀表达式.c

  1 #include "stdio.h"
  2 #include "stdlib.h"
  3 #include "linkstack.h"
  4 
  5 int isLeft(char c)
  6 {
  7     int ret = 0;
  8 
  9     switch(c)
 10     {
 11     case '<':
 12     case '(':
 13     case '[':
 14     case '{':
 15     case '\'':
 16     case '\"':
 17         ret = 1;
 18         break;
 19     default:
 20         ret = 0;
 21         break;
 22     }
 23 
 24     return ret;
 25 }
 26 
 27 int isRight(char c)
 28 {
 29     int ret = 0;
 30 
 31     switch(c)
 32     {
 33     case '>':
 34     case ')':
 35     case ']':
 36     case '}':
 37     case '\'':
 38     case '\"':
 39         ret = 1;
 40         break;
 41     default:
 42         ret = 0;
 43         break;
 44     }
 45 
 46     return ret;
 47 }
 48 
 49 int match(char left, char right)
 50 {
 51     int ret = 0;
 52 
 53     switch(left)
 54     {
 55     case '<':
 56         ret = (right == '>');
 57         break;
 58     case '(':
 59         ret = (right == ')');
 60         break;
 61     case '[':
 62         ret = (right == ']');
 63         break;
 64     case '{':
 65         ret = (right == '}');
 66         break;
 67     case '\'':
 68         ret = (right == '\'');
 69         break;
 70     case '\"':
 71         ret = (right == '\"');
 72         break;
 73     default:
 74         ret = 0;
 75         break;
 76     }
 77 
 78     return ret;
 79 }
 80 //就近匹配原理
 81 int scanner(const char* code)
 82 {
 83     LinkStack* stack = LinkStack_Create();
 84     int ret = 0;
 85     int i = 0;
 86 
 87     while( code[i] != '\0' )
 88     {
 89         if( isLeft(code[i]) )
 90         {
 91             LinkStack_Push(stack, (void*)(code + i)); //&code[i]
 92         }
 93 
 94         if( isRight(code[i]) )
 95         {
 96             char* c = (char*)LinkStack_Pop(stack);
 97 
 98             if( (c == NULL) || !match(*c, code[i]) )
 99             {
100                 printf("%c does not match!\n", code[i]);
101                 ret = 0;
102                 break;
103             }
104         }
105 
106         i++;
107     }
108 
109     if( (LinkStack_Size(stack) == 0) && (code[i] == '\0') )
110     {
111         printf("Succeed!\n");
112         ret = 1;
113     }
114     else
115     {
116         printf("Invalid code!\n");
117         ret = 0;
118     }
119 
120     LinkStack_Destroy(stack);
121 
122     return ret;
123 }
124 
125 void main()
126 {
127     const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0; ";
128 
129     scanner(code);
130     system("pause");
131     return ;
132 }
View Code

demo02_中缀转后缀.c

  1 #include "stdio.h"
  2 #include "stdlib.h"
  3 #include "string.h"
  4 #include "linkstack.h"
  5 
  6 int isNumber(char c)
  7 {
  8     return ('0' <= c) && (c <= '9');
  9 }
 10 
 11 int isOperator(char c)
 12 {
 13     return (c == '+') || (c == '-') || (c == '*') || (c == '/');
 14 }
 15 
 16 int isLeft(char c)
 17 {
 18     return (c == '(');
 19 }
 20 
 21 int isRight(char c)
 22 {
 23     return (c == ')');
 24 }
 25 
 26 int priority(char c)
 27 {
 28     int ret = 0;
 29 
 30     if( (c == '+') || (c == '-') )
 31     {
 32         ret = 1;
 33     }
 34 
 35     if( (c == '*') || (c == '/') )
 36     {
 37         ret = 2;
 38     }
 39 
 40     return ret;
 41 }
 42 
 43 void output(char c)
 44 {
 45     if( c != '\0' )
 46     {
 47         printf("%c", c);
 48     }
 49 }
 50 
 51 void transform(const char* exp)
 52 {
 53     int i = 0;
 54     LinkStack* stack = LinkStack_Create();
 55 
 56     while( exp[i] != '\0' )
 57     {
 58         if( isNumber(exp[i]) )
 59         {
 60             output(exp[i]);
 61         }
 62         else if( isOperator(exp[i]) )
 63         {
 64             while( priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)) )
 65             {
 66                 output((char)(int)LinkStack_Pop(stack));
 67             }
 68 
 69             LinkStack_Push(stack, (void*)(int)exp[i]);
 70         } 
 71         else if( isLeft(exp[i]) )
 72         {
 73             LinkStack_Push(stack, (void*)(int)exp[i]);
 74         } 
 75         else if( isRight(exp[i]) )
 76         {
 77             //char c = '\0';
 78             while( !isLeft((char)(int)LinkStack_Top(stack)) )
 79             {
 80                 output((char)(int)LinkStack_Pop(stack));
 81             }
 82 
 83             LinkStack_Pop(stack);
 84         }
 85         else
 86         {
 87             printf("Invalid expression!");
 88             break;
 89         }
 90 
 91         i++;
 92     }
 93 
 94     while( (LinkStack_Size(stack) > 0) && (exp[i] == '\0') )
 95     {
 96         output((char)(int)LinkStack_Pop(stack));
 97     }
 98 
 99     LinkStack_Destroy(stack);
100 }
101 
102 int main()
103 {
104     transform("8+(3-1)*5");
105 
106     printf("\n");
107     system("pause");
108     return 0;
109 }
View Code

demo03_后缀计算.c

 1 #include <stdio.h>
 2 #include "LinkStack.h"
 3 
 4 int isNumber3(char c)
 5 {
 6     return ('0' <= c) && (c <= '9');
 7 }
 8 
 9 int isOperator3(char c)
10 {
11     return (c == '+') || (c == '-') || (c == '*') || (c == '/');
12 }
13 
14 int value(char c)
15 {
16     return (c - '0');
17 }
18 
19 int express(int left, int right, char op)
20 {
21     int ret = 0;
22 
23     switch(op)
24     {
25     case '+':
26         ret = left + right;
27         break;
28     case '-':
29         ret = left - right;
30         break;
31     case '*':
32         ret = left * right;
33         break;
34     case '/':
35         ret = left / right;
36         break;
37     default:
38         break;
39     }
40 
41     return ret;
42 }
43 
44 int compute(const char* exp)
45 {
46     LinkStack* stack = LinkStack_Create();
47     int ret = 0;
48     int i = 0;
49 
50     while( exp[i] != '\0' )
51     {
52         if( isNumber3(exp[i]) )
53         {
54             LinkStack_Push(stack, (void*)value(exp[i]));
55         }
56         else if( isOperator3(exp[i]) )
57         {
58             int right = (int)LinkStack_Pop(stack);
59             int left = (int)LinkStack_Pop(stack);
60             int result = express(left, right, exp[i]);
61 
62             LinkStack_Push(stack, (void*)result);
63         }
64         else
65         {
66             printf("Invalid expression!");
67             break;
68         }
69 
70         i++;
71     }
72 
73     if( (LinkStack_Size(stack) == 1) && (exp[i] == '\0') )
74     {
75         ret = (int)LinkStack_Pop(stack);
76     } 
77     else 
78     {
79         printf("Invalid expression!");
80     }
81 
82     LinkStack_Destroy(stack);
83 
84     return ret;
85 }
86 
87 int main()
88 {
89     printf("8 + (3 - 1) * 5  = %d\n", compute("831-5*+"));
90     system("pause");
91     return 0;
92 }
View Code

案例4:栈的应用之进制转换

资料来自互联网

以后带补充,如果有雷同,纯属巧合。。如果认为不错,请关注一下。

 

转载于:https://www.cnblogs.com/wanghui1234/p/8873543.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值