链表系列
来源:互联网 发布:vb.net 源码 编辑:程序博客网 时间:2024/06/06 20:27
链表
前言:将之前学习的链表方面的知识做一下整理,方便以后复习。
链表中的个对象按照线性顺序排列,数组的线性顺序是由数组下标决定,链表的顺序是由对象里的指针决定。链表为动态集合提供了简单而灵活的表示方法。
基本上一个单向链表包括的操作有
- 链表的创建
- 链表的销毁
- 链表的清空
- 获取链表长度
- 链表中插入元素
- 链表中删除元素
- 按位置获取链表中的元素
接下来实现以上单向链表操作:
在之前,需要做一些准备工作,链表中要用到一些结构来存储链表信息。考虑到链表通用性,于是将链表结构与具体数据进行分离的设计,使同一套链表的API能够用于大部分数据链表处理。
typedef void LinkList;typedef struct _LinkListNode{ struct _LinkListNode* next;}LinkListNode;
如果链表节点这样设计,那么数据如何存储?
例如,如何将下面的数据存储到上述链表中,
typedef struct _Student{ char name[40]; int age;}Student;
对此,可以在Student中添加LinkListNode元素,将Student改造成新的结构体,
typedef struct _Student{ LinkListNode node; char name[20]; int age;}Student;
可以通过指针的强制转换,实现Student和LinkListNode的相互转换。
到目前为止,实际上已经实现了具体数据与链表API的解耦合。初此之外,还需要一个结构体表示链表的头,结构需包含链表的长度、LinkListNode型的变量来指向链表的第一个元素。于是,结构体如下:
typedef struct _LinkList{ LinkListNode header; int length;}HLinkList;
实际上这个数据结构做为内部结构可以被隐藏,外界无法知道内部实现。完成这些准备工作之后,就可以开始单向链表API的实现了。
1.链表的创建
创建链表其实就是创建一个链表头,初始化长度。这里将 typedef void LinkList 以方便表示
LinkList* LinkListCreate() { HLinkList *tmp = NULL; tmp = (HLinkList *)malloc(sizeof(HLinkList)); if (tmp == NULL) { return NULL; } tmp->length = 0; tmp->head.next = NULL; return tmp;}
2.链表的销毁
创建一个,对应的就要销毁一个链表,销毁链表也很简单,就是将LinkListCreate()中malloc的内存释放掉,如下:
void LinkListDestroy(LinkList* list) { if (list == NULL) { return ; } free(list); return ;}
函数中的参数LinkList* list是来标明要操作的时哪一个链表,这里没有销毁元素,因为元素与链表已经分开,所以元素创造者也是元素毁灭者。
3.链表的清空
这个操作其实就是将链表长度置零,head里的next指向NULL;
void LinkListClear(LinkList* list) { HLinkList *hList = NULL; hList = (HLinkList *)list; if (hList == NULL) { return ; } hList->header.next = NULL; hList->length = 0; return ;}
这里涉及指针的转换,hList = (HLinkList *)list;
4.获取链表长度
将链表头中的长度返回即可
int LinkListLength(LinkList* list) { HLinkList *hList = NULL; hList = (HLinkList *)list; if (tList == NULL) { return -1; } return hList->length;}
5.链表的插入
链表的插入是链表一个重要操作。
int LinkListInsert(LinkList* list, LinkListNode* node, int pos) { int i = 0; LinkListNode *current = NULL; HLinkList *hList = NULL; hList = (HLinkList *)list; if (list==NULL || node==NULL || pos<0) { return -1; } current = &(hList->header); for (i=0; i<pos; i++) { current = current->next; } node->next = current->next; current->next = node; hList->length ++; return 0;}
在三号位置插入元素,就是把插入元素的地址存储到2号位置next指针域,将原来存储在2号位置next指针域的值存到插入元素的next域。
6.链表的删除
如图,在三号位置删除三号元素,只需将2号位置的next指向4号位置,同时将3号元素返回,一边对删除元素做其他处理。
LinkListNode* LinkListDelete(LinkList* list, int pos) { int i = 0; LinkListNode *current = NULL; LinkListNode *ret = NULL; HLinkList *hList = NULL; hList = (HLinkList *)list; if (list==NULL || pos<0) { return NULL; } current = &(hList->header); for (i=0; i<pos; i++) { current = current->next; } ret = current->next; current->next = ret->next; hList->length --; return ret;}
7.按位置获取链表中的元素
这个非常简单,就是按位置找到相应元素然后返回
LinkListNode* LinkListGet(LinkList* list, int pos) { int i = 0; LinkListNode *current = NULL; HLinkList *hList = NULL; hList = (HLinkList *)list; if (list==NULL || pos<0) { return NULL; } current = &(hList->header); for (i=0; i<pos; i++) { current = current->next; } return current->next;}
- 链表系列
- 链表反转系列
- 数据结构系列之链表
- 静态链表系列操作
- 作业系列静态链表
- 作业系列静态链表
- leetcode系列(2)链表排序
- leetcode总结无止境系列之链表
- leetcode总结无止境系列之链表
- 剑指offer系列源码-反转链表
- STL系列(3):List 双向链表
- 喜羊羊系列之数据结构内核链表
- 喜羊羊系列之数据结构双向链表
- leetcode题目 反转链表系列问题
- 【剑指offer系列】 反转链表___16
- 链表的重要总结 系列一
- 链表的重要总结 系列二
- 链表的重要总结 系列三
- 把C++类成员方法直接作为线程回调函数
- Java IO流
- AngularJS学习笔记(一)
- 19岁少年重塑CPU,降低80%计算机功耗
- pip安装使用详解
- 链表系列
- oracle登录错误(ORA-01033:ORACLE initialization or shutdown in progress
- Java Heap sapce 与 Java PermGen space
- hdoj 1814 Peaceful Commission 【2-sat暴力染色 求解字典序最小解】
- linux qt5.5发布 依赖库
- SylixOS优先级与POSIX优先级关系
- AngularJS学习笔记(二)
- [LeetCode]Implement Trie (Prefix Tree)
- 百度云推送的ios证书配置