数据结构链式线性表实现
/*****************************************************
> File Name : test.c
> Author : xboss
> Mail : 2366006417@qq.com
> Created Time: 2020年06月13日 星期六 15时14分59秒
*****************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
typedef void LinkList;
//小链表节点,需要上层去包含此节点例如
/*
typedef struct teacher_message
{
LinkListNode node; //让老师对象节点去包含小节点,并且老师节点地址和小链表地址相同,没有偏移量
int age;
char name[];
}Teacher;
*/
typedef struct _tag_LinkListNode
{
struct _tag_LinkListNode *next;
}LinkListNode; //小链表节点,需要上层应用去包含此节点
typedef struct _tag_LinkList
{
LinkListNode head; //链表头部
int length; //链式线性表的当前的长度(到底有多少个子节点)
}TLinkList;
/***************************************
function :链式线性表创建
parameter:无
return :链式线性表数据对象的首地址
****************************************/
LinkList* LinkList_Create()
{
TLinkList *tep = (TLinkList *)malloc(sizeof(LinkList));
//malloc后置0
memset(tep,0,sizeof(LinkList));
tep->length = 0;
tep->head.next = NULL;
return tep;
}
/***************************************
function :链式线性表销毁
parameter:链式线性表数据对象的首地址
return :无
****************************************/
void LinkList_Destory(LinkList *list)
{
if(list != NULL)
{
free(list);
list = NULL;
}
return ;
}
/***************************************
function :链式线性表清除(让链表回到初始值)
parameter:链式线性表数据对象的首地址
return :无
****************************************/
void LinkList_Clear(LinkList *list)
{
TLinkList *tlist = NULL;
if(list == NULL)
{
return ;
}
tlist = (TLinkList *)list;
tlist->length = 0;
tlist->head.next = NULL;
return ;
}
/***************************************
function :链式线性表长度计算
parameter:链式线性表数据对象的首地址
return :链式线性表长度
****************************************/
int LinkList_Length(LinkList *list)
{
TLinkList *tlist = NULL;
if(list == NULL)
{
return -1;
}
tlist = (TLinkList *)list;
return tlist->length;
}
/***************************************
function :链式线性表数据插入
parameter:链式线性表数据对象的首地址,插入的链表子节点,插入的位置
return :成功返回0,失败返回-1
****************************************/
int LinkList_Insert(LinkList *list,LinkListNode *node,int pos)
{
int ret = 0,i= 0;
TLinkList *tlist = NULL;
LinkListNode *current = NULL; //辅助指针变量
if(list == NULL || node == NULL || pos < 0 )
{
ret = -1;
printf("LinkList_Insert err:%d\r\n",ret);
return ret;
}
tlist = (TLinkList *)list;
current = &(tlist->head); //辅助指针指着链表头部
for(i = 0;i<pos && current->next != NULL;i++)//让辅助指针跳到插入位置的前一个位置
{
current = current->next;
}
node->next = current->next; //让node节点连接后续链表
current->next = node; //让前面的链表连接新的node节点
tlist->length++; //长度加1
return 0;
}
/***************************************
function :获取链式线性表指定位置上的数据
parameter:链式线性表数据对象的首地址,获取的位置
return :获取到数据位置的地址
****************************************/
LinkList* LinkList_Get(LinkList *list,int pos)
{
int ret = 0,i= 0;
TLinkList *tlist = NULL;
LinkListNode *current = NULL; //辅助指针变量
if(list == NULL || pos < 0 )
{
ret = -1;
printf("LinkList_Insert err:%d\r\n",ret);
return NULL;
}
tlist = (TLinkList *)list;
current = &(tlist->head); //辅助指针指着链表头部
for(i = 0;i<pos && current->next != NULL;i++)//让辅助指针跳到插入位置的前一个位置
{
current = current->next;
}
return current->next;
}
/***************************************
function :链式线性表删除指定位置的数据
parameter:链式线性表数据对象的首地址,指定位置pos
return :需要删除数据位置的地址
****************************************/
LinkList* LinkList_Delete(LinkList *list,int pos)
{
int ret = 0,i= 0;
TLinkList *tlist = NULL;
LinkListNode *current = NULL; //辅助指针变量
LinkListNode *tem = NULL;
if(list == NULL || pos < 0 )
{
ret = -1;
printf("LinkList_Insert err:%d\r\n",ret);
return NULL;
}
tlist = (TLinkList *)list;
current = &(tlist->head); //辅助指针指着链表头部
for(i = 0;i<pos && current->next != NULL;i++)//让辅助指针跳到插入位置的前一个位置
{
current = current->next;
}
tem = current->next; //缓存被删除节点的位置
current->next = tem->next; //连接节点
tlist->length--; //长度减1
return tem;
}
typedef struct teacher_message
{
LinkListNode node; //让老师对象节点去包含小节点,并且老师节点地址和小链表地址相同,没有偏移量
int age;
char name[64];
}Teacher;
int main(void)
{
Teacher t1,t2,t3;
int ret = 0;
int i = 0;
t1.age = 22;
strcpy(t1.name,"黎明");//向name中拷贝字符串,只能通过strcpy函数完成
t2.age = 13;
strcpy(t2.name,"小刚学长");
t3.age = 14;
strcpy(t3.name,"小东");
LinkList* list = NULL;
//创建顺序线性表
list = LinkList_Create();
if(list == NULL)
{
printf("LinkList_Create\r\n");
exit(1);
}
//向顺序线性表插入数据
ret = LinkList_Insert(list,(LinkListNode *)&t1,0);
ret = LinkList_Insert(list,(LinkListNode *)&t2,0);
ret = LinkList_Insert(list,(LinkListNode *)&t3,0);
//遍历顺序线性表中的元素
for(i = 0;i<LinkList_Length(list);i++)
{
Teacher *temp = (Teacher *)LinkList_Get(list,i);
if(temp == NULL)
{
printf("error");
exit(1);
}
printf("temp->age= %d\r\n",temp->age);
printf("temp->name= %s\r\n",temp->name);
}
//删除顺序线性表中的元素
LinkList_Delete(list,0);
Teacher *temp = (Teacher *)LinkList_Get(list,0);
printf("temp->age= %d\r\n",temp->age);
printf("temp->name= %s\r\n",temp->name);
return 0;
}
1、代码运行效果
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/38ce4e6c5e073df79738c9804d448387.png)
2、链表发展的过程(本文采用第三种,让子节点(例如本文的LinkListNode对象)和业务节点(上层应用的对象,例如本文的Teacher对象)在同一个地址,没有偏移量)
typedef struct teacher_message
{
LinkListNode node; //让老师对象节点去包含小节点,并且老师节点地址和小链表地址相同,没有偏移量
int age;
char name[64];
}Teacher;
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/16bda259e6619671d1b293a524faf153.png)
3、插入节点示意图(算法中的 LinkList_Insert函数实现原理)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e4aa668b8183ce85fb054d1c46adff24.png)
4、删除节点示意图(算法中的 LinkList_Delete函数实现原理)(使用两个辅助指针)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9fd6c6d8e169c0cc35fe00ed3a29e3ba.png)