基本数据结构――单链表

文章简介:基本数据结构系列讲解之单链表(附源码)

 

1.介绍链表结构

链表中的每个结点都应包括以下两个部分。

(1)数据部分:保存结点的数据

(2)地址部分:保存下一结点地址

链表的头指针指向链表结构的第一个结点,依次直到最后一个结点,最后一个结点的地址部分一般放一个空指针NULL。

在链表结构中,通过指针实现结点的逻辑相邻,而逻辑相邻的结点在内存中不一定相邻,所以使用链表时不需要事先分配一块存储空间,程序员通过malloc函数动态分配结点的存储空间,当删除某结点时,再用free函数释放空间。

链表结构的缺点是浪费存储空间,因为每一个结点都需要额外存储一个指针变量。

链表有单链表、双向链表、循环链表等几类,本文主要讲解单链表的相关操作。

 

2.定义链表及数据元素类型

本程序的功能是通过单链表存储学生信息,学生信息包括:学号key,姓名name,年龄age。学生信息作为数据元素类型Data,链表数据结构CLType,在CLType内用Data类型变量表示数据部分,用链表结构的指针指向下一结点。

typedef struct { 	char key[10]; 	char name[15]; 	int age; }Data;  typedef struct Node { 	Data nodeData; 	struct Node *nextNode; }CLType;


3.添加结点

添加结点即在链表的尾部加入结点,操作步骤如下:

(1)分配内存空间,用以保存将要添加的结点;

(2)从头指针head开始检查,找到最后一个结点;

(3)将表尾结点的地址设置为新增结点地址;

(4)将新增结点的地址设置为NULL。

程序使用malloc为新增结点申请内存空间。

CLType *CLAddEnd(CLType *head,Data nodeData) { 	CLType *node,*temp; 	if(!(node=(CLType*)malloc(sizeof(CLType)))) 	{ 		printf("内存申请失败!\n"); 		return NULL; 	} 	else 	{ 		node->nodeData=nodeData; 		node->nextNode=NULL; 		if(head=NULL) 		{ 			head=node; 			return head; 		} 		temp=head; 		while(temp!=NULL) 		{ 			temp=temp->nextNode; 		} 		temp->nextNode=node; 		return head; 	} }

4.插入头结点

在链表首部插入结点,步骤如下:

(1)分配内存空间,用以保存新增结点;

(2)将新增结点指向head所指的结点;

(3)使head指向新增结点。 


CLType *CLAddFist(CLType *head,Data nodeData) { 	CLType *node; 	if(!(node=(CLType *)malloc(sizeof(CLType)))) 	{ 		printf("内存分配失败!\n"); 		return NULL; 	} 	else 	{ 		node->nodeData=nodeData; 		node->nextNode=head; 		head=node; 		return head; 	} }


5.查找结点

通过关键字key来查找结点,使用strcmp函数比较查找,找到后返回该结点指针。

 

CLType *CLFindNode(CLType *head,char *key) { 	CLType *temp; 	temp=head; 	while(temp) 	{ 		if(strcmp(temp->nodeData.key,key)==0) 		{ 			return temp; 		} 	temp=temp->nextNode; 	} 	return NULL; }


6.插入结点

链表中插入结点步骤如下:

(1)分配内存空间,用以保存新的结点;

(2)找到要插入的位置;

(3)将插入的结点指向插入位置指向的结点,插入位置指向新增结点。

本程序使用关键字找到要插入的位置。


CLType *CLInsertNode(CLType *head,char *key,Data nodeData) { 	CLType *node,*temp; 	if(!(node=(CLType *)malloc(sizeof(CLType)))) 	{ 		printf("内存申请失败!\n"); 		return 0; 	} 	node->nodeData=nodeData; 	temp=CLFindNode(head,key); 	if(temp) 	{ 		node->nextNode=temp->nextNode; 		temp->nextNode=node; 	} 	else 	{ 		printf("插入的位置不对!\n"); 		free(node); 	} 	return head; }

7.删除结点

链表中删除结点的操作如下:

(1)找到要删除的目标结点;

(2)使该结点的前一个结点指向后一个结点;

(3)删除该结点。

 

int CLDeleteNode(CLType *head,char *key) { 	CLType *node,*temp; 	temp=head; 	node=head; 	while(temp) 	{ 		if(strcmp(temp->nodeData.key,key)==0) 		{ 			node->nextNode=temp->nextNode; 			free(temp); 			return 1; 		} 		else 		{ 			node=temp; 			temp=temp->nextNode; 		} 	} 	return 0; }


8.计算链表长度

由于链表不是在内存中不是连续存储的,所以需要遍历整个链表才能计算出链表长度。

 

int CLLength(CLType *head) { 	int len=0; 	CLType *temp; 	temp=head; 	while(temp) 	{ 		len++; 		temp=temp->nextNode; 	} 	return len; }


9.显示所有结点


void CLAllNode(CLType *head) { 	CLType *temp; 	Data nodeData; 	temp=head; 	printf("当前共有%d个结点。链表所有数据如下:\n",CLLength(head)); 	while(temp) 	{ 		nodeData=temp->nodeData; 		printf("结点(%s,%s,%d)\n",nodeData.key,nodeData.name,nodeData.age); 		temp=temp->nextNode; 	} }


 

本文源代码:单链表操作.cpp

 

 

 

 


你可能感兴趣的:(数据结构,c,单链表)