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

举报
陈业贵 发表于 2022/05/13 23:44:06 2022/05/13
【摘要】 #include <stdio.h> #include <stdlib.h> #include <string.h> /* 要求编写的函数如下: In...
#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;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262

文章来源: blog.csdn.net,作者:贵哥的编程之路(热爱分享),版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_37805832/article/details/124744060

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。