第2章课本算法实现 SinglyLinkedList

时间:2019-01-23
本文章向大家介绍第2章课本算法实现 SinglyLinkedList,主要包括第2章课本算法实现 SinglyLinkedList使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
/*******************************************
 * 文件夹: ▲02 线性表\04 SinglyLinkedList *
 * 文件名: SinglyLinkedList.h              *
 * 内  容: 单链表相关操作列表              *
 *******************************************/

#ifndef SINGLYLINKEDLIST_H
#define SINGLYLINKEDLIST_H

#include <stdio.h>
#include <stdlib.h>						//提供malloc、realloc、free、exit原型
#include "../../▲01 绪论/Status.h"		//**▲01 绪论**//
#include "../../▲01 绪论/Scanf.c"		//**▲01 绪论**//

/* 单链表类型定义 */
#ifndef BANKQUEUING_H			/*后续的模拟银行排队算法中,此类型需要重新定义*/
typedef int LElemType_L;

/* 单链表结构体 */
typedef struct LNode
{
	LElemType_L data;
	struct LNode* next;
}LNode;
typedef LNode* LinkList;		//指向单链表结点的指针 
#endif

/* 单链表(带头结点)函数列表 */

// (01)初始化单链表L
Status InitList_L(LinkList *L);

//(02)置空单链表L,头结点保留
Status ClearList_L(LinkList L);
 
//(03)销毁单链表L,连同通结点一起销毁
void DestroyList_L(LinkList *L);

//(04)判断单链表L是否为空
Status ListEmpty_L(LinkList L);

//(05)返回单链表L元素个数
int ListLength_L(LinkList L);
 
//(06)算法2.8:用e接收单链表L中第i个元素
Status GetElem_L(LinkList L, int i, LElemType_L *e);

//(07)返回单链表L中第一个与e满足Compare关系的元素位序
int LocateElem_L(LinkList L, LElemType_L e, Status(Compare)(LElemType_L, LElemType_L));

//(08)用pre_e接收cur_e的前驱
Status PriorElem_L(LinkList L, LElemType_L cur_e, LElemType_L *pre_e);

//(09)用next_e接收cur_e的后继
Status NextElem_L(LinkList L, LElemType_L cur_e, LElemType_L *next_e);

//(10)算法2.9:在单链表L第i个位置之前插入e
Status ListInsert_L(LinkList L, int i, LElemType_L e);

//(11)算法2.10:删除单链表L第i个位置的值,并用e接收
Status ListDelete_L(LinkList L, int i, LElemType_L *e);
 
//(12)用Visit函数访问单链表L
Status ListTraverse_L(LinkList L, void(Visit)(LElemType_L));
 
//(13)算法2.11:头插法建立单链表L(逆序输入)
Status CreateList_HL(FILE *fp, LinkList *L, int n);
  
//(14)尾插法建立单链表L(顺序输入)
Status CreateList_TL(FILE *fp, LinkList *L, int n);

#endif
/*******************************************
 * 文件夹: ▲02 线性表\04 SinglyLinkedList *
 * 文件名: SinglyLinkedList.c              *
 * 算  法: 2.8、2.9、2.10、2.11            * 
 *******************************************/

#ifndef SINGLYLINKEDLIST_C
#define SINGLYLINKEDLIST_C

#include "SinglyLinkedList.h" 			//**▲02 线性表**//

//(01)初始化单链表L
Status InitList_L(LinkList *L)
{
	(*L) = (LinkList)malloc(sizeof(LNode));
	if(!(*L))
		exit(OVERFLOW);
	(*L)->next = NULL;
	
	return OK;
}

//(02)置空单链表L,头结点保留
Status ClearList_L(LinkList L)			//保留头结点 
{	
	LinkList pre, p;
	
	if(!L)
		return ERROR;
	
	pre = L->next;

	while(pre)
	{
		p = pre->next;
		free(pre);
		pre = p;
	}

	L->next = NULL;

	return OK; 
}

//(03)销毁单链表L,连同通结点一起销毁
void DestroyList_L(LinkList *L)			//销毁所有结点 
{
	LinkList p = *L;	

	while(p)
	{
		p = (*L)->next;
		free(*L);
		(*L) = p;
	}
}

//(04)判断单链表L是否为空
Status ListEmpty_L(LinkList L)
{
	if(L!=NULL && L->next==NULL)		//链表存在且只有头结点 
		return TRUE;
	else
		return FALSE;
}

//(05)返回单链表L元素个数
int ListLength_L(LinkList L)
{
	LinkList p;
	int i;
	
	if(L)
	{
		i = 0;
		p = L->next;
		while(p)
		{
			i++;
			p = p->next;
		}		
	}
	
	return i;
}

