基本概念
链式存储定义:
为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后继的信息。
表头结点:
链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息。
数据结点:
链表中代表数据元素的结点,包含指向下一个数据元素的指针和数据元素的信息。
尾结点:
链表中的最后一个数据结点,其下一元素指针为空,表示无后继。
链表技术领域推演
链表链式存储_api实现分析:
在C语言中可以用结构体来定义链表中的指针域,链表中的表头结点也可以用结构体实现;
带头结点、位置从0的单链表;
返回链表中第3个位置处,元素的值。
linkListNode* linkList_Get(linkList* list, int pos)
{
if (list == NULL || pos < 0 || pos >= linkList_Length(list)) {
return NULL;
}
TlinkList *tList = NULL;
tList = (TlinkList *)list;
linkListNode *cur = NULL;
cur = &(tList->header);
for (int i = 0; i < pos; ++i) {
cur = cur->next;
}
return cur->next;
}
返回第三个位置的。
移动pos次以后,当前指针指向哪里?
答案:指向位置2,所以需要返回 ret = current->next。
备注:循环遍历时
遍历第1次,指向位置0;
遍历第2次,指向位置1;
遍历第3次,指向位置2;
遍历第n次,指向位置n-1。
删除元素:
代码实例:
linklist.h
#ifndef _MYlinkLIST_H_
#define _MYlinkLIST_H_
typedef void linkList;
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
linklist.cpp
#include#include #include "linklist.h" using namespace std; typedef void linkList; typedef struct _tag_linkList { linkListNode header; int length; }TlinkList; linkList* linkList_Create() { TlinkList *tmp = NULL; tmp = (TlinkList *)malloc(sizeof(TlinkList)); if (tmp == NULL) { printf("function linkList_Create() err.n"); return NULL; } memset(tmp, 0, sizeof(TlinkList)); // 初始化为空链表 return tmp; } void linkList_Destroy(linkList* list) { if (list == NULL) { return; } free(list); return; } void linkList_Clear(linkList* list) { if (list == NULL) { return; } TlinkList *tList = NULL; tList = (TlinkList *)list; tList->header.next = NULL; tList->length = 0; return; } int linkList_Length(linkList* list) { if (list == NULL) { return -1; } TlinkList *tList = NULL; tList = (TlinkList *)list; return tList->length; } int linkList_Insert(linkList* list, linkListNode* node, int pos) { if (list == NULL || node == NULL || pos < 0) { return -1; } TlinkList *tList = NULL; tList = (TlinkList *)list; linkListNode *cur = NULL; cur = &(tList->header); // 对pos的容错处理,如果pos过大,改为最后面 if (pos > linkList_Length(list)) { pos = linkList_Length(list); } // 移动到需要插入的位置 for (int i = 0; i < pos; ++i) { cur = cur->next; } // 插入 node->next = cur->next; cur->next = node; ++tList->length; return 0; } linkListNode* linkList_Get(linkList* list, int pos) { if (list == NULL || pos < 0 || pos >= linkList_Length(list)) { return NULL; } TlinkList *tList = NULL; tList = (TlinkList *)list; linkListNode *cur = NULL; cur = &(tList->header); for (int i = 0; i < pos; ++i) { cur = cur->next; } return cur->next; } linkListNode* linkList_Delete(linkList* list, int pos) { if (list == NULL || pos < 0 || pos >= linkList_Length(list)) { return NULL; } TlinkList *tList = NULL; tList = (TlinkList *)list; linkListNode *cur = NULL; cur = &(tList->header); for (int i = 0; i < pos; ++i) { cur = cur->next; } linkListNode *ret = NULL; ret = cur->next; // 删除结点 cur->next = ret->next; --tList->length; return ret; }
main.cpp
#include#include #include "linklist.h" using namespace std; typedef struct _Student { linkListNode node; char name[32]; int age; }Student; int main() { Student s1, s2, s3, s4, s5, s6; s1.age = 21; s2.age = 22; s3.age = 23; s4.age = 24; s5.age = 25; s6.age = 26; // 创建链表 Student *list = (Student *)linkList_Create(); // 插入结点 linkList_Insert(list, (linkListNode *)&s1, 0); linkList_Insert(list, (linkListNode *)&s2, 0); linkList_Insert(list, (linkListNode *)&s3, 0); linkList_Insert(list, (linkListNode *)&s4, 0); linkList_Insert(list, (linkListNode *)&s5, 0); linkList_Insert(list, (linkListNode *)&s6, 3); // 遍历链表 for (int i = 0; i < linkList_Length(list); ++i) { Student *tmp = (Student *)linkList_Get(list, i); if (tmp == NULL) { return 0; } printf("age: %dn", tmp->age); } // 删除链表结点 while (linkList_Length(list)) { Student *tmp = (Student *)linkList_Delete(list, 0); if (tmp == NULL) { return 0; } printf("age: %dn", tmp->age); } linkList_Destroy(list); return 0; }
优点:
- 无需一次性定制链表的容量;
- 插入和删除操作无需移动数据元素。
缺点:
- 数据元素必须保存后继元素的位置信息;
- 获取指定数据的元素操作需要顺序访问之前的元素。
工程详情:Github



