对单向无头链表的基础操作
2018-03-26 13:24
381 查看
我们要求对链表进行如下要求
初始化链表
尾插
尾删
头插
头删
查找元素在链表的位置
在pos前插入
在pos后插入
删除指定位置的元素
删除指定值的元素
指定的元素所有都删除掉
判定链表是否为空
求链表的元素个数
逆序打印链表
不允许遍历链表,在pos前插入
接下来是在Linux环境下的编程语言:
接下来是程序
接下来是测试代码
初始化链表
尾插
尾删
头插
头删
查找元素在链表的位置
在pos前插入
在pos后插入
删除指定位置的元素
删除指定值的元素
指定的元素所有都删除掉
判定链表是否为空
求链表的元素个数
逆序打印链表
不允许遍历链表,在pos前插入
接下来是在Linux环境下的编程语言:
#pragma once #include <stdio.h> #include <stdlib.h> #include <malloc.h> typedef char LinkType; //创建一个结构体 typedef struct LinkNode{ LinkType data;//这个就是我们链表的存储数据 struct LinkNode *next;//这个是链表中每个节点能够串联起来的原因(存储下个节点的地址) }LinkNode; //为了后期的代码的维护性,以及代码的健壮性所以我们有必要对那些相比较函数内部独立的程序封装起来 LinkNode* CreateNode(LinkType valaue);//创建节点 void DeleteNode(LinkNode *head);//删除节点 void LinkNodePrint(LinkNode *head,const char* msg);//打印节点 void LinkNodeInit(LinkNode **head);//链表的初始化 LinkNode* LinkNodePushBack(LinkNode **head,LinkType value);//尾插一个节点 void LinkNodePopBack(LinkNode **head);//尾删一个节点 void LinkNodePushTop(LinkNode **head,LinkType value);//头插一个节点 void LinkNodePopTop(LinkNode **head);//头删一个节点 LinkNode* LinkNodeFind(LinkNode *head,LinkType to_find);//找到节点元素并返回元素地址 void LinkNodeInsert(LinkNode **head,LinkNode *pos,LinkType value);//在pos之前插入元素 void LinkNodeInsertAfter(LinkNode **head,LinkNode *pos,LinkType value);//在pos之后插入元素 void LinkNodeErase(LinkNode **head,LinkNode *pos);//删除指定位置的元素 void LinkNodeRemove(LinkNode **head,LinkType value);//删除指定值的节点(有多个只删除第一个) void LinkNodeRemoveAll(LinkNode **head,LinkType value);//删除所有指定值的节点 int LinkNodeEmpty(LinkNode *head);//判断链表是否为空 size_t LinkNodeSize(LinkNode *head);//返回链表的长度 void LinkNodeReversePrint(LinkNode *head);//逆序打印链表 void LinkNodeInsert1(LinkNode **head,LinkNode *pos,LinkType value);//不允许遍历链表,在pos之前插入节点
接下来是程序
#include "linknode.h" //链表初始化 void LinkNodeInit(LinkNode **head) { if(head ==NULL) { return; } *head = NULL;//一定要注意初始化是一定要确定这个链表是空的,否则你将头结点置为空,那他后面的节点就找不到了 ,这样就会造成内存泄漏。如果是不为空链表的初始化,记得一定要将后面节点释放掉,再将头结点置为空。 } //创建节点 LinkNode* CreateNode(LinkType value) { LinkNode *new_node = (LinkNode *)malloc(sizeof(LinkNode));//使用malloc一定要切记,一个malloc对一个free。 if(new_node == NULL) { perror("malloc"); return NULL; } new_node->next = NULL; new_node->data = value; return new_node; } //删除节点 void DeleteNode(LinkNode *head) { free(head);//malloc之后free(好借好还再借不难) head = NULL; return; } //尾插一个节点 LinkNode* LinkNodePushBack(LinkNode **head,LinkType value) { LinkNode *cur = NULL;//定义这个指针主要作用是遍历链表 LinkNode *new_node = NULL;//这个就是新插入的节点 if(head == NULL) { return NULL; } new_node = CreateNode(value);//将需要插入的数值保存在节点上 if(*head == NULL)//空链表的情况 { *head = new_node; 4000 return *head; } cur = *head; while(cur->next != NULL)//遍历链表找到最后一个节点 { cur = cur->next; } cur->next = new_node;//将需要插入的节点放入链表的最末尾就行了 return new_node; } //尾删一个节点 void LinkNodePopBack(LinkNode **head) { if(head == NULL) { printf("LinkNode is null.\n"); return; } LinkNode *cur = *head;//主要作用还是遍历链表 LinkNode *to_delete = NULL;//需要被删除的节点指针 if((*head)->next == NULL)//空链表 { DeleteNode(*head);//空链表删除头结点就行了 return; } while(cur->next->next != NULL) { cur = cur->next; } to_delete = cur->next;//一通转换 DeleteNode(to_delete);//最后记得要删除节点啊(malloc申请你的空间一定要记得释放,不然会造成内存泄露) cur->next = NULL; return; } //头插 void LinkNodePushTop(LinkNode **head,LinkType value) { if(head == NULL) { return; } LinkNode *cur = CreateNode(value);//头插相比较简单一点 直接将需要差的值插在头 cur->next = *head; *head = cur;//最后吧头结点转换成最新的节点就行了 } //头删 void LinkNodePopTop(LinkNode **head) { if(head == NULL) { return; } if(*head == NULL)//如果是空链表的 无处可删 { printf("LinkNode is null.\n"); return; } LinkNode *cur = *head;//删除和头插还是类似的 *head = (*head)->next; DeleteNode(cur);//一定要记得释放节点啊 free return; } //返回元素的节点地址 LinkNode* LinkNodeFind(LinkNode *head,LinkType to_find) { LinkNode *cur = NULL; if(head == NULL) { printf("LinkNdoe is null.\n"); return NULL; } cur = head;//还是老规矩,遍历用 while(cur != NULL) { if(cur->data == to_find)//找到了 返回地址 { return cur; } cur = cur->next; } return NULL;//没找到 返回空值 } //在pos前插入一个节点 void LinkNodeInsert(LinkNode **head,LinkNode *pos,LinkType value) { LinkNode *cur = *head; LinkNode *new_node = NULL; if(head == NULL || pos == NULL)//检查传入的参数是否有效 { return; } if(*head == NULL)//判断是否为空链表 { printf("LinkNode is null.\n"); return; } if(cur == pos) { LinkNodePushTop(head,value); return; } while(cur->next != NULL)//遍历插入节点 { if(cur->next == pos) { new_node = CreateNode(value); cur->next = new_node; new_node->next = pos; return; } cur = cur->next; } return; } //在pos之后插入节点(和pos前插入节点类似) void LinkNodeInsertAfter(LinkNode **head,LinkNode *pos,LinkType value) { if(head == NULL || pos == NULL) { return; } if(*head == NULL) { LinkNodePushTop(head,value); return; } LinkNode *cur = *head; LinkNode *new_node = NULL; while(cur->next != NULL) { if(cur == pos) { new_node = CreateNode(value); new_node->next = cur->next; cur->next = new_node; return; } cur = cur->next; } return; } //删除节点 void LinkNodeErase(LinkNode **head,LinkNode *pos) { if(head == NULL || pos == NULL) { return; } if(*head == NULL) { printf("LinkNode is null.\n"); return; } LinkNode *cur = *head; while(cur->next != NULL) { if(cur->next == pos) { cur->next = pos->next; DeleteNode(pos);//**重要** return; } cur = cur->next; } return; } //删除指定元素的节点 void LinkNodeRemove(LinkNode **head,LinkType value) { if(head == NULL) { return; } if(*head == NULL) { printf("LinkNode is null.\n"); return; } LinkNode *cur = *head; LinkNode *new_node = NULL; if(cur->data == value) { LinkNodePopTop(head); } while(cur->next != NULL) { if(cur->next->data == value) { new_node = cur->next; cur->next = new_node->next; DeleteNode(new_node); return; } cur = cur->next; } return; } //删除所有指定元素的节点 void LinkNodeRemoveAll(LinkNode **head,LinkType value) { if(head == NULL) { return; } if(*head == NULL) { printf("LinkNode is null.\n"); return; } LinkNode *cur = *head; LinkNode *new_node = NULL; if(cur->data == value) { LinkNodePopTop(head); } while(cur->next != NULL) { if(cur->next->data == value) { new_node = cur->next; cur->next = new_node->next; DeleteNode(new_node); } cur = cur->next; } return; } //判断链表是否为空 空为0 否则为1 int LinkNodeEmpty(LinkNode *head) { if(head == NULL) { return 1; } return 0; } //计算链表的长度 size_t LinkNodeSize(LinkNode *head) { size_t count = 0; if(head == NULL) { printf("LinkNode is null.\n"); return count; } LinkNode *cur = head; while(cur != NULL) { count++; cur = cur->next; } return count; } //逆序打印链表(递归) void LinkNodeReversePrint(LinkNode *head) { if(head == NULL) { printf("NULL"); return; } LinkNode *cur = head; while(cur != NULL ) { LinkNodeReversePrint(cur->next); printf("<-[%c|%p]",cur->data,&(cur->data)); return; } return; } //进阶版的在pos前插入(不需要遍历,但是必须保证pos在链表内) void LinkNodeInsert1(LinkNode **head,LinkNode *pos,LinkType value) { if(head == NULL || pos == NULL) { return; } if(*head == NULL) { printf("LinkNode is null.\n"); return; } LinkNode *new_node = CreateNode(pos->data); pos->data = value; new_node->next = pos->next; pos->next = new_node; return; }
接下来是测试代码
//------------------------------------------------------------------ //测试代码 //------------------------------------------------------------------ #define LINE printf("-------------------------------------------------------\n"); //打印测试函数 void LinkNodePrint(LinkNode *head,const char* msg) { LINE; printf("%s",msg); printf("\n"); if(head == NULL) { printf("LinkNode is null.\n"); return; } LinkNode* cur = NULL; cur = head; while(cur != NULL) { printf("[%c|%p]->",cur->data,&(cur->data)); cur = cur->next; } printf("NULL\n"); return; } //测试函数 void LinkNodeTest() { LinkNode *head = NULL; LinkNodeInit(&head); LinkNodePushBack(&head,'a'); LinkNode *pos1 = LinkNodePushBack(&head,'b'); LinkNodePushBack(&head,'c'); LinkNodePushBack(&head,'d'); LinkNodePushBack(&head,'e'); LinkNodePushBack(&head,'a'); LinkNodePushBack(&head,'c'); LinkNodePushBack(&head,'a'); LinkNodePrint(head,"LinkNodePushBack"); LinkNodePopBack(&head); LinkNodePrint(head,"LinkNodePopBack"); LinkNodePushTop(&head,'f'); LinkNodePrint(head,"LinkNodePushTop"); LinkNodePopTop(&head); LinkNodePrint(head,"LinkNodePopTop"); LinkNodePrint(head,"LinkNodeFind"); LinkNode *cur = LinkNodeFind(head,'c'); printf("to_find is :[%c|%p]\n",cur->data,&(cur->data)); LinkNode *pos = LinkNodePushBack(&head,'x'); LinkNodePushBack(&head,'e'); LinkNodeInsert(&head,pos,'z'); LinkNodePrint(head,"LinkNodeInsert"); LinkNodeInsertAfter(&head,pos,'v'); LinkNodePrint(head,"LinkNodeInsertAfter"); LinkNodeErase(&head,pos); LinkNodePrint(head,"LinkNodeErase"); LinkNodeRemove(&head,'v'); LinkNodePrint(head,"LinkNodeRemove"); LinkNodeRemoveAll(&head,'a'); LinkNodePrint(head,"LinkNodeRemoveAll"); LinkNodePrint(head,"change LinkNode is empty?"); printf("%d\n",LinkNodeEmpty(head)); LinkNodePrint(head,"LinkNode:"); printf("count LinkNode:%d\n",LinkNodeSize(head)); LinkNodePrint(head,"LinkNode:"); printf("\n"); LinkNodeReversePrint(head); printf("\n"); LinkNodeInsert1(&head,pos1,'a'); LinkNodePrint(head,"LinkNodeInsert1"); } int main() { LinkNodeTest(); return 0; }
相关文章推荐
- 面试基础_02单向链表操作
- C语言实现,无头结点不带环的单向链表的基本操作
- (C语言版)链表(二)——实现单向循环链表创建、插入、删除、释放内存等简单操作
- 单向链表删除操作
- ZT C语言链表操作(新增单向链表的逆序建立)
- 数据结构实验二 链式存储结构----单向链表的有关操作(学生成绩信息C语言)
- Java链表基础(3)-基本操作
- 单向链表操作
- 16.单向链表的一些基本操作实现(链表反转,链表有环无环判断,链表冒泡排序,链表快速排序)
- 单向链表常用操作,C和C++版本(转载)
- 文章标题C语言实现单链表之基础操作
- 关于单向链表的相关一系列操作(作为备忘)
- 复习下C 链表操作(单向链表)
- VC++基础 链表的操作示例
- java基础之面试篇四-单向链表和双向链表区别
- 数据结构面试题总结9——链表:基础操作
- 顺序表(Seqlist)&链表(List)的基础操作
- java 单向链表的操作
- 单向链表的基本操作
- 单链表基础操作C++实现