//(06)算法2.8:用e接收单链表L中第i个元素
Status GetElem_L(LinkList L, int i, LElemType_L *e)
{
	int j;
	LinkList p = L->next;
	
	j = 1;
	p = L->next;
	
	while(p && j<i)						//p不为空且还未到达i处
	{
		j++;
		p = p->next;
	}

	if(!p || j>i)						//第i个元素不存在 
		return ERROR;

	*e = p->data;

	return OK; 
}

//(07)返回单链表L中第一个与e满足Compare关系的元素位序
int LocateElem_L(LinkList L, LElemType_L e, Status(Compare)(LElemType_L, LElemType_L))
{
	int i;
	LinkList p;
	
	i = -1;								//L不存在时返回-1 
	
	if(L)
	{
		i = 0;
		p = L->next;
		
		while(p)
		{
			i++;
			
			if(!Compare(e, p->data))
			{
				p = p->next;
				if(p==NULL)		//失配时已经是最后一个结点 
					i++;
			}
			else
				break;
		}	
	}

	return i;	
}

/* 银行排队算法中,此处两个函数不能直接使用,原因是结构不能直接比较 */
#ifndef BANKQUEUING_C
//(08)用pre_e接收cur_e的前驱				
Status PriorElem_L(LinkList L, LElemType_L cur_e, LElemType_L *pre_e)
{
	LinkList p, suc;
	
	if(L)
	{
		p = L->next;
		
		if(p->data!=cur_e)				//第一个结点无前驱 
		{
			while(p->next)				//若p结点有后继 
			{
				suc = p->next;			//suc指向p的后继
				if(suc->data==cur_e)
				{
					*pre_e = p->data;
					return OK;
				}
				p = suc;
			}			
		}	
	}

	return ERROR;
}

//(09)用next_e接收cur_e的后继
Status NextElem_L(LinkList L, LElemType_L cur_e, LElemType_L *next_e)
{
	LinkList p, suc;
	
	if(L)
	{
		p = L->next;
		
		while(p && p->next)
		{
			suc = p->next;
			
			if(suc && p->data==cur_e)
			{
				*next_e = suc->data;
				return OK;
			}
			
			if(suc)
				p = suc;
			else
				break;
		}	
	}

	return ERROR;
}
#endif

//(10)算法2.9:在单链表L第i个位置之前插入e
Status ListInsert_L(LinkList L, int i, LElemType_L e)
{
	LinkList p, s;
	int j;
	
	p = L;
	j = 0; 
	
	while(p && j<i-1)					//寻找第i-1个结点 
	{
		p = p->next;
		++j;
	}
	
	if(!p || j>i-1)
		return ERROR;

	s = (LinkList)malloc(sizeof(LNode));
	if(!s)
		exit(OVERFLOW);
	s->data = e;
	s->next = p->next;
	p->next = s;

	return OK;
}



//(11)算法2.10:删除单链表L第i个位置的值,并用e接收
Status ListDelete_L(LinkList L, int i, LElemType_L *e)
{
	LinkList pre, p; 
	int j;

	pre = L;
	j = 1; 

	while(pre->next && j<i)			//寻找第i个结点,并令pre指向其前驱 
	{
		pre = pre->next;
		++j;
	}
	
	if(!pre->next || j>i)			//删除位置不合理
		return ERROR;

	p = pre->next;
	pre->next = p->next;
	*e = p->data;
	free(p);

	return OK; 
}

//(12)用Visit函数访问单链表L
Status ListTraverse_L(LinkList L, void(Visit)(LElemType_L))
{
	LinkList p;

	if(!L)
		return ERROR;
	else
		p = L->next;	

	while(p)
	{
		Visit(p->data);
		p = p->next;
	}

	return OK;
}

//(13)算法2.11:头插法建立单链表L(逆序输入)
Status CreateList_HL(FILE *fp, LinkList *L, int n)
{
	int i;
	LinkList p;
	LElemType_L tmp;
		
	*L = (LinkList)malloc(sizeof(LNode));
	if(!(*L))
		exit(OVERFLOW);
	(*L)->next = NULL;							//建立头结点 
	
	for(i=1; i<=n; ++i)
	{
		if(Scanf(fp, "%d", &tmp)==1)
		{
			p = (LinkList)malloc(sizeof(LNode));
			if(!p)
				exit(OVERFLOW);
			p->data = tmp;						//录入数据 
			p->next = (*L)->next;
			(*L)->next = p;		
		}
		else
			return ERROR;
	}
	
	return OK;
}  

