数据结构之链表

  链表是一种物理存储单元上非连续、非顺序的数据结构。

一、链表的特点

(1)链表是由0或多个结点构成的

(2)除头结点外,每个结点都有一个前驱结点

(3)除尾结点外,每个结点都有一个后继结点

(4)链表的每个结点除了存储当前结点数据外,还存储下一个结点的地址

头结点:数据域无效

首结点:第一个数据域有效的结点

尾结点:指针域为空

空链表:既是头结点又是尾结点

三、链表的实现 

1.定义数据元素的类型

typedef struct UsrInfo
{
	int id;//编号
	char name[20]; //名字
}data_t;

2.定义单链表中节点的结构体

typedef struct Node
{
	data_t data;//  当前节点的数据元素
	struct Node * pNext;//下一个节点的首地址
}Node;

 3.定义描述一个单链表的结构体

typedef struct Link
{
	Node * pHead;//单链表中第一个节点的首地址
    int count;//节点的个数
}Link;

4.创建一个新节点

Node* createNode(data_t data)
{
	Node* pNode =(Node*) malloc(sizeof(Node));
	if(NULL == pNode) 
	{
		return NULL;
	}
	memset(pNode,'\0',sizeof(Node));
	pNode->data = data;
	return pNode;
}

5.创建空链表,没有一个节点,pHead = NULL,count = 0返回值:空链表表结构的首地址

Link* createLink()
{
	Link* pLink = (Link*)malloc(sizeof(Link));
	if(NULL == pLink)
	{
		return NULL;
	}
	memset(pLink,'\0',sizeof(Link));
	return pLink;
}

6.头插法,只要插入一个元素pHead就要被更新

int pushItemFront(Link* pLink,data_t data)
{
	if(NULL == pLink)
	{
		return LINK_ERROR;
	}
	//创建一个新节点
	Node* pNode = createNode(data);

	//将新节点插入到链表中
    pNode->pNext = pLink->pHead;
	pLink->pHead = pNode;

	pLink->count++;
	return LINK_OK;
}

7.显示

void showLink(Link * pLink)
{
	if(NULL == pLink)
	{
		return;
	}
	Node * pTmp = pLink->pHead;
	while(pTmp != NULL)
	{
		printf("id = %d name = %s\n",pTmp->data.id,pTmp->data.name);
		pTmp = pTmp->pNext;
	}
}

8.中间插入,在指定的位置插入元素,位置的编号从0开始,要插入的节点必须要找到要插入位置的前一个节点。

int insertItemLink(Link *pLink,int ioffset,data_t data)
{
	if(NULL == pLink||ioffset < 0||ioffset > pLink->count)
	{
		return LINK_ERROR;
	}
	//创建一个新节点
	Node* pNode = createNode(data);
	//找到要插入位置的前一个节点,用pTmp表示
	Node * pTmp = pLink->pHead;
	int i;
	for(i = 0;i<ioffset-1;i++)
	{
		pTmp = pTmp->pNext;
	}
	//头插
	if(0 == ioffset)
	{
		pushItemFront(pLink,data);
		return LINK_OK;
	}
	//插入
	pNode->pNext = pTmp->pNext;
	pTmp->pNext = pNode;

	pLink->count++;
	return LINK_OK;
}

9.销毁链表

void destroyLink(Link ** ppLink)
{
	if(NULL == ppLink ||NULL == *ppLink)
	{
		return;
	}
	Node * pDel = (*ppLink)->pHead;
	//释放一个一个节点
	while(pDel != NULL)
	{
		(*ppLink)->pHead = pDel->pNext;
		free(pDel);
		pDel = (*ppLink)->pHead;
	}
	//释放表的结构体
	free(*ppLink);
	*ppLink = NULL;	
}

10.删除指定位置元素,位置从0开始

int deleteItemLink(Link* pLink,int ioffset,data_t *pData)
{
	if(NULL == pLink||ioffset < 0||ioffset > pLink->count)
	{
    	return LINK_ERROR;
	}

	//pTmp是要删除的节点前一个节点
	Node* pTmp = pLink->pHead;
	int i;
	for(i = 0;i < ioffset-1; i++)
	{
		pTmp = pTmp-> pNext;
	}
	//pDel删除的节点
    Node* pDel = pTmp->pNext;
	if(NULL != pData)
	{  
	 *pData = pDel->data;
	}
	pTmp->pNext = pDel->pNext;
	free(pDel);
	pDel = NULL;
	pLink->count--;
	return LINK_OK;
}

11.按照id查找名字,如果没有找到,就返回NOT_FOUND

int findItemLink(Link* pLink,data_t* pData)
{
	if(NULL == pLink ||NULL == pData)
	{
		return LINK_ERROR;
	}
	//遍历链表,根据传进来的id一个一个去比较
	//如果相等了,就将name带出来
	Node* pTmp = pLink->pHead;
	while(pTmp != NULL)
	{
		if(pTmp->data.id == pData->id)
		{
			strcpy(pData->name,pTmp->data.name);
			return LINK_OK;
		}
		pTmp = pTmp->pNext;
	}
	return NOT_FOUND;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值