【本文谢绝转载原文来自http://990487026.blog.51cto.com】
数据结构与算法 2:双向链表,栈,队列 双向链表 双向链表API 双向链表的正常的插入操作 双向链表的正常删除操作 双向链表的优缺点 栈 栈的顺序储存,选型[图] 栈的链式储存,选型[图] 栈的顺序储存设计与实现 栈的链式储存设计与实现 栈的典型应用1:就近匹配,语法检查器 栈的典型应用2:中缀转后缀 队列 队列顺序存储API 队列链式存储API
重点:
循环链表:
特殊处理:在头结点插入数据,必须遍历到尾节点
特殊处理:删除头结点数据,必须遍历到尾节点
双向链表:
引入三个辅助指针变量
特殊处理,空数据,在头结点插入数据相当于尾节点插入数据
双向链表API:
1,dlinklist.h
chunli@http://990487026.blog.51cto.com~/double_list$ cat dlinklist.h #ifndef _MY_DLINKLIST_H_ #define _MY_DLINKLIST_H_ typedef void DLinkList; /* typedef struct _tag_DLinkListNode DLinkListNode; struct _tag_DLinkListNode { DLinkListNode* next; DLinkListNode* pre; }; */ typedef struct _tag_DLinkListNode { struct _tag_DLinkListNode* next; struct _tag_DLinkListNode * pre; }DLinkListNode; DLinkList* DLinkList_Create(); void DLinkList_Destroy(DLinkList* list); void DLinkList_Clear(DLinkList* list); int DLinkList_Length(DLinkList* list); int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos); DLinkListNode* DLinkList_Get(DLinkList* list, int pos); DLinkListNode* DLinkList_Delete(DLinkList* list, int pos); //-- add DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node); DLinkListNode* DLinkList_Reset(DLinkList* list); DLinkListNode* DLinkList_Current(DLinkList* list); DLinkListNode* DLinkList_Next(DLinkList* list); DLinkListNode* DLinkList_Pre(DLinkList* list); #endif chunli@http://990487026.blog.51cto.com~/double_list$
2,dlinklist.c
chunli@http://990487026.blog.51cto.com~/double_list$ cat dlinklist.c #include <stdio.h> #include <malloc.h> #include "dlinklist.h" typedef struct _tag_DLinkList { DLinkListNode header; DLinkListNode* slider; int length; } TDLinkList; DLinkList* DLinkList_Create() { TDLinkList* ret = (TDLinkList*)malloc(sizeof(TDLinkList)); if( ret != NULL ) { ret->length = 0; ret->header.next = NULL; ret->header.pre = NULL; ret->slider = NULL; } return ret; } void DLinkList_Destroy(DLinkList* list) { if (list != NULL) { free(list); } } void DLinkList_Clear(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; if( sList != NULL ) { sList->length = 0; sList->header.next = NULL; sList->header.pre = NULL; sList->slider = NULL; } } int DLinkList_Length(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; int ret = -1; if( sList != NULL ) { ret = sList->length; } return ret; } //大家一定要注意:教科书不会告诉你 项目上如何用;哪些点是项目的重点 int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos) { int ret = 0, i = 0; TDLinkList* sList = (TDLinkList*)list; if (list==NULL || node==NULL || pos<0) { return -1; } { DLinkListNode* current = (DLinkListNode*)sList; DLinkListNode* next = NULL; //需要增加next指针 for(i=0; (i<pos) && (current->next != NULL); i++) { current = current->next; } next = current->next; //步骤1-2 current->next = node; node->next = next; //步骤3-4 if( next != NULL ) //当链表插入第一个元素,需要特殊处理 { next->pre = node; } node->pre = current; if( sList->length == 0 ) { sList->slider = node; //当链表插入第一个元素处理游标 } //若在0位置插入,需要特殊处理 新来结点next前pre指向null if( current == (DLinkListNode*)sList ) { node->pre = NULL; } sList->length++; } return ret; } DLinkListNode* DLinkList_Get(DLinkList* list, int pos) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; int i = 0; if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) { DLinkListNode* current = (DLinkListNode*)sList; for(i=0; i<pos; i++) { current = current->next; } ret = current->next; } return ret; } //插入第一个节点 //删除的是最后一个结点,该是如何处理 DLinkListNode* DLinkList_Delete(DLinkList* list, int pos) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; int i = 0; if (sList == NULL || pos <0 ) { return NULL; } //if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) { DLinkListNode* current = (DLinkListNode*)sList; DLinkListNode* next = NULL; //需要增加next指针 for(i=0; i<pos; i++) { current = current->next; } ret = current->next; next = ret->next; //步骤1 current->next = next; //步骤2 if( next != NULL )//需要特殊处理 { next->pre = current; if( current == (DLinkListNode*)sList ) //若第0个位置,需要特殊处理 { next->pre = NULL; } } if( sList->slider == ret ) { sList->slider = next; } sList->length--; } return ret; } DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; int i = 0; if( sList != NULL ) { DLinkListNode* current = (DLinkListNode*)sList; for(i=0; i<sList->length; i++) { if( current->next == node ) { ret = current->next; break; } current = current->next; } if( ret != NULL ) { DLinkList_Delete(sList, i); } } return ret; } DLinkListNode* DLinkList_Reset(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; if( sList != NULL ) { sList->slider = sList->header.next; ret = sList->slider; } return ret; } DLinkListNode* DLinkList_Current(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; if( sList != NULL ) { ret = sList->slider; } return ret; } DLinkListNode* DLinkList_Next(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; if( (sList != NULL) && (sList->slider != NULL) ) { ret = sList->slider; sList->slider = ret->next; } return ret; } DLinkListNode* DLinkList_Pre(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; if( (sList != NULL) && (sList->slider != NULL) ) { ret = sList->slider; sList->slider = ret->pre; } return ret; } chunli@http://990487026.blog.51cto.com~/double_list$
3,测试程序 mia.c
chunli@http://990487026.blog.51cto.com~/double_list$ cat main.c #include <stdio.h> #include <stdlib.h> #include "dlinklist.h" struct Value { DLinkListNode node; int v; }; int main(int argc, char *argv[]) { int i = 0; DLinkList* list = DLinkList_Create();//创建双向链表 struct Value* pv = NULL; struct Value v1, v2, v3, v4, v5; v1.v = 1; v2.v = 2; v3.v = 3; v4.v = 4; v5.v = 5; DLinkList_Insert(list, (DLinkListNode*)&v1, DLinkList_Length(list));//尾插法 DLinkList_Insert(list, (DLinkListNode*)&v2, DLinkList_Length(list));//尾插法 DLinkList_Insert(list, (DLinkListNode*)&v3, DLinkList_Length(list));//尾插法 DLinkList_Insert(list, (DLinkListNode*)&v4, DLinkList_Length(list));//尾插法 DLinkList_Insert(list, (DLinkListNode*)&v5, DLinkList_Length(list));//尾插法 for(i=0; i<DLinkList_Length(list); i++) //遍历链表 { pv = (struct Value*)DLinkList_Get(list, i); printf("遍历链表: %3d\n", pv->v); } printf("\n"); DLinkList_Delete(list, DLinkList_Length(list)-1);//删除尾节点 DLinkList_Delete(list, 0); //删除头头结点 //DLinkList_Delete(list, 3); for(i=0; i<DLinkList_Length(list); i++) { pv = (struct Value*)DLinkList_Next(list); printf("删除尾节点,头结点后 %3d\n", pv->v); } printf("\n"); DLinkList_Reset(list); //重置游标,头结点已经删除了,此时头结点就是值为2那个 DLinkList_Next(list); //游标下移,指向3了 pv = (struct Value*)DLinkList_Current(list);//显示当前游标指向的位置 printf("%d\n", pv->v); DLinkList_DeleteNode(list, (DLinkListNode*)pv);//删除3,游标会下移 pv = (struct Value*)DLinkList_Current(list); printf("%d\n", pv->v);//获取游标指向的元素,指向4 DLinkList_Pre(list); //游标往前跑 pv = (struct Value*)DLinkList_Current(list); printf("%d\n", pv->v); //获取游标指向的元素,指向2 printf("此时链表长度,Length: %3d\n", DLinkList_Length(list)); DLinkList_Destroy(list); return 0; } chunli@http://990487026.blog.51cto.com~/double_list$ 编译运行: chunli@http://990487026.blog.51cto.com~/double_list$ gcc main.c dlinklist.c -Wall && ./a.out 遍历链表: 1 遍历链表: 2 遍历链表: 3 遍历链表: 4 遍历链表: 5 删除尾节点,头结点后 2 删除尾节点,头结点后 3 删除尾节点,头结点后 4 3 4 2 此时链表长度,Length: 2 chunli@http://990487026.blog.51cto.com~/double_list$
双向链表的正常的插入操作
双向链表的正常删除操作
双向链表的优缺点
优点:双向链表在单链表的基础上增加了指向前驱的指针
功能上双向链表可以完全取代单链表的使用
循环链表的Next,Pre和Current操作可以高效的遍历链表中的所有元素
缺点:代码复杂
栈
栈的顺序储存,选型[图]
栈的链式储存,选型[图]
1,栈的顺序储存设计与实现
项目列表:
chunli@http://990487026.blog.51cto.com~/seq_stack$ tree . ├── main.c ├── seqlist.c ├── seqlist.h ├── seqstack.c └── seqstack.h 0 directories, 5 files
main测试程序文件
chunli@http://990487026.blog.51cto.com~/seq_stack$ cat main.c #include <stdio.h> #include "seqstack.h" int main() { int my_data[10] = {0,1,2,3,4,5,6,7,8,9};//我的数据 int i = 0; //临时变量 for,while专用变量 SeqStack *stack = SeqStack_Create(10);//创建顺序表的大小 if(stack == NULL) { return -1; } for(i = 0;i<10;i++) //数据压栈 { SeqStack_Push(stack,&my_data[i]);//把变量的地址压栈 } printf("栈的容量大小为:%3d\n",SeqStack_Capacity(stack));//求栈容量的大小 printf("栈的实际长度为:%3d\n",SeqStack_Size(stack));//求栈的实际长度 printf("栈顶元素为:%3d\n",*(int*)SeqStack_Top(stack));//求栈的实际长度 while(SeqStack_Size(stack) > 0) //当栈实际长度大于0,就开始删除栈内元素 { printf("被弹出的元素 %d\n",*(int*)SeqStack_Top(stack)); SeqStack_Pop(stack); //弹出栈内元素 } printf("\n"); printf("栈的容量大小为:%3d\n",SeqStack_Capacity(stack));//求栈容量的大小 printf("栈的实际长度为:%3d\n",SeqStack_Size(stack));//求栈的实际长度 printf("栈顶元素为:%p\n",SeqStack_Top(stack));//求栈的实际长度 return 0; } chunli@http://990487026.blog.51cto.com~/seq_stack$
线性表函数实现文件,seqlist.c
chunli@http://990487026.blog.51cto.com~/seq_stack$ cat seqlist.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "seqlist.h" //申明一个结构体类型,用来存储线性表自己的信息 typedef struct _tag_SeqList { int length; //线性表的实际利用长度 int capacity; //线性表一共有多长 size_t *node; }TSeqList; //创建线性表 SeqList* SeqList_Create(int capacity)//相当于分配数组的大小 { TSeqList * tmp = NULL; //创建线性表的头,放在堆内存中 tmp = (TSeqList*)malloc(sizeof(TSeqList)); if(tmp == NULL) { printf("ERROR in (TSeqList*)malloc(sizeof(TSeqList)) \n"); return NULL; } //做个细心的人 memset(tmp,0,sizeof(TSeqList)); //根据capacity的大小,创建线性表的长度 tmp->node = (size_t *)malloc(sizeof(size_t*) *capacity ); if(tmp->node == NULL) { printf("ERROR in (unsigned int *)malloc(sizeof(unsigned int *) * capacity ) \n"); return NULL; } tmp->length = 0; tmp->capacity = capacity; return tmp; } //销毁链表 void SeqList_Destroy(SeqList* list) { TSeqList *tlist = NULL; if(list == NULL) { printf("list == NULL \n"); return; } tlist = (TSeqList *)list; if(tlist ->node != NULL) { free(tlist->node);//释放存储内存区 } free(tlist); //释放线性表头 return ; } //清空链表的长度 void SeqList_Clear(SeqList* list) { TSeqList *tlist = NULL; if(list == NULL) { printf("list == NULL \n"); return; } tlist = (TSeqList *)list; tlist->length = 0; return ; } //返回线性表的长度 int SeqList_Length(SeqList* list) { TSeqList *tlist = NULL; if(list == NULL) { printf("list == NULL \n"); return -1; } tlist = (TSeqList *)list; return tlist->length; } //返回线性表的容量 int SeqList_Capacity(SeqList* list) { TSeqList *tlist = NULL; if(list == NULL) { printf("list == NULL \n"); return -1; } tlist = (TSeqList *)list; return tlist->capacity; } //节点的插入 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) { if(list == NULL || node == NULL || pos <0) { printf("list == NULL || node == NULL \n"); return -1; } TSeqList *tlist = NULL; tlist = (TSeqList *)list; //判断容量是不是 满了 if(tlist->length >= tlist->capacity) { printf("插入失败,线性表已经装满了\n"); } //容错修正 20个容量,已经用到6,要求在10插入 if(pos >= tlist->length ) { pos = tlist->length; } int i = 0; for(i = tlist->length;i > pos;i--) { tlist->node[i] = tlist->node[i-1]; } tlist->length ++; tlist->node[pos] = *(size_t *)node; return 0; } SeqListNode* SeqList_Get(SeqList* list, int pos) { if(list == NULL || pos <0) { printf("检测到线性表为空,返回NULL \n"); return NULL; } TSeqList *tlist = NULL; tlist = (TSeqList *)list; return &tlist->node[pos]; } SeqListNode* SeqList_Delete(SeqList* list, int pos) { if(list == NULL || pos <0) { printf("线性表为空 \n"); return NULL; } TSeqList *tlist = NULL; tlist = (TSeqList *)list; int i = 0; for(i = pos+1;i<tlist->length;i++) { tlist->node[i-1] = tlist->node[i]; } tlist->length --; return NULL; } chunli@http://990487026.blog.51cto.com~/seq_stack$
线性表函数声明文件,seqlist.h
chunli@http://990487026.blog.51cto.com~/seq_stack$ cat seqlist.h #ifndef __MY_SEQLIST_H__ #define __MY_SEQLIST_H__ typedef void SeqList; typedef void SeqListNode; SeqList* SeqList_Create(int capacity); void SeqList_Destroy(SeqList* list); void SeqList_Clear(SeqList* list); int SeqList_Length(SeqList* list); int SeqList_Capacity(SeqList* list); int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); SeqListNode* SeqList_Get(SeqList* list, int pos); SeqListNode* SeqList_Delete(SeqList* list, int pos); #endif //__MY_SEQLIST_H__ chunli@http://990487026.blog.51cto.com~/seq_stack$
栈函数实现文件seqstack.c
chunli@http://990487026.blog.51cto.com~/seq_stack$ cat seqstack.c #include <stdio.h> #include "seqstack.h" #include "seqlist.h" SeqStack* SeqStack_Create(int capacity) //创建一个顺序栈 { return SeqList_Create(capacity);//创建一个线程表 } void SeqStack_Destroy(SeqStack* stack)//销毁顺序栈 { SeqList_Destroy(stack) ;//销毁线性表 } void SeqStack_Clear(SeqStack* stack)//清空顺序栈 { SeqList_Clear(stack) ;//清空线性表 } int SeqStack_Push(SeqStack* stack, void* item)//往栈中压入数据,相当于在尾部插入元素 { return SeqList_Insert(stack,item,SeqList_Length(stack)); } void* SeqStack_Pop(SeqStack* stack) //从栈中弹出元素,相当于从链表的尾部删除元素 { return SeqList_Delete(stack,SeqList_Length(stack)-1); } void* SeqStack_Top(SeqStack* stack)//获取栈顶元素,相当于获取线性表的尾部元素 { return SeqList_Get(stack,SeqList_Length(stack)-1); } int SeqStack_Size(SeqStack* stack)//获取栈的大小,相当于获取线性表的实际长度 { return SeqList_Length(stack); } int SeqStack_Capacity(SeqStack* stack)//获取栈的容量,相当于获取线性表顺序存储的容量 { return SeqList_Capacity(stack) ; } chunli@http://990487026.blog.51cto.com~/seq_stack$
栈函数声明文件seqstack.h
chunli@http://990487026.blog.51cto.com~/seq_stack$ cat seqstack.h // seqstack.h #ifndef _MY_SEQSTACK_H_ #define _MY_SEQSTACK_H_ typedef void SeqStack; SeqStack* SeqStack_Create(int capacity); void SeqStack_Destroy(SeqStack* stack); void SeqStack_Clear(SeqStack* stack); int SeqStack_Push(SeqStack* stack, void* item); void* SeqStack_Pop(SeqStack* stack); void* SeqStack_Top(SeqStack* stack); int SeqStack_Size(SeqStack* stack); int SeqStack_Capacity(SeqStack* stack); #endif //_MY_SEQSTACK_H_ chunli@http://990487026.blog.51cto.com~/seq_stack$
编译运行:
chunli@http://990487026.blog.51cto.com~/seq_stack$ gcc main.c seqstack.c seqlist.c -Wall -g && ./a.out 栈的容量大小为: 10 栈的实际长度为: 10 栈顶元素为: 9 被弹出的元素 9 被弹出的元素 8 被弹出的元素 7 被弹出的元素 6 被弹出的元素 5 被弹出的元素 4 被弹出的元素 3 被弹出的元素 2 被弹出的元素 1 被弹出的元素 0 栈的容量大小为: 10 栈的实际长度为: 0 检测到线性表为空,返回NULL 栈顶元素为:(nil) chunli@http://990487026.blog.51cto.com~/seq_stack$
2,栈的链式储存设计与实现,[难度大]
项目文件:
chunli@http://990487026.blog.51cto.com~/link_stack$ tree . ├── linklist.c ├── linklist.h ├── linkstack.c ├── linkstack.h └── main.c 0 directories, 5 files
linklist.c链表函数实现文件
chunli@http://990487026.blog.51cto.com~/link_stack$ cat linklist.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "linklist.h" typedef struct _tag_LinkList { //这个句柄里面,需要保存所有节点信息。需要有一个起始点 //就是带头节点的链表。。。 LinkListNode header; int length; }TLinkList; LinkList* LinkList_Create() { TLinkList *ret = (TLinkList *)malloc(sizeof(TLinkList)); if (ret == NULL) { return NULL; } //memset(ret, 0, sizeof(TLinkList)); ret->header.next = NULL; ret->length = 0; return ret; } void LinkList_Destroy(LinkList* list) { if (list == NULL) { return ; } free(list); return ; } void LinkList_Clear(LinkList* list) { TLinkList *tList =NULL; if (list == NULL) { return ; } tList = (TLinkList *)list; tList->length = 0; tList->header.next = NULL; return ; } int LinkList_Length(LinkList* list) { TLinkList *tList = (TLinkList *)list; if (tList == NULL) { return -1; } return tList->length; } int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) { int i = 0; TLinkList *tList = NULL; LinkListNode *current = NULL; tList = (TLinkList *)list; if (list==NULL || node==NULL) //modify by bombing 2014.06.26 { return -1; } //准备环境让辅助指针变量 指向链表头节点 current = &tList->header; for (i=0; i<pos &&(current->next!=NULL); i++) { current = current->next; } //让node节点链接后续链表 node->next = current->next ; //让前边的链表。链接node current->next = node; tList->length ++; return 0; } LinkListNode* LinkList_Get(LinkList* list, int pos) { int i = 0; TLinkList *tList = NULL; LinkListNode *current = NULL; LinkListNode *ret = NULL; tList = (TLinkList *)list; if (list == NULL || pos <0 ||pos>=tList->length) { return NULL; } //准备环境让辅助指针变量 指向链表头节点 current = &tList->header; for (i=0; i<pos &&(current->next!=NULL); i++) { current = current->next; } ret = current->next; return ret; } LinkListNode* LinkList_Delete(LinkList* list, int pos) { int i = 0; TLinkList *tList = NULL; LinkListNode *current = NULL; LinkListNode *ret = NULL; tList = (TLinkList *)list; if (list == NULL || pos <0 ||pos>=tList->length) { return NULL; } //准备环境让辅助指针变量 指向链表头节点 current = &tList->header; for (i=0; i<pos &&(current->next!=NULL); i++) { current = current->next; } ret = current->next; //删除算法 current->next =ret->next; tList->length--; return ret; } chunli@http://990487026.blog.51cto.com~/link_stack$
linklist.h链表函数声明文件
chunli@http://990487026.blog.51cto.com~/link_stack$ cat linklist.h #ifndef _MYLINKLIST_H_ #define _MYLINKLIST_H_ typedef void LinkList; /* typedef struct _tag_LinkListNode LinkListNode; struct _tag_LinkListNode { LinkListNode* next; }; */ typedef struct _tag_LinkListNode { struct _tag_LinkListNode* next; }LinkListNode; LinkList* LinkList_Create(); void LinkList_Destroy(LinkList* list); void LinkList_Clear(LinkList* list); int LinkList_Length(LinkList* list); int LinkList_Insert(LinkList* list, LinkListNode* node, int pos); LinkListNode* LinkList_Get(LinkList* list, int pos); LinkListNode* LinkList_Delete(LinkList* list, int pos); #endif chunli@http://990487026.blog.51cto.com~/link_stack$
linkstack.c栈函数声明文件
chunli@http://990487026.blog.51cto.com~/link_stack$ cat linkstack.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "linkstack.h" #include "linklist.h" typedef struct linkstack_node { LinkListNode node;//让万象包含链表 void *item; //栈的业务节点 }linkstack_node; LinkStack* LinkStack_Create()//创建一个栈,相当于创建一个线性表 { return LinkList_Create(); } void LinkStack_Destroy(LinkStack* stack)//销毁一个栈,相当于销毁一个线性表 { LinkStack_Clear(stack); LinkList_Destroy(stack); return ; } void LinkStack_Clear(LinkStack* stack)//清空一个栈,相当于清空一个线性表 { //清空栈的时候,涉及到元素生命周期管理 if(stack == NULL) { return; } while(LinkStack_Size(stack) > 0) { LinkStack_Pop(stack);//释放链表节点 } return ; } int LinkStack_Push(LinkStack* stack, void* item)//向线性表的头部插入元素 { linkstack_node *tmp = (linkstack_node*)malloc(sizeof(linkstack_node)); if(tmp == NULL) { return -1; } memset(tmp,0,sizeof(linkstack_node)); tmp->item = item; int ret = LinkList_Insert(stack,(LinkListNode*)tmp,0);//把数据转换成链表的业务节点 if(ret != 0) { printf("数据插入失败!\n"); if(tmp != NULL)//业务失败时,及时释放内存 { free(tmp); } return -2; } return 0; } void* LinkStack_Pop(LinkStack* stack)//相当于从线性表的头部弹出元素 { linkstack_node *tmp = NULL;//返回一个linkstack_node tmp = (linkstack_node *)LinkList_Delete(stack,0);//把链表节点转成业务节点 if(tmp == NULL) { return NULL; } void *item = tmp->item;//还原业务节点 free(tmp); //干掉链表节点 return item; } void* LinkStack_Top(LinkStack* stack)//获取栈顶元素 { linkstack_node *tmp = (linkstack_node *)LinkList_Get(stack,0); if(tmp == NULL) { return NULL; } return tmp->item; } int LinkStack_Size(LinkStack* stack)//求栈的大小,相当于求线性表的额length { return LinkList_Length(stack); } chunli@http://990487026.blog.51cto.com~/link_stack$
linkstack.h栈函数实现文件
chunli@http://990487026.blog.51cto.com~/link_stack$ cat linkstack.h #ifndef _MY_LINKSTACK_H_ #define _MY_LINKSTACK_H_ typedef void LinkStack; LinkStack* LinkStack_Create(); void LinkStack_Destroy(LinkStack* stack); void LinkStack_Clear(LinkStack* stack); int LinkStack_Push(LinkStack* stack, void* item); void* LinkStack_Pop(LinkStack* stack); void* LinkStack_Top(LinkStack* stack); int LinkStack_Size(LinkStack* stack); #endif //_MY_LINKSTACK_H_ chunli@http://990487026.blog.51cto.com~/link_stack$
main.c测试程序
chunli@http://990487026.blog.51cto.com~/link_stack$ cat main.c // gcc main.c linkstack.c linklist.c -Wall -g && ./a.out #include <stdio.h> #include <stdlib.h> #include <string.h> #include "linkstack.h" #define MAX 20 int main() { int i = 0; int ret = 0; int a[MAX] ={0}; LinkStack * stack = LinkStack_Create(); if(stack == NULL) { return -1; } printf("开始压栈 ... "); for(i = 0;i<MAX;i++)//数据压栈 { a[i] = i*i+i+1; ret = LinkStack_Push(stack,&a[i]); if(ret != 0) { printf("error LinkStack_Push %d\n",ret); } } printf("压栈完毕\n"); printf("栈的大小%d\n",LinkStack_Size(stack)); printf("栈顶元素%d\n",*(int *)LinkStack_Top(stack)); while(LinkStack_Size(stack) > 0) { printf("正在删除栈顶元素%d\n",*(int *)LinkStack_Top(stack)); LinkStack_Pop(stack); } LinkStack_Destroy(stack);//删除栈 return 0; } chunli@http://990487026.blog.51cto.com~/link_stack$
编译运行:
chunli@http://990487026.blog.51cto.com~/link_stack$ gcc main.c linkstack.c linklist.c -Wall -g && ./a.out 开始压栈 ... 压栈完毕 栈的大小20 栈顶元素381 正在删除栈顶元素381 正在删除栈顶元素343 正在删除栈顶元素307 正在删除栈顶元素273 正在删除栈顶元素241 正在删除栈顶元素211 正在删除栈顶元素183 正在删除栈顶元素157 正在删除栈顶元素133 正在删除栈顶元素111 正在删除栈顶元素91 正在删除栈顶元素73 正在删除栈顶元素57 正在删除栈顶元素43 正在删除栈顶元素31 正在删除栈顶元素21 正在删除栈顶元素13 正在删除栈顶元素7 正在删除栈顶元素3 正在删除栈顶元素1 chunli@http://990487026.blog.51cto.com~/link_stack$
3,栈的典型应用1:就近匹配,语法检查器
几乎所有的编译器都具有检测括号是否匹配的能力
如何实现编译器中的符号成对检测?
#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0;
算法思路
从第一个字符开始扫描
当遇见普通字符时忽略,当遇见左符号时压入栈中
当遇见右符号时从栈中弹出栈顶符号,并进行匹配
匹配成功:继续读入下一个字符
匹配失败:立即停止,并报错
结束:
成功: 所有字符扫描完毕,且栈为空
失败:匹配失败或所有字符扫描完毕但栈非空
当需要检测成对出现但又互不相邻的事物时
可以使用栈“后进先出”的特性
栈非常适合于需要“就近匹配”的场合
计算机的本质工作就是做数学运算,那计算机可以读入字符串
“9 + (3 - 1) * 5 + 8 / 2”并计算值吗?
项目文件:
chunli@http://990487026.blog.51cto.com~/link_stack$ tree . ├── linklist.c ├── linklist.h ├── linkstack.c ├── linkstack.h └── main.c 0 directories, 5 files
除了main.c文件与之前的文件不一样
linklist.c,linklist.h,linkstack.c,linkstack.h和上面的一样
main.c
chunli@http://990487026.blog.51cto.com~/link_stack$ cat main.c // gcc main.c linkstack.c linklist.c -Wall -g && ./a.out #include <stdio.h> #include <stdlib.h> #include "linkstack.h" int isLeft(char c) { int ret = 0; switch(c) { case '<': case '(': case '[': case '{': case '\'': case '\"': ret = 1; break; default: ret = 0; break; } return ret; } int isRight(char c) { int ret = 0; switch(c) { case '>': case ')': case ']': case '}': case '\'': case '\"': ret = 1; break; default: ret = 0; break; } return ret; } int match(char left, char right) { int ret = 0; switch(left) { case '<': ret = (right == '>'); break; case '(': ret = (right == ')'); break; case '[': ret = (right == ']'); break; case '{': ret = (right == '}'); break; case '\'': ret = (right == '\''); break; case '\"': ret = (right == '\"'); break; default: ret = 0; break; } return ret; } int scanner(const char* code) { LinkStack* stack = LinkStack_Create(); int ret = 0; int i = 0; while( code[i] != '\0' ) { if( isLeft(code[i]) ) { LinkStack_Push(stack, (void*)(code + i)); //&code[i] } if( isRight(code[i]) ) { char* c = (char*)LinkStack_Pop(stack); if( (c == NULL) || !match(*c, code[i]) ) { printf("%c does not match!\n", code[i]); ret = 0; break; } } i++; } if( (LinkStack_Size(stack) == 0) && (code[i] == '\0') ) { printf("Succeed!\n"); ret = 1; } else { printf("Invalid code!\n"); ret = 0; } LinkStack_Destroy(stack); return ret; } int main() { //const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0; ";//Invalid code! const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0; }";//Succeed! scanner(code); return 0; } chunli@http://990487026.blog.51cto.com~/link_stack$ 编译运行: chunli@http://990487026.blog.51cto.com~/link_stack$ gcc main.c linkstack.c linklist.c -Wall -g && ./a.out Succeed! chunli@http://990487026.blog.51cto.com~/link_stack$
4,栈的典型应用2:中缀转后缀
计算机的本质工作就是做数学运算,那计算机可以读入字符串
“9 + (3 - 1) * 5 + 8 / 2”并计算值吗?
后缀表达式 ==?符合计算机运算
波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式对应的,
我们习惯的数学表达式叫做中缀表达式===》符合人类思考习惯
实例:
5 + 4=> 5 4 +
1 + 2 * 3 => 1 2 3 * +
8 + ( 3 – 1 ) * 5 => 8 3 1 – 5 * +
中缀表达式符合人类的阅读和思维习惯
后缀表达式符合计算机的“运算习惯”
如何将中缀表达式转换成后缀表达式?
中缀转后缀算法:
遍历中缀表达式中的数字和符号
对于数字:直接输出
对于符号:
左括号:进栈
运算符号:与栈顶符号进行优先级比较
若栈顶符号优先级低:此符合进栈 (默认栈顶若是左括号,左括号优先级最低)
若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
右括号:将栈顶符号弹出并输出,直到匹配左括号
遍历结束:将栈中的所有符号弹出并输出
中缀转后缀
项目文件:
chunli@http://990487026.blog.51cto.com~/link_stack$ tree . ├── linklist.c ├── linklist.h ├── linkstack.c ├── linkstack.h └── main.c 0 directories, 8 files
除了main.c文件与之前的文件不一样,linklist.c,linklist.h,linkstack.c,linkstack.h和上面的一样
chunli@http://990487026.blog.51cto.com~/link_stack$ cat main.c // gcc main.c linkstack.c linklist.c -Wall -g && ./a.out #include <stdio.h> #include <stdlib.h> #include <string.h> #include "linkstack.h" size_t isNumber(char c) { return ('0' <= c) && (c <= '9'); } size_t isOperator(char c) { return (c == '+') || (c == '-') || (c == '*') || (c == '/'); } size_t isLeft(char c) { return (c == '('); } size_t isRight(char c) { return (c == ')'); } size_t priority(char c)//求符号的优先级 { size_t ret = 0; if( (c == '+') || (c == '-') ) { ret = 1; } if( (c == '*') || (c == '/') ) { ret = 2; } return ret; } void output(char c) { if( c != '\0' ) { printf("%c", c); } } void transform(const char* exp) { size_t i = 0; LinkStack* stack = LinkStack_Create(); while( exp[i] != '\0' ) { if( isNumber(exp[i]) ) { output(exp[i]); } else if( isOperator(exp[i]) ) { while( priority(exp[i]) <= priority((char)(size_t)LinkStack_Top(stack)) ) { output((char)(size_t)LinkStack_Pop(stack)); } LinkStack_Push(stack, (void*)(size_t)exp[i]); } else if( isLeft(exp[i]) ) { LinkStack_Push(stack, (void*)(size_t)exp[i]); } else if( isRight(exp[i]) ) { //char c = '\0'; while( !isLeft((char)(size_t)LinkStack_Top(stack)) ) { output((char)(size_t)LinkStack_Pop(stack)); } LinkStack_Pop(stack); } else { printf("Invalid expression!"); break; } i++; } while( (LinkStack_Size(stack) > 0) && (exp[i] == '\0') ) { output((char)(size_t)LinkStack_Pop(stack)); } LinkStack_Destroy(stack); } int main() { const char *str = "8+(3-1)*5"; printf("中缀表达式:%s\n",str); printf("后缀表达式:"); transform(str); printf("\n"); return 0; } chunli@http://990487026.blog.51cto.com~/link_stack$ gcc main.c linkstack.c linklist.c -Wall -g && ./a.out 中缀表达式:8+(3-1)*5 后缀表达式:831-5*+ chunli@http://990487026.blog.51cto.com~/link_stack$
队列
1,队列顺序存储
项目文件:
chunli@http://990487026.blog.51cto.com~/seq_queue$ tree . ├── main.c ├── seqlist.c ├── seqlist.h ├── seqqueue.c └── seqqueue.h 0 directories, 5 files
main.c
chunli@http://990487026.blog.51cto.com~/seq_queue$ cat main.c #include <stdio.h> #include "seqqueue.h" #define MAX 20 int main() { int ret = 0; int i = 0; int arr[MAX] = {0}; SeqQueue *queue = SeqQueue_Create(MAX); if(queue == NULL) { return -1; } for(i=0;i<MAX;i++) { arr[i] = i*i+i+1; ret = SeqQueue_Append(queue,&arr[i]); if(ret != 0) { printf("error in SeqQueue_Append %d\n",ret); return -2; } } printf("队列的长度%d\n",SeqQueue_Length(queue)); printf("队列的头元素%d\n",*(int*)SeqQueue_Header(queue)); while(SeqQueue_Length(queue) > 0) { printf("正在出列%3d\n",*(int*)SeqQueue_Header(queue)); SeqQueue_Retrieve(queue); } SeqQueue_Destroy(queue); return 0; } chunli@http://990487026.blog.51cto.com~/seq_queue$
seqlist.c
chunli@http://990487026.blog.51cto.com~/seq_queue$ cat seqlist.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "seqlist.h" //申明一个结构体类型,用来存储线性表自己的信息 typedef struct _tag_SeqList { int length; //线性表的实际利用长度 int capacity; //线性表一共有多长 size_t *node; }TSeqList; //创建线性表 SeqList* SeqList_Create(int capacity)//相当于分配数组的大小 { TSeqList * tmp = NULL; //创建线性表的头,放在堆内存中 tmp = (TSeqList*)malloc(sizeof(TSeqList)); if(tmp == NULL) { printf("ERROR in (TSeqList*)malloc(sizeof(TSeqList)) \n"); return NULL; } //做个细心的人 memset(tmp,0,sizeof(TSeqList)); //根据capacity的大小,创建线性表的长度 tmp->node = (size_t *)malloc(sizeof(size_t*) *capacity ); if(tmp->node == NULL) { printf("ERROR in (unsigned int *)malloc(sizeof(unsigned int *) * capacity ) \n"); return NULL; } tmp->length = 0; tmp->capacity = capacity; return tmp; } //销毁链表 void SeqList_Destroy(SeqList* list) { TSeqList *tlist = NULL; if(list == NULL) { printf("list == NULL \n"); return; } tlist = (TSeqList *)list; if(tlist ->node != NULL) { free(tlist->node);//释放存储内存区 } free(tlist); //释放线性表头 return ; } //清空链表的长度 void SeqList_Clear(SeqList* list) { TSeqList *tlist = NULL; if(list == NULL) { printf("list == NULL \n"); return; } tlist = (TSeqList *)list; tlist->length = 0; return ; } //返回线性表的长度 int SeqList_Length(SeqList* list) { TSeqList *tlist = NULL; if(list == NULL) { printf("list == NULL \n"); return -1; } tlist = (TSeqList *)list; return tlist->length; } //返回线性表的容量 int SeqList_Capacity(SeqList* list) { TSeqList *tlist = NULL; if(list == NULL) { printf("list == NULL \n"); return -1; } tlist = (TSeqList *)list; return tlist->capacity; } //节点的插入 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) { if(list == NULL || node == NULL || pos <0) { printf("list == NULL || node == NULL \n"); return -1; } TSeqList *tlist = NULL; tlist = (TSeqList *)list; //判断容量是不是 满了 if(tlist->length >= tlist->capacity) { printf("插入失败,线性表已经装满了\n"); } //容错修正 20个容量,已经用到6,要求在10插入 if(pos >= tlist->length ) { pos = tlist->length; } int i = 0; for(i = tlist->length;i > pos;i--) { tlist->node[i] = tlist->node[i-1]; } tlist->length ++; tlist->node[pos] = *(size_t *)node; return 0; } SeqListNode* SeqList_Get(SeqList* list, int pos) { if(list == NULL || pos <0) { printf("检测到线性表为空,返回NULL \n"); return NULL; } TSeqList *tlist = NULL; tlist = (TSeqList *)list; return &tlist->node[pos]; } SeqListNode* SeqList_Delete(SeqList* list, int pos) { if(list == NULL || pos <0) { printf("线性表为空 \n"); return NULL; } TSeqList *tlist = NULL; tlist = (TSeqList *)list; int i = 0; for(i = pos+1;i<tlist->length;i++) { tlist->node[i-1] = tlist->node[i]; } tlist->length --; return NULL; } chunli@http://990487026.blog.51cto.com~/seq_queue$
seqlist.h
chunli@http://990487026.blog.51cto.com~/seq_queue$ cat seqlist.h #ifndef __MY_SEQLIST_H__ #define __MY_SEQLIST_H__ typedef void SeqList; typedef void SeqListNode; SeqList* SeqList_Create(int capacity); void SeqList_Destroy(SeqList* list); void SeqList_Clear(SeqList* list); int SeqList_Length(SeqList* list); int SeqList_Capacity(SeqList* list); int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); SeqListNode* SeqList_Get(SeqList* list, int pos); SeqListNode* SeqList_Delete(SeqList* list, int pos); #endif //__MY_SEQLIST_H__ chunli@http://990487026.blog.51cto.com~/seq_queue$
seqqueue.c
chunli@http://990487026.blog.51cto.com~/seq_queue$ cat seqqueue.c #include "seqqueue.h" #include "seqlist.h" //创建队列,相当于创建一个线性表 SeqQueue* SeqQueue_Create(int capacity) { return SeqList_Create(capacity); } void SeqQueue_Destroy(SeqQueue* queue) { SeqList_Destroy(queue); } void SeqQueue_Clear(SeqQueue* queue) { SeqList_Clear(queue); } //向队列中添加元素,相当于 向线性表中,尾部插入元素 int SeqQueue_Append(SeqQueue* queue, void* item) { return SeqList_Insert(queue, item, SeqList_Length(queue)); } //从队列中删除元素,相当于从线性表中删除第一个元素 void* SeqQueue_Retrieve(SeqQueue* queue) { return SeqList_Delete(queue, 0); } void* SeqQueue_Header(SeqQueue* queue) { return SeqList_Get(queue, 0); } int SeqQueue_Length(SeqQueue* queue) { return SeqList_Length(queue); } int SeqQueue_Capacity(SeqQueue* queue) { return SeqList_Capacity(queue); } chunli@http://990487026.blog.51cto.com~/seq_queue$
seqqueue.h
chunli@http://990487026.blog.51cto.com~/seq_queue$ cat seqqueue.h #ifndef _MY_SEQQUEUE_H_ #define _MY_SEQQUEUE_H_ typedef void SeqQueue; SeqQueue* SeqQueue_Create(int capacity); void SeqQueue_Destroy(SeqQueue* queue); void SeqQueue_Clear(SeqQueue* queue); int SeqQueue_Append(SeqQueue* queue, void* item); void* SeqQueue_Retrieve(SeqQueue* queue); void* SeqQueue_Header(SeqQueue* queue); int SeqQueue_Length(SeqQueue* queue); int SeqQueue_Capacity(SeqQueue* queue); #endif //_MY_SEQQUEUE_H_ chunli@http://990487026.blog.51cto.com~/seq_queue$
编译运行:
chunli@http://990487026.blog.51cto.com~/seq_queue$ gcc main.c seqqueue.c seqlist.c -Wall -g&& ./a.out 队列的长度20 队列的头元素1 正在出列 1 正在出列 3 正在出列 7 正在出列 13 正在出列 21 正在出列 31 正在出列 43 正在出列 57 正在出列 73 正在出列 91 正在出列111 正在出列133 正在出列157 正在出列183 正在出列211 正在出列241 正在出列273 正在出列307 正在出列343 正在出列381 chunli@http://990487026.blog.51cto.com~/seq_queue$
2,队列链式储存设计与实现:
项目文件:
chunli@http://990487026.blog.51cto.com~/link_queue$ tree . ├── linklist.c ├── linklist.h ├── linkqueue.c ├── linkqueue.h └── main.c 0 directories, 5 files
链表实现实现文件:
chunli@http://990487026.blog.51cto.com~/link_queue$ cat linklist.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "linklist.h" typedef struct _tag_LinkList { //这个句柄里面,需要保存所有节点信息。需要有一个起始点 //就是带头节点的链表。。。 LinkListNode header; int length; }TLinkList; LinkList* LinkList_Create() { TLinkList *ret = (TLinkList *)malloc(sizeof(TLinkList)); if (ret == NULL) { return NULL; } //memset(ret, 0, sizeof(TLinkList)); ret->header.next = NULL; ret->length = 0; return ret; } void LinkList_Destroy(LinkList* list) { if (list == NULL) { return ; } free(list); return ; } void LinkList_Clear(LinkList* list) { TLinkList *tList =NULL; if (list == NULL) { return ; } tList = (TLinkList *)list; tList->length = 0; tList->header.next = NULL; return ; } int LinkList_Length(LinkList* list) { TLinkList *tList = (TLinkList *)list; if (tList == NULL) { return -1; } return tList->length; } int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) { int i = 0; TLinkList *tList = NULL; LinkListNode *current = NULL; tList = (TLinkList *)list; if (list==NULL || node==NULL) //modify by bombing 2014.06.26 { return -1; } //准备环境让辅助指针变量 指向链表头节点 current = &tList->header; for (i=0; i<pos &&(current->next!=NULL); i++) { current = current->next; } //让node节点链接后续链表 node->next = current->next ; //让前边的链表。链接node current->next = node; tList->length ++; return 0; } LinkListNode* LinkList_Get(LinkList* list, int pos) { int i = 0; TLinkList *tList = NULL; LinkListNode *current = NULL; LinkListNode *ret = NULL; tList = (TLinkList *)list; if (list == NULL || pos <0 ||pos>=tList->length) { return NULL; } //准备环境让辅助指针变量 指向链表头节点 current = &tList->header; for (i=0; i<pos &&(current->next!=NULL); i++) { current = current->next; } ret = current->next; return ret; } LinkListNode* LinkList_Delete(LinkList* list, int pos) { int i = 0; TLinkList *tList = NULL; LinkListNode *current = NULL; LinkListNode *ret = NULL; tList = (TLinkList *)list; if (list == NULL || pos <0 ||pos>=tList->length) { return NULL; } //准备环境让辅助指针变量 指向链表头节点 current = &tList->header; for (i=0; i<pos &&(current->next!=NULL); i++) { current = current->next; } ret = current->next; //删除算法 current->next =ret->next; tList->length--; return ret; } chunli@http://990487026.blog.51cto.com~/link_queue$
链表函数声明文件:
chunli@http://990487026.blog.51cto.com~/link_queue$ cat linklist.h #ifndef _MYLINKLIST_H_ #define _MYLINKLIST_H_ typedef void LinkList; /* typedef struct _tag_LinkListNode LinkListNode; struct _tag_LinkListNode { LinkListNode* next; }; */ typedef struct _tag_LinkListNode { struct _tag_LinkListNode* next; }LinkListNode; LinkList* LinkList_Create(); void LinkList_Destroy(LinkList* list); void LinkList_Clear(LinkList* list); int LinkList_Length(LinkList* list); int LinkList_Insert(LinkList* list, LinkListNode* node, int pos); LinkListNode* LinkList_Get(LinkList* list, int pos); LinkListNode* LinkList_Delete(LinkList* list, int pos); #endif chunli@http://990487026.blog.51cto.com~/link_queue$
队列的实现文件:
chunli@http://990487026.blog.51cto.com~/link_queue$ cat linkqueue.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include "linkqueue.h" #include "linklist.h" typedef struct _tag_LinkQueueNode { LinkListNode node; void *item; }TLinkQueueNode; //思想:用线性表来模拟队列 //创建一个队列,相当于创建一个线性表 LinkQueue* LinkQueue_Create() //O(1) { return LinkList_Create(); } void LinkQueue_Destroy(LinkQueue* queue) //O(1) { LinkQueue_Clear(queue); LinkList_Destroy(queue); return ; } void LinkQueue_Clear(LinkQueue* queue) //O(n) { while (LinkQueue_Length(queue) > 0) { LinkQueue_Retrieve(queue); } //LinkQueue_Clear(queue); return ; } //向队列中添加元素,相当于向队列的尾部插入元素 int LinkQueue_Append(LinkQueue* queue, void* item) //O(n) { int ret = 0; TLinkQueueNode *node = NULL; //需要向linklist中添加业务节点,需要在业务节点中包含链表结点 //需要让链表结点放在业务节点的第一个成员域。 //把形参item,转换为 linklist识别的业务节点 node = (TLinkQueueNode *)malloc(sizeof(TLinkQueueNode)); if (node == NULL) { return -1; } memset(node, 0, sizeof(TLinkQueueNode)); node->item = item; ret = LinkList_Insert(queue, (LinkListNode *)node, LinkList_Length(queue)); if (ret != 0) { free(node); return ret; } return ret; } //从队列删除元素,相当于从队列的头部拿元素 void* LinkQueue_Retrieve(LinkQueue* queue) //O(1) { void *item = NULL; TLinkQueueNode *node = NULL; //需要向linklist中添加业务节点,需要在业务节点中包含链表结点 node = (TLinkQueueNode *)LinkList_Delete(queue, 0); if (node == NULL) { return NULL; } item = node->item; if (node != NULL) { free(node); node = NULL; } return item; } //获取队列头元素,相当于从队列0位置拿元素 void* LinkQueue_Header(LinkQueue* queue) //O(1) { void *item = NULL; TLinkQueueNode *node = NULL; node = (TLinkQueueNode *)LinkList_Get(queue, 0); if (node == NULL) { return NULL; } item = node->item; return item; } int LinkQueue_Length(LinkQueue* queue) { return LinkList_Length(queue); } chunli@http://990487026.blog.51cto.com~/link_queue$
队列的申明文件:
chunli@http://990487026.blog.51cto.com~/link_queue$ cat linkqueue.h #ifndef _MY_LINKQUEUE_H_ #define _MY_LINKQUEUE_H_ typedef void LinkQueue; LinkQueue* LinkQueue_Create(); void LinkQueue_Destroy(LinkQueue* queue); void LinkQueue_Clear(LinkQueue* queue); int LinkQueue_Append(LinkQueue* queue, void* item); void* LinkQueue_Retrieve(LinkQueue* queue); void* LinkQueue_Header(LinkQueue* queue); int LinkQueue_Length(LinkQueue* queue); #endif //_MY_LINKQUEUE_H_ chunli@http://990487026.blog.51cto.com~/link_queue$
主函数:
chunli@http://990487026.blog.51cto.com~/link_queue$ cat main.c // chunli@http://990487026.blog.51cto.com~/link_queue$ gcc main.c linklist.c linkqueue.c -Wall && ./a.out // 队列的长度:20 // 队头元素:1 // 出列:1 // 出列:3 // 出列:7 // 出列:13 // 出列:21 // 出列:31 // 出列:43 // 出列:57 // 出列:73 // 出列:91 // 出列:111 // 出列:133 // 出列:157 // 出列:183 // 出列:211 // 出列:241 // 出列:273 // 出列:307 // 出列:343 // 出列:381 // chunli@http://990487026.blog.51cto.com~/link_queue$ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "linkqueue.h" #define MAX 20 int main() { int i = 0; int a[MAX] = {0}; //创建队列 LinkQueue *queue = LinkQueue_Create(); if(queue == NULL) { printf("error in LinkQueue_Create()\n"); return -1; } //入队列 for(i=0;i<MAX;i++) { a[i] = i*i+i+1; LinkQueue_Append(queue,&a[i]); } //求队列的属性 printf("队列的长度:%d\n",LinkQueue_Length(queue)); printf("队头元素:%d\n",*(int*)LinkQueue_Header(queue)); //出列 while(LinkQueue_Length(queue) > 0) { printf("出列:%d\n",*(int*)LinkQueue_Header(queue)); LinkQueue_Retrieve(queue); } //销毁队列 LinkQueue_Destroy(queue); return 0; } chunli@http://990487026.blog.51cto.com~/link_queue$
编译运行:
chunli@http://990487026.blog.51cto.com~/link_queue$ gcc -Wall main.c linklist.c linkqueue.c &&./a.out 队列的长度:20 队头元素:1 出列:1 出列:3 出列:7 出列:13 出列:21 出列:31 出列:43 出列:57 出列:73 出列:91 出列:111 出列:133 出列:157 出列:183 出列:211 出列:241 出列:273 出列:307 出列:343 出列:381 chunli@http://990487026.blog.51cto.com~/link_queue$