//(14)尾插法建立单链表L(顺序输入)
Status CreateList_TL(FILE *fp, LinkList *L, int n)
{
	int i;
	LinkList p, q;
	LElemType_L tmp;	
			
	*L = (LinkList)malloc(sizeof(LNode));
	if(!(*L))
		exit(OVERFLOW);
	(*L)->next = NULL;
		
	for(i=1,q=*L; i<=n; ++i)
	{
		if(Scanf(fp, "%d", &tmp)==1)
		{
			p = (LinkList)malloc(sizeof(LNode));
			if(!p)
				exit(OVERFLOW);
			p->data = tmp;						//录入数据 
			q->next = p;
			q = q->next;		
		}
		else
			return ERROR;		
	}
	
	q->next = NULL;

	return OK;
}

#endif 
/*******************************************
 * 文件夹: ▲02 线性表\04 SinglyLinkedList *
 * 内  容: 单链表相关函数测试              *
 *******************************************/

#include <stdio.h> 
#include "SinglyLinkedList.c" 						//**▲02 线性表**//

/* 函数原型 */
Status CmpGreater(LElemType_L e, LElemType_L data);	//判断data是否大于e //若data大于e,返回TRUE 
void PrintElem(LElemType_L e);						//测试函数,打印整型 
	
int main(int argc, char **argv)
{
	LinkList L;
	int i;
	LElemType_L e;
	
	printf("▼1\n▲函数 InitList_L 测试...\n");			//1.函数InitList_L测试
	{
		printf("初始化单链表 L ...\n");					 
		InitList_L(&L);
		printf("\n");	
	}
	PressEnter;
	
	printf("▼4\n▲函数 ListEmpty_L 测试...\n");		//4.函数ListEmpty_L测试
	{
		ListEmpty_L(L) ? printf(" L 为空!!\n") : printf(" L 不为空!\n");
		printf("\n");
	}
	PressEnter;
	
	printf("▼10\n▲函数 ListInsert_L 测试...\n");		//10.函数ListInsert_L测试
	{
		for(i=1; i<=6; i++)									
		{
			printf("在 L 第 %d 个位置插入 \"%d\" ...\n", i, 2*i);
			ListInsert_L(L, i, 2*i);
		}
		printf("\n");
	}
	PressEnter;
	
	printf("▼12\n▲函数 ListTraverse_L 测试...\n");	//12.函数ListTraverse_L测试
	{
		printf(" L 中的元素为:L = ");						 
		ListTraverse_L(L, PrintElem);
		printf("\n\n");
	}
	PressEnter;

	printf("▼5\n▲函数 ListLength_L 测试...\n");		//5.函数ListLength_L测试
	{
		printf(" L 的长度为 %d \n", ListLength_L(L));
		printf("\n");
	}
	PressEnter;
		
	printf("▼11\n▲函数 ListDelete_L 测试...\n");		//11.函数ListDelete_L测试
	{
		ListDelete_L(L, 6, &e);
		printf("删除 L 中第 6 个元素 \"%d\" ...\n", e);
		printf(" L 中的元素为:L = ");						 
		ListTraverse_L(L, PrintElem);
		printf("\n\n");
	}
	PressEnter;
		
	printf("▼6\n▲函数 GetElem_L 测试...\n");			//6.函数GetElem_L测试
	{
		GetElem_L(L, 4, &e);
		printf(" L 中第 4 个位置的元素为 \"%d\" \n", e);
		printf("\n");
	}
	PressEnter;
	
	printf("▼7\n▲函数 LocateElem_L 测试...\n");		//7.函数LocateElem_L测试
	{
		i = LocateElem_L(L, 13, CmpGreater);
		printf(" L 中第一个元素值大于 \"7\" 的元素的位置为 %d \n", i);
		printf("\n");
	}
	PressEnter;
	
	printf("▼8\n▲函数 PriorElem_L 测试...\n");		//8.函数PriorElem_L测试
	{
		PriorElem_L(L, 6, &e);
		printf("元素 \"6\" 的前驱为 \"%d\" \n", e);
		printf("\n");
	}
	PressEnter;
	
	printf("▼9\n▲函数 NextElem_L 测试...\n");			//9.函数NextElem_L测试
	{
		NextElem_L(L, 6, &e);
		printf("元素 \"6\" 的后继为 \"%d\" \n", e);
		printf("\n");
	}
	PressEnter;
	
	printf("▼2\n▲函数 ClearList_L 测试...\n");		//2.函数ClearList_L测试
	{
		printf("清空 L 前:");
		ListEmpty_L(L) ? printf(" L 为空!!\n") : printf(" L 不为空!\n");
		ClearList_L(L);
		printf("清空 L 后:");
		ListEmpty_L(L) ? printf(" L 为空!!\n") : printf(" L 不为空!\n");
		printf("\n");
	}
	PressEnter;
	
	printf("▼3\n▲函数 DestroyList_L 测试...\n");		//3.函数DestroyList_L测试
	{
		printf("销毁 L 前:");
		L ? printf(" L 存在!\n") : printf(" L 不存在!!\n");
		DestroyList_L(&L);
		pri