头文件
#ifndef _MYLINKLIST_H_
#define _MYLINKLIST_H_
typedef void LinkList;
/*
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode
{
LinkListNode* next;
};
*/
typedef struct _tag_LinkListNode
{
struct _tag_LinkListNode* next;
}LinkListNode;
LinkList* LinkList_Create();
void LinkList_Destroy(LinkList* list);
void LinkList_Clear(LinkList* list);
int LinkList_Length(LinkList* list);
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
LinkListNode* LinkList_Get(LinkList* list, int pos);
LinkListNode* LinkList_Delete(LinkList* list, int pos);
#endif
实现部分:
#include "linklist.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct _tag_linklist {
LinkListNode header;
int length;
}Tlinklist;
LinkList* LinkList_Create() {
Tlinklist *ret = NULL;
ret = (Tlinklist *)malloc(sizeof(Tlinklist));
if (ret == NULL)
{
return NULL;
}
memset(ret, 0, sizeof(Tlinklist));
//或者
//tem->length = 0;
//tem->header.next = NULL;
return ret;
}
void LinkList_Destroy(LinkList* list) {
if (list != NULL) {
free(list);
list = NULL;
}
return ;
}
//让链表恢复到初始化状态
void LinkList_Clear(LinkList* list) {
Tlinklist *Tlist = NULL;
if (list == NULL) {
return;
}
Tlist = (Tlinklist *)list;
Tlist->length = 0;
Tlist->header.next = NULL;
return ;
}
int LinkList_Length(LinkList* list) {
Tlinklist *Tlist = (Tlinklist *)list;
if (Tlist == NULL) {
printf("fun LinkList_Length() err");
return -1;
}
return Tlist->length;
}
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) {
int ret = 0, i = 0;
LinkListNode *current = NULL;
Tlinklist *tlist = NULL;
tlist = (Tlinklist *)list;
if (list == NULL || node == NULL || pos < 0) {
ret = -1;
printf("func LinkList_Insert() err: %d \n", ret);
return ret;
}
current = &(tlist->header); //让辅助指针变量指向链表的头部
for (i = 0; i < pos && (current->next != NULL); i++) {
current = current->next;
}
//1 让node连接后续节点
node->next = current->next; //用node->next = current可否?
//2 让前面的链表 连接新的node节点
current->next = node;
tlist->length++;
return 0;
}
LinkListNode* LinkList_Get(LinkList* list, int pos) {
int ret = 0, i = 0;
LinkListNode *current = NULL; //辅助指针变量
Tlinklist *tlist = NULL;
LinkListNode *tem = NULL;
tlist = (Tlinklist *)list;
if (list == NULL || pos < 0 || pos >= tlist->length) {
ret = -1;
printf("func LinkList_Insert() err: %d \n", ret);
return NULL;
}
current = &(tlist->header); //让辅助指针变量指向链表的头部
for (i = 0; i < pos && (current->next != NULL); i++) { //跳pos次
current = current->next;
}
tem = current->next;
return tem;
}
LinkListNode* LinkList_Delete(LinkList* list, int pos) {
int ret = 0, i = 0;
LinkListNode *current = NULL; //辅助指针变量
LinkListNode *tem = NULL; //辅助指针变量
Tlinklist *tlist = NULL;
tlist = (Tlinklist *)list;
if (list == NULL || pos < 0 || pos >= tlist->length) {
ret = -1;
printf("func LinkList_Insert() err: %d \n", ret);
return NULL;
}
current = &(tlist->header); //让辅助指针变量指向链表的头部
for (i = 0; i < pos && (current->next != NULL); i++) { //跳pos次
current = current->next;
}
tem = current->next; //缓存被删除的节点
//删除算法//连线
current->next = tem->next;
tlist->length--;
return tem; //业务节点的内存不是底层库分配的,返回被删节点地址,让上层应用去析构其空间
}
测试代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "linklist.h"
typedef struct Teacher {
LinkListNode node; //第一个域(第一个元素)
int age;
char name[64];
}Teacher;
int main() {
int ret = 0, len = 0, i = 0;
//创建一个线性表
LinkList* list = NULL;
Teacher t1, t2, t3, t4, t5;
t1.age = 31;
t2.age = 32;
t3.age = 33;
t4.age = 34;
t5.age = 35;
list = LinkList_Create();
if (list == NULL) {
printf("fun LinkList_Create() err:");
return;
}
len = LinkList_Length(list);
//实现具体算法和具体业务节点的分离
LinkList_Insert(list, (LinkListNode*)&t1, 0);
LinkList_Insert(list, (LinkListNode*)&t2, 0);
LinkList_Insert(list, (LinkListNode*)&t3, 0);
LinkList_Insert(list, (LinkListNode*)&t4, 0);
LinkList_Insert(list, (LinkListNode*)&t5, 0);
//遍历
for (i = 0; i < LinkList_Length(list); i++) {
Teacher *tem = (Teacher*)LinkList_Get(list,i);
if (tem != NULL) {
printf("tem->age:%d ", tem->age);
}
}
printf("\n");
//删除链表
while (LinkList_Length(list) > 0) {
Teacher *tem = (Teacher*)LinkList_Delete(list, 0); //从头号位置开始删,返回被删除的值
if (tem != NULL) {
printf("tem->age:%d ", tem->age);
}
}
LinkList_Destroy(list); //销毁链表
system("pause");
return;
}
链表优点:
无需一次性定制链表的容量
插入和删除无需移动数据元素
缺点:
获取元素必须保存后继元素的位置信息
获取指定数据的元素操作需要顺序访问之前的元素
学好链表的关键
1 指针指向谁就把谁的地址赋给指针
2 分清楚 链表的操作逻辑和 辅助指针变量之间的关系
注:具体详情请关注传智播客讲师——传智扫地僧,在此仅作笔记使用