C语言实现单链表的初始化及增删改查
文件组织
main.c
//注意:linkList为头节点,头节点只是为了后面操作方便。其数据域无意义,但是头节点数据域通常保存链表长度,头指针指向第一个节点。
#include "test.h"
//初始化链表
void InitLinkList(LinkList * linkList,ElementType * dataArray,int length);
//插入节点
void InsertLinkList(LinkList * linkList,int pos,ElementType element);
//打印链表
void PrintLinkList(LinkList * linkList);
//判断链表是否为空
int IsLInkListEmpty(LinkList * linkList);
//删除并返回指定位置的节点
ElementType DeleteLinkListElement(LinkList * linkList,int pos);
//清空链表
void ClearLinkList(LinkList * linkList);
ElementType dataArray[] = {
{1,"侠客行"},
{2,"将进酒"},
{3,"神来之笔"},
{4,"青莲剑歌"}
};
int main()
{
TestLinkList();
return 0;
}
void TestLinkList(){
LinkList linkList;
linkList.length = 0;//初始化链表长度为0
InitLinkList(&linkList,dataArray,sizeof(dataArray)/sizeof(dataArray[0]));
PrintLinkList(&linkList);
//下面进行插入节点
ElementType element;
element.id = 5;
element.name = (char *)malloc(8); //一个汉字占2或3个字节
//strcpy是一种C语言的标准库函数,strcpy把含有'\0'结束符的字符串复制到另一个地址空间,返回值的类型为char*。
strcpy(element.name,"剑仙李白");
InsertLinkList(&linkList,5,element);
printf("插入新节点后:\n");
PrintLinkList(&linkList);
printf("是否为空? %d\n",IsLInkListEmpty(&linkList));
printf("删除第3个元素后:\n");
DeleteLinkListElement(&linkList,3);
PrintLinkList(&linkList);
printf("清空链表后:\n");
ClearLinkList(&linkList);
PrintLinkList(&linkList);
}
test.c
#include "test.h"
//初始化链表
void InitLinkList(LinkList * linkList,ElementType * dataArray,int length)
{
for (int i = 0;i<length;i++){
InsertLinkList(linkList,i+1,dataArray[i]); //注意:这里是在pos位置处插入,故从1开始计数.相反,若是index,则为0开始.
}
}
//插入元素
void InsertLinkList(LinkList * linkList,int pos,ElementType element){
//1.创建空节点并为数据域赋值
//用malloc创建空节点空间,(Node *)强制类型转换为指向Node型的指针
Node * node = (Node *)malloc(sizeof(Node));
node->data = element;
node->next = NULL;
//2.找到插入位置的节点
//如果插入位置为第一个
//注意:linkList为头节点,头节点只是为了后面操作方便。其数据域无意义,但是头节点数据域通常保存链表长度,头指针指向第一个节点。
if (pos == 1){
linkList->next=node;
linkList->length++;
return;
}
//如果不是插入第一个
Node * currNode = linkList->next;
for (int i = 1;currNode && i<pos-1;i++){
currNode = currNode->next;
}
if (currNode){
node->next = currNode->next;
currNode->next = node;
linkList->length++;
}
}
void PrintLinkList(LinkList * linkList){
Node * currentNode = linkList->next;
if (!currentNode){
printf("LinkList is NULL.\n");
linkList->length=0;
}
for(int i=0;i<linkList->length;i++){
printf("%d技能 %s.\n",currentNode->data.id,currentNode->data.name);
currentNode = currentNode->next;
}
}
//.h中有宏定义,TRUE=1,FALSE=0
int IsLInkListEmpty(LinkList * linkList){
return linkList->length == 0 ? TRUE : FALSE;
}
ElementType DeleteLinkListElement(LinkList * linkList,int pos){
ElementType element; //被删除的元素
element.id=-99999; //赋一个不可能的值,来判断是否删除成功
Node * node = NULL;
if (pos == 1){ //如果删除第一个节点
node = linkList->next; //头节点
if (node){
element = node->data; //保存被删除的元素
linkList->next = node->next;
free(node);
linkList->length--;
}
return element;
}
//如果不是删除第一个节点
Node * preNode; //前缀节点
node = linkList->next;
for (int i=1;node && i<pos;i++){
preNode = node;
node = node->next;
}
if (node){
element = node->data;
preNode->next = node->next;
free(node);
linkList->length--;
}
return element;
}
//清空链表
void ClearLinkList(LinkList * linkList){
Node * node = linkList->next;
Node * nextNode; //定义两个指针来删除链表
while(node) {
nextNode = node->next; //先记录当前节点的下一个节点,以便释放当前节点的内存
free(node);
node = nextNode;
}
linkList->next = NULL;
linkList->length = 0;
}
test.h
test.h
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
//定义节点的数据域ElementType
typedef struct {
int id;
char * name;
}ElementType;
//加上指针域,构成节点
typedef struct Node{
ElementType data;
struct Node * next;
}Node;
//定义名为LinkList的头节点!!
//注意:linkList为头节点,头节点只是为了后面操作方便。其数据域无意义,但是头节点数据域通常保存链表长度,头指针指向第一个节点。
typedef struct LinkList{
Node * next;
int length;
}LinkList;
#endif // TEST_H_INCLUDED
运行结果如下: