本文谢绝转载原文来自http://990487026.blog.51cto.com

数据结构与算法 2:双向链表,栈,队列_算法

数据结构与算法 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$



双向链表的正常的插入操作

数据结构与算法 2:双向链表,栈,队列_算法_02




双向链表的正常删除操作

数据结构与算法 2:双向链表,栈,队列_结构_03





双向链表的优缺点


优点:双向链表在单链表的基础上增加了指向前驱的指针

功能上双向链表可以完全取代单链表的使用

循环链表的Next,Pre和Current操作可以高效的遍历链表中的所有元素


缺点:代码复杂









栈的顺序储存,选型[图]

数据结构与算法 2:双向链表,栈,队列_数据_04



栈的链式储存,选型[图]


数据结构与算法 2:双向链表,栈,队列_数据_05



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$



数据结构与算法 2:双向链表,栈,队列_结构_06