目录
前置条件:
1.结点的结构体:
typedef struct node{
void *data;
struct node *next;
}NODE_T;
结构体的内容分为数据域和指针域,其中数据域定义为void*的指针,目的是使结点可以接受任意类型的数据。这个数据只需要在堆区开辟一个空间来存放,然后把堆区的地址传送给data即可。(具体见下文代码)
2.该链表是带头结点的单向链表,头结点不放数据
带头结点方便进行数据的操作,计算结点个数时不包括头结点,链表的第一个位置指带有数据的第一个结点。但在释放整条链表时也要释放头结点。
函数声明:
/*
函数名:List_init
函数功能:创建链表头结点
函数参数: 无
函数返回值:头结点地址
*/
NODE_T *List_init();
/*
函数名:List_add
函数功能:添加链表结点
函数参数: head--链表头结点
data--添加的数据
函数返回值:无
*/
void List_add(NODE_T *head,void *data);
/*
函数名:getListCount
函数功能:计算结点个数
函数参数: head--链表头结点
函数返回值:结点个数
*/
int getListCount(NODE_T *head);
/*
函数名:findListByPos
函数功能:根据位置查找结点
函数参数: head--链表头结点
pos--位置
函数返回值:查找到的结点
*/
void *findListByPos(NODE_T *head,int pos);
/*
函数名:InsertListByPos
函数功能:在某个位置插入结点
函数参数: head--链表头结点
pos--位置
data--插入的数据
函数返回值:1--成功,0--失败
*/
int insertListByPos(NODE_T *head,int pos,void *data);
/*
函数名:DeleteListBYPos
函数功能:删除某个位置的结点
函数参数: head--链表头结点
pos--位置
函数返回值:1--成功,0--失败
*/
int deleteListByPos(NODE_T *head,int pos);
/*
函数名:freeList
函数功能:删除整条链表(包括头结点)
函数参数: head--链表头结点
函数返回值:头结点
*/
void *freeList(NODE_T *head);
函数实现:
NODE_T *list_init()
{
NODE_T *head = NULL;
head = (NODE_T*)malloc(sizeof(NODE_T));
if(!head)
{
printf("开空间失败!\n");
exit(0);
}
memset(head,0x0,sizeof(NODE_T));//初始化结点
head->next = NULL;
return head;
}
void list_add(NODE_T *head,void *data)
{
//新建一个结点
NODE_T *newnode = NULL;
newnode = (NODE_T*)malloc(sizeof(NODE_T));
if(!newnode)
{
printf("开空间失败!\n");
exit(0);
}
memset(newnode,0x0,sizeof(NODE_T));
newnode->next = NULL;
//赋值
newnode->data = data;
//找到尾结点
while(head->next)
{
head = head->next;
}
//添加结点
head->next = newnode;
}
int getListCount(NODE_T *head)
{
int count = 0;
while(head->next)
{
count ++;
head = head->next;
}
return count;
}
void *findListByPos(NODE_T *head,int pos)
{
if(pos > getListCount(head))
{
printf("位置大于总结点数。\n");
return NULL;
}
while(pos>0)
{
head = head->next;
pos--;
}
return head->data;
}
int insertListByPos(NODE_T *head,int pos,void *data)
{
//找到插入位置(准确说是找到pos位置的结点的前一个)
NODE_T *newnode =NULL;
NODE_T *q = head->next;
if(pos < 1)
{
printf("插入的位置要>=1\n");
return 0;
}
if(pos > getListCount(head))
{
printf("插入的位置大于总结点数。\n");
return 0;
}
while(pos>1)
{
head = q;
q = head->next;
pos--;
}
//新建一个结点
newnode = (NODE_T*)malloc(sizeof(NODE_T));
if(!newnode)
{
printf("开空间失败!\n");
exit(0);
}
memset(newnode,0x0,sizeof(NODE_T));
newnode->next = NULL;
newnode->data = data;
//插入
head->next = newnode;
newnode->next = q;
return 1;
}
int deleteListByPos(NODE_T *head,int pos)
{
//找到这个位置(其实也是找到前一个位置)
NODE_T *q = head->next;
if(pos < 1)
{
printf("删除位置要>=1\n");
return 0;
}
if(pos > getListCount(head))
{
printf("删除位置大于总结点数。\n");
return 0;
}
while(pos>1)
{
head = q;
q = head->next;
pos--;
}
//删除
head->next = q->next;
free(q->data);
free(q);
return 1;
}
void *freeList(NODE_T *head)(比较简单的写法)
{
NODE_T *p = NULL;
//每次找到最后一个位置,释放
while(head->next)//循环条件即还存在数据结点
{
p = head;
//调用删除单个结点和统计结点个数的函数,每次都删除最后一个结点。
deleteListByPos(p,getListCount(p));
}
//释放头结点
free(head->data);
free(head);
head = NULL;
return NULL;
}
注意,释放结点的时候要先释放结点的数据,再释放整个结点。
C语言链表:函数内部对头结点head的修改为什么不会改变外面的head?