数据结构(二)——链表(C语言实现)
2016-09-30 22:08
651 查看
定义
实现
定义结构
定义操作
创建头结点
插入结点
删除结点
销毁链表
链表的访问需要从第一个结点(或称头结点)开始寻找,(顺序表可以根据下标直接访问)。链表的插入和删除只需对指定位置的结点操作即可。
常见的链表,根据指向下个链表的指针可分为单向链表,双向链表。根据第一个结点是否存储元素可分为带头结点的链表和不带头结点的链表。再根据末尾结点next指针的指向可分为循环链表和非循环链表。
*下面程序以单向带头结点的非循环链表为例。
定义LinkType类型,使该链表结构适合更多数据类型。每个链表的结点,包含一个值域key和一个指针域next。这里声明两种类型
这里是动态分配一个内存单元存储头结点,也可以参照顺序表中,使用
在带头结点的链表中,头插法表示每次将结点插入到头结点的后面。在不带头结点的链表中,将待插入的结点放在链表中第一个结点的前面,代替之成为第一个结点。
对于尾插法而言,不区分带头结点和不带头结点的链表。只将待插入的结点插到链表的最后一个位置。因此需要先循环到链表的末尾。
先根据下标找到待插入的位置,然后插入结点。对比顺序表,先移动指定位置的后续结点,再插入新的结点。
下标从0开始,表示头结点后的第一个结点。先找到待删除的结点,取出key值,再删除该结点。
首先根据val值,找到待删除的结点,最后删除之。
释放掉除头结点之外的所有结点占用的内存。
最后附上,头文件的定义
实现
定义结构
定义操作
创建头结点
插入结点
删除结点
销毁链表
定义
相对于顺序表而言,“勤拿少取”这是对链表最形象的描述。意指,它需要一个结点,就在内存中分配一块内存单元。比顺序表不足的是,链表的每个结点中,需要一个存储单元保存指向下一个结点的地址。链表的访问需要从第一个结点(或称头结点)开始寻找,(顺序表可以根据下标直接访问)。链表的插入和删除只需对指定位置的结点操作即可。
常见的链表,根据指向下个链表的指针可分为单向链表,双向链表。根据第一个结点是否存储元素可分为带头结点的链表和不带头结点的链表。再根据末尾结点next指针的指向可分为循环链表和非循环链表。
*下面程序以单向带头结点的非循环链表为例。
实现
定义结构
typedef int LinkType; //存储单元类型 typedef struct linkNode { LinkType key; //结点的key值 struct linkNode *next; //指向下一个结点 } LNode, *LinkList;//LNode 是普通类型,LinkList是指针类型
定义LinkType类型,使该链表结构适合更多数据类型。每个链表的结点,包含一个值域key和一个指针域next。这里声明两种类型
LNode和
LinkList。以下两行代码是等价的。
LNode* node = (LNode*)malloc(sizeof(LNode)); LinkList node = (LinkList)malloc(sizeof(LNode));
定义操作
创建头结点
/** * 创建头结点 */ LinkList createHead_link() { LinkList head = (LinkList) malloc(sizeof(LNode)); head->next = NULL; return head; }
这里是动态分配一个内存单元存储头结点,也可以参照顺序表中,使用
LNode head,由系统分配内存。1
插入结点
/** * 头插法 */ void insertFirst_link(LinkList head, LinkType val) { LinkList node = (LinkList) malloc(sizeof(LNode)); node->key = val; node->next = head->next; head->next = node; }
在带头结点的链表中,头插法表示每次将结点插入到头结点的后面。在不带头结点的链表中,将待插入的结点放在链表中第一个结点的前面,代替之成为第一个结点。
/** * 尾插法 */ void insertLast_link(LinkList head, LinkType val) { LinkList temp = head; while (temp->next != NULL) //找到末尾结点 temp = temp->next; LinkList node = (LinkList) malloc(sizeof(LNode)); node->key = val; temp->next = node; node->next = NULL; }
对于尾插法而言,不区分带头结点和不带头结点的链表。只将待插入的结点插到链表的最后一个位置。因此需要先循环到链表的末尾。
/** * 指定位置插入,position表示插入后的位置,0表示头结点后的第一个结点 */ void insert_link(LinkList head, int position, LinkType val) { if (position < 0) //-1 从末尾添加,采用尾插法 insertLast_link(head, val); else if (position == 0) //从第一个结点插入,采用头插法 insertFirst_link(head, val); else { // LinkList temp = head->next; while (temp != NULL && --position > 0) { //找到合适的位置结点 temp = temp->next; } LinkList node = (LinkList) malloc(sizeof(LNode)); node->key = val; node->next = temp->next; temp->next = node; } }
先根据下标找到待插入的位置,然后插入结点。对比顺序表,先移动指定位置的后续结点,再插入新的结点。
删除结点
/** * 删除节点(指定位置),下标从0开始 */ void removeNode_link(LinkList head, int index, LinkType &key) { if (index < 0) { printf("指定下标值不正确\n"); return; } LinkList node = head; int i = 0; while (!node->next || i < index) { //寻找指定下标的节点,结束循环时,i==index node = node->next; i++; } if (i == index) { //找到指定节点 LinkList temp = node->next; //temp 是要被删除的节点 node->next = temp->next; temp->next = NULL; key = temp->key; free(temp); } else { //没找到 printf("没找到指定下标的值"); } }
下标从0开始,表示头结点后的第一个结点。先找到待删除的结点,取出key值,再删除该结点。
/** * 删除节点(指定节点) */ void removeNode_link(LinkList head, LinkType val) { LinkList node = head; while (!node->next) { if (node->next->key == val) break; node = node->next; } if (node->next != NULL) { //找到要删除的节点 LinkList temp = node->next; //temp 是要被删除的节点 node->next = temp->next; temp->next = NULL; free(temp); } else { printf("没找到要删除的节点\n"); } }
首先根据val值,找到待删除的结点,最后删除之。
销毁链表
/** * 销毁链表 */ void destory_link(LinkList head) { while (head->next != NULL) { LinkList node = head->next; head->next = node->next; free(node); } }
释放掉除头结点之外的所有结点占用的内存。
最后附上,头文件的定义
/* * linklist.h * 顺序表的链式存储结构 * Created on: 2016年8月30日 * Author: flueky */ #ifndef LINKLIST_H_ #define LINKLIST_H_ typedef int LinkType; //存储单元类型 typedef struct linkNode { LinkType key; //节点的key值 struct linkNode *next; //指向下一个节点 } LNode, *LinkList;//LNode 是普通类型,LinkList是指针类型 /** * 创建头结点 */ LinkList createHead_link(); /** * 头插法 */ void insertFirst_link(LinkList, LinkType); /** * 尾插法 */ void insertLast_link(LinkList, LinkType); /** * 在指定位置插入 */ void insert_link(LinkList,int, LinkType); /** * 删除节点(指定位置) */ void removeNode_link(LinkList,int,LinkType&); /** * 删除节点(指定节点) */ void removeNode_link(LinkList,LinkType); /** * 销毁链表 */ void destory_link(LinkList); #endif /* LINKLIST_H_ */数据结构(一)——顺序表(C语言实现) ↩
相关文章推荐
- 【数据结构】C语言实现链表的创建及遍历链表
- (C语言)单链表的顺序实现(数据结构一)
- C语言数据结构_单链表_19个功能实现全解
- C语言数据结构实现链表去重的实例
- C语言实现数据结构中的循环链表
- 【数据结构】C语言实现链表节点的插入和删除
- 数据结构--单链表的基本操作(C语言实现)
- 【数据结构】链表及相关操作(C语言实现)
- 重温数据结构之链表二——C语言实现
- 【数据结构】C语言实现链表
- C语言数据结构之单向链表(已经调试可以实现相应的功能了,可是还是有几个问题现在还是不大理解,希望大家能够一起探讨)
- 【小镇的技术天梯】从头写数据结构,C语言实现双向链表
- [数据结构]C语言链表实现
- 【数据结构】C语言实现单链表
- C语言数据结构中链表的具体实现
- 数据结构中单链表的实现+单链表的C语言实现源代码
- 数据结构模版----单链表SimpleLinkList[不带头结点&&伪OO](C语言实现)
- 数据结构(严蔚敏)之二——链表的c语言实现
- C语言实现数据结构的链表
- c语言实现数据结构中的链表源代码