数据结构中单链表的实现+单链表的C语言实现源代码

线性表(List):零个或多个数据元素的有限序列。线性表的抽象数据类型。

线性表的顺序存储:

优点:无须为表示表中元素的逻辑关系而额外的存储空间,可以快速的取表中任意位置的元素。

缺点:插入和删除操作需要转移大量元素,线性表的长度较大时,难以确定存储空间的容量, 造成存储空间的“碎片”。

线性表的链式存储:

为了表示每一个数据元素a1与其直接后级数据元素ai+1之间的逻辑关系,对数据元素a1来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信号(即直接后继的存储位置)。存储数据元素信息的域叫做数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称为指针或链。这两部分组成数据元素ai的存储影像,称为结点(Node

其中头指针和头结点的区别:

1,头指针是指向链表的第一个结点的指针,若链表有都结点,则指向头结点的指针。头指针具有标示作用,所以常用头指针冠以链表的名字。无论链表是否为空,头指针均不为空,头指针是链表的必要条件。

2,头结点是为了操作的统一和方便设置的,放在头一个元素的结点之前,其数据域一般无意义。有了头结点,对其在第一元素位置前插入删除擦偶偶与其他结点的操作统一。头结点不是链表的必须要素。

带有头结点的指针;

空链表:

C语言中用结构指针表示结点:

typedef struct Node
{	
	int data;
	struct Node *next;
}Node, *pNode,*LinkList;

 

其中单链表的抽象数据结构即操作有:

void InitList(LinkList *list);//初始化操作,建立空的单链表
void ClearList(LinkList *list);//清空单链表。

void ListInsert(LinkList *list,int i, int e);//单链表第i个位置后面插入变量e
void DestoryList(LinkList *list);//销毁链表
bool ListEmpty(LinkList list);//判断单链表是否为空,为空返回真
void GetElem(LinkList, int &e, int i);//将单链表中第i个位置的值返回给变量e
void ListDelete(LinkList *list, int i, int &e);//删除单链表表第i个位置元素
void ListTraverse(LinkList list);//遍历线性表
int ListLength(LinkList list);//返回线性表的长度
void Recursion(LinkList list);//递归逆序输出单链表

各种函数的实现源代码:

void InitList(LinkList *list)
{
	*list = (LinkList)malloc(sizeof(Node));
	(*list)->next = NULL;
	(*list)->data = 0;
}
void ListInsert(LinkList *list, int i , int e)//第i个元素后面插入e
{	
	LinkList p = *list;
	
	if( i == 0)
		{
			pNode q = (LinkList)malloc(sizeof(Node));
			q->next = NULL;
			q->data = e;
			p->next = q;
		}
	else
		{	
			pNode p = (*list)->next;
			int j = 1;

			while( p && i > j)
			{
				p = p->next;
				++j;
			}

			pNode q = (LinkList)malloc(sizeof(Node));
			q->next = p->next;
			q->data = e;
			p->next = q;
		}
	
}
void ListTraverse(LinkList list)
{
	pNode p = list;
	if(p != NULL)
	{
		p = p->next;
	}	
	else 	
	{
		return;
	}
	while(p)
	{
		printf("%d\t", p->data);
		p = p->next;
	}
}
void Recursion(LinkList list)//递归的方法逆序输出链表
{ 
	if(NULL==list)
	{ 
		return;
	} 
	if(list->next!=NULL)
	{
	 Recursion(list->next);
	 }
	printf("%d\t",list->data);
}
bool ListEmpty(LinkList list)
{
	pNode p = list;

	if(NULL == list->next)
		return true;
	else
		return false;
}
void GetElem(LinkList list, int &e, int i)
{
	pNode p = list;
	
	if( i < 0 || i > ListLength(list))
		return ;
	p = p->next;
	int j = 1;
	while( j < i)
		{
			p = p->next;
			j++;
		}
	e = p->data;
}
void ListDelete(LinkList *list, int i, int &e)
{
	pNode p = *list;
	if( i < 0 || i > ListLength(*list))
		return ;
	pNode q = p;
	p = q->next;
	int j = 1;
	while( j < i )
		{	q = p;
			p = p->next;
			j++;
		}
	p->data = e;
	q->next = p->next;
	free(p);
	

	
}
int ListLength(LinkList list)
{
	pNode p = list;
	int i = 0;
	p = p->next;
	while(p)
		{
			p = p->next;
			i++;
		}
	return i;
}
void ClearList (LinkList *list)
{
	pNode p = *list;
	if( p != NULL)
		p = p->next;
	pNode q;
	while( p )
	{
		q = p;
		p = p->next;
		free(q);
	}
	
}
void DestoryList(LinkList *list)
{
	pNode p = *list;
	if( p != NULL)
		p = p->next;
	pNode q;
	while( p )
	{
		q = p;
		p = p->next;
		free(q);
	}
	free(*list);
}

测试函数源代码:

int main()
{
	LinkList list;

	InitList(&list);
	
	ListInsert(&list, 0, 1);
	ListInsert(&list, 1, 2);
	ListInsert(&list, 2, 3);
	ListInsert(&list, 1, 4);
	ListInsert(&list, 1, 5);
	ListInsert(&list, 5, 6);
	ListInsert(&list, 6, 7);
	ListInsert(&list, 7, 8);
	ListInsert(&list, 8, 9);
	ListInsert(&list, 9, 10);

	printf("\n递归调用函数Reversion:\n");
	LinkList p = list->next;
	Recursion(p);

	printf("\n遍历链表ListTranverse:\n");
	ListTraverse(list);


	int j = ListLength(list);
	printf("\n链表的长度ListLength:%d\t",j);

	int e;
	GetElem(list, e,  3);
	printf("取链表特定的元素GetElem : %d\n",e);

	ListDelete(&list, 1, e);
	printf("\n删除链表中特定位置的元素:%d\n", e);
	ListTraverse(list);

	ClearList (&list);
	printf("\n链表清空ClearList: \n");
	ListInsert(&list, 0, 1);
	ListInsert(&list, 1, 2);
	ListInsert(&list, 2, 3);
	ListTraverse(list);


	DestoryList(&list);

	return 0;
}


参考: 大话数据结构,数据结构(C语言版)严蔚敏版



 

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值