C语言单链表(实现全部函数)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*

     要求编写的函数如下:
	 InitList(Node *pHead)    *pHead必须具有,单链表必须有head。如果没有用不了,具有操作意义                           :初始化单链表*
	 DestroyList(Node *pHead)                            :销毁单链表*
	 ClearList(Node *pHead)  //除了头结点都删除掉                            :清空单链表
	 ListEmpty(Node *pHead)                              :判断单链表是否为空
	 ListLength(Node *pHead)                             :获取单链表中节点个数
	 GetElem(Node *pHead, int index, Node *pElem)Node *pHead头指针。index指定索引  Node *pElem指定节点元素   :获取单链表中指定的节点
	 LocateElem(Node *pHead, Node *pElem)                :给定节点获取单链表中第一次出现的索引位置
	 ListInsert(Node *pHead, int index, Node *pElem)     :将节点插入单链表中指定位置*
	 ListDelete(Node *pHead, int index, Node *pElem)     :从单链表中指定位置删除节点*
	 ListTraverse(Node *pHead)                           :遍历单链表中所有节点*

*/
/************************************************************************/

#define KLen 30//单链表的长度

int g_iCount = 0;
/*编写一个单链表,每个节点就是一条信息,每条信息包含的内容如下:
	 姓名:name
	 联系方式:phone*/
typedef struct tagNode
{
	char name[KLen];
	char phone[KLen];

	struct tagNode *pNext;
}Node;//Node类型

int InitList(Node **pHead);
void ClearList(Node *pHead);
void DestroyList(Node *pHead);
int ListEmpty(Node *pHead);
int ListLength(Node *pHead);
void ListTraverse(Node *pHead);
int GetElem(Node *pHead, int index, Node *pElem);
int LocateElem(Node *pHead, Node *pElem);
int ListInsert(Node *pHead, int index, Node *pElem);
int ListDelete(Node *pHead, int index, Node *pElem);

int main(void)
{
	//单元测试
	Node *pList = NULL;
	Node node1 = {"Jim", "1234", NULL};
	Node node2 = {"Merry", "4321", NULL};
	Node node3 = {"James", "3456", NULL};
	Node node4;
	InitList(&pList);
	
	ListInsert(pList, 0, &node1);
	printf("%d \n", ListLength(pList));
	ListInsert(pList, 1, &node2);
	ListInsert(pList, 1, &node3);
	printf("%d \n", ListEmpty(pList));
	printf("%d \n", ListLength(pList));
	ListTraverse(pList);

	ListDelete(pList, 2, NULL);
	printf("%d \n", ListLength(pList));
	ListTraverse(pList);

	DestroyList(pList);
	
	system("pause");
	return 0;
}

int InitList(Node **pHead)//为什么使用二重指针,因为要传进去,又能拿出内存出来
{
	*pHead = (Node *)malloc(sizeof(Node));//为什么要强制转换成(Node *),因为不转换会成为void *类型的
	if(*pHead == NULL)//一级指针,先把head+next都设置成NULL
	{
		return 0;
	}
	(*pHead)->pNext = NULL;//单链表的结构 [值(value)  地址(pNext )]===一个元素
	return 1;//设置初始化后,返回1
}

void ClearList(Node *pHead)//注意,不清空头结点.
{
	Node *pCurrentNode = NULL;
	Node *pNextNode = NULL;
	if(pHead->pNext != NULL)//如果头结点的next不等于null的话,意思是头结点的下一个元素不为null的话,
	{
		pCurrentNode = pHead->pNext;//就赋值
		while(pCurrentNode != NULL)//只要有值,就一直循环
		{
			pNextNode = pCurrentNode->pNext;//赋值
			free(pCurrentNode);//释放内存
			pCurrentNode = pNextNode;//再找head的下下个来做
		}
	}
}

void DestroyList(Node *pHead)
{
	ClearList(pHead);//清空除了头结点的
	free(pHead);//释放内存
	pHead = NULL;//然后头结点也没了
}

int ListEmpty(Node *pHead)
{
	/*if(pHead->pNext == NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}*/

	if(g_iCount == 0)//如果count为0的话,代表是为空,就返回是的1
	{
		return 1;
	}
	return 0;
}

int ListLength(Node *pHead)
{
	return g_iCount;
}

void ListTraverse(Node *pHead)//遍历
{
	Node *pCurrentNode = pHead->pNext;//head的下一个元素
	while(pCurrentNode != NULL)//head的下一个元素不为null
	{
		printf("姓名:%s   ", pCurrentNode->name);//输出输出
		printf("电话:%s   ", pCurrentNode->phone);
		printf("\n");
		pCurrentNode = pCurrentNode->pNext;//在指向head的下一个元素的下一个元素,一直循环到没有下一个元素为止
	}
	printf("\n\n");
}

int GetElem(Node *pHead, int index, Node *pElem)
{
	int count = 0;
	if(index < 0 || index > g_iCount)//如果索引index小于0或者单链表长度小于索引的长度
	{
		return 0;
	}
	Node *pCurrentNode = pHead;
	while(pCurrentNode != NULL)
	{
		if(count == index)//如果找到了就赋值给pElem,然后输出
		{
			pElem = pCurrentNode;
			return 1;
		}
		count++;
		pCurrentNode = pCurrentNode->pNext;//找不到。呵呵。继续循环直到找到为止
	}
	return 1;
}

int LocateElem(Node *pHead, Node *pElem)
{
	int index = 1;
	Node *pCurrentNode = pHead->pNext;
	while(pCurrentNode != NULL)
	{
		if(!strcmp(pCurrentNode->name, pElem->name)&& !strcmp(pCurrentNode->phone, pElem->phone))//看是不是相等函数,看name+phone与传入的是否相等
		{//
			return index;
		}
		pCurrentNode = pCurrentNode->pNext;//继续next
		index++;
	}

	return -1;
}

int ListInsert(Node *pHead, int index, Node *pElem)
{
	int count = 0;
	Node *pNode = NULL;
	Node *pCurrentNode = NULL;
	if(index < 0 || index > g_iCount)
	{
		return 0;
	}
	pNode = (Node *)malloc(sizeof(Node));//申请内存(Node *)强制转换成这个,不然会返回无类型.void *.
	if(pNode == NULL)
	{
		return 0;
	}
	//拷贝
	strcpy(pNode->name, pElem->name);
	strcpy(pNode->phone, pElem->phone);

	pCurrentNode = pHead;
	while(pCurrentNode != NULL)
	{
		if(count == index)//0==0
		{
			/*这段话的根本意思是:0代表head的下一个位置。也就是1.因为head是固定的
			保存head指向下一个结点的指针。head的下一个元素是要放进来的哪个元素
			然后是把放进去的哪个元素的next指向原来的1的位置上的元素
			*/
			//1. 将当前节点的next指针保存
			Node *pTemp = pCurrentNode->pNext;
			//2. 让当前节点的next指针指向申请的内存
			pCurrentNode->pNext = pNode;
			//3. 将保存的next指针赋值给新节点的next指针
			pNode->pNext = pTemp;
			g_iCount++;//因为放进来一个,所以++
			return 1;
		}
		count++;
		pCurrentNode = pCurrentNode->pNext;//如果没有找到要插入的位置,继续next
	}
	return 1;
}

int ListDelete(Node *pHead, int index, Node *pElem)//删除节点
{
	int count = 0;
	Node *pCurrentNode = pHead;
	Node *pPreNode = NULL;
	if(index <= 0 || index > g_iCount)
	{
		return 0;
	}

	
	while(pCurrentNode != NULL)
	{
		if(count == index)
		{
			
			//1. 使currentNode的上一个节点指向currentNode的下一个节点
			pPreNode->pNext = pCurrentNode->pNext;
		
			if(pElem != NULL)
			{
				//将要删除的节点数据拷贝出来
				strcpy(pElem->name, pCurrentNode->name);
				strcpy(pElem->phone, pCurrentNode->phone);
			}
			

			//2. 删除currentNode指向的节点
			free(pCurrentNode);
			g_iCount--;//删除一个节点,所以要--1
			return 1;
		}
		count++;
		pPreNode = pCurrentNode;
		pCurrentNode = pCurrentNode->pNext;
	}
	return 1;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贵哥的编程之路(热爱分享)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值