链表的增、删、查、找
2017-12-20 21:01
127 查看
基本结构
typedef int DataType;
typedef struct SListNode
{
struct SListNode* _next;
DataType _data;
}SListNode;
链表结构分为两部分,一部分是数据域,存放的是节点的数据部分,另一部分是指针域,保存下一节点的地址
新建节点
和动态顺序表不一样,每次只开辟一个节点的空间,将其节点的指针域赋为空
代码:
打印链表
动态顺序表是通过下标来进行访问,而链表是通过指针访问到每一个节点,当某一节点的指针域为空时,说明链表到尾
代码:
链表的头插(过程如下图)
代码:
链表头删(过程如下图)
代码:
尾插(过程与头插想类似在这里不在画图)
代码:
尾删
代码:
任意位置插入(指头插)
在这里需要注意几点:
1)链表为空时,只需调用头插即可
2)链表有一个及以上节点时,需注意保存该位置的前一位置,将其与前一位置相连
代码:
任意位置删除(删除方法类似头插,不在画图)
代码:
下面给出完整代码及测试用例:
SeqList.c:
test.c
typedef int DataType;
typedef struct SListNode
{
struct SListNode* _next;
DataType _data;
}SListNode;
链表结构分为两部分,一部分是数据域,存放的是节点的数据部分,另一部分是指针域,保存下一节点的地址
新建节点
和动态顺序表不一样,每次只开辟一个节点的空间,将其节点的指针域赋为空
代码:
SListNode* BuySListNode(DataType x) { SListNode *NewNode =(SListNode *) malloc(sizeof(SListNode)); if (NewNode==NULL) { perror("申请失败"); exit(EXIT_FAILURE); } NewNode->_data = x; NewNode->_next = NULL; return NewNode; }
打印链表
动态顺序表是通过下标来进行访问,而链表是通过指针访问到每一个节点,当某一节点的指针域为空时,说明链表到尾
代码:
void SListPrint(SListNode* pHead) { while (pHead != NULL) { printf("%d ", pHead->_data); pHead = pHead->_next; } printf("\n"); }
链表的头插(过程如下图)
代码:
void SListPushFront(SListNode** ppHead, DataType x) { if ((*ppHead) == NULL) { SListNode *cur = BuySListNode(x); *ppHead = cur; } else { SListNode *cur = BuySListNode(x); cur->_next = *ppHead; *ppHead = cur; } }
链表头删(过程如下图)
代码:
void SListPopFront(SListNode** ppHead) { if (*ppHead == NULL) { printf("list is empty\n"); } else { SListNode *cur = *ppHead; free(cur); *ppHead = (*ppHead)->_next; } }
尾插(过程与头插想类似在这里不在画图)
代码:
void SListPushBack(SListNode** ppHead, DataType x) { assert(ppHead); SListNode *cur = *ppHead; if (*ppHead == NULL) { *ppHead = BuySListNode(x); } else { while (cur->_next != NULL) { cur = cur->_next; } cur->_next = BuySListNode(x); } }
尾删
代码:
void SListPopBack(SListNode** ppHead) { SListNode *cur = *ppHead; if (*ppHead == NULL) { printf("List is empty\n"); } else if ((*ppHead)->_next == NULL) { free(*ppHead); *ppHead = NULL; } else { while (cur->_next->_next != NULL) { cur = cur->_next; } free(cur->_next); cur->_next = NULL; } }
任意位置插入(指头插)
在这里需要注意几点:
1)链表为空时,只需调用头插即可
2)链表有一个及以上节点时,需注意保存该位置的前一位置,将其与前一位置相连
代码:
void SListInsest(SListNode** ppHead, SListNode* pos, DataType x) { assert(*ppHead); SListNode* prev = *ppHead;//记录pos位置的前一个节点 SListNode* cur = *ppHead;//头结点 if (pos == cur) { SListPushFront(ppHead, x); } else { while (prev->_next != pos) { prev = prev->_next; } SListNode* NewNode = BuySListNode(x); NewNode->_next = prev->_next; prev->_next = NewNode; } }
任意位置删除(删除方法类似头插,不在画图)
代码:
void SListErase(SListNode** ppHead, SListNode* pos) { if (*ppHead == NULL) { printf("list is empty\n"); } else { if (pos == *ppHead) { SListNode *cur = *ppHead; (*ppHead) = (*ppHead)->_next; free(cur); } else if (pos == NULL) { SListPopBack(&pos); } else { SListNode* prev = *ppHead; while (prev->_next != pos) { prev = prev->_next; } prev->_next = pos->_next; free(pos); } } }
下面给出完整代码及测试用例:
SeqList.c:
SListNode* list;
//新建一个节点
SListNode* BuySListNode(DataType x) { SListNode *NewNode =(SListNode *) malloc(sizeof(SListNode)); if (NewNode==NULL) { perror("申请失败"); exit(EXIT_FAILURE); } NewNode->_data = x; NewNode->_next = NULL; return NewNode; }
//打印链表
void SListPrint(SListNode* pHead) { while (pHead != NULL) { printf("%d ", pHead->_data); pHead = pHead->_next; } printf("\n"); }
//释放节点
void SListDestory(SListNode** ppHead)
{
assert(ppHead);
free(*ppHead);
*ppHead = NULL;
}
//尾插
void SListPushBack(SListNode** ppHead, DataType x)
{
assert(ppHead);
SListNode *cur = *ppHead;
if (*ppHead == NULL)
{
*ppHead = BuySListNode(x);
(*ppHead)->_next = NULL;
}
else
{
while (cur->_next != NULL)
{
cur = cur->_next;
}
cur->_next = BuySListNode(x);
}
}
//尾删
void SListPopBack(SListNode** ppHead)
{
SListNode *cur = *ppHead;
if (*ppHead == NULL)
{
printf("List is empty\n");
}
else if ((*ppHead)->_next == NULL)
{
free(*ppHead);
*ppHead = NULL;
}
else
{
while (cur->_next->_next != NULL)
{
cur = cur->_next;
}
free(cur->_next);
cur->_next = NULL;
}
}
//头插
void SListPushFront(SListNode** ppHead, DataType x)
{
if ((*ppHead) == NULL)
{
SListNode *cur = BuySListNode(x);
*ppHead = cur;
}
else
{
SListNode *cur = BuySListNode(x);
cur->_next = *ppHead;
*ppHead = cur;
}
}
//头删
void SListPopFront(SListNode** ppHead)
{
if (*ppHead == NULL)
{
printf("list is empty\n");
}
else
{
SListNode *cur = *ppHead;
*ppHead = (*ppHead)->_next;
free(cur);
}
}
//任意位置插入
void SListInsest(SListNode** ppHead, SListNode* pos, DataType x)
{
assert(ppHead);
//assert(pos);
SListNode* prev = *ppHead;//记录pos位置的前一个节点
SListNode* cur = *ppHead;//头结点
if (pos == cur)
{
SListPushFront(ppHead, x);
}
else
{
while (prev->_next != pos)
{
prev = prev->_next;
}
SListNode* NewNode = BuySListNode(x);
NewNode->_next = prev->_next;
prev->_next = NewNode;
}
}
//查找
SListNode* SListFind(SListNode* pHead, DataType x)
{
assert(pHead);
SListNode *cur = pHead;
while (cur != NULL)
{
if (cur->_data == x)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
//任意位置删除
void SListErase(SListNode** ppHead, SListNode* pos) { if (*ppHead == NULL) { printf("list is empty\n"); } else { if (pos == *ppHead) { SListNode *cur = *ppHead; (*ppHead) = (*ppHead)->_next; free(cur); } else if (pos == NULL) { SListPopBack(&pos); } else { SListNode* prev = *ppHead; while (prev->_next != pos) { prev = prev->_next; } prev->_next = pos->_next; free(pos); } } }
test.c
//测试尾插 void TestSListPushBack() { list = NULL; SListPushBack(&list, 0); SListPushBack(&list, 1); SListPushBack(&list, 2); SListPushBack(&list, 3); SListPushBack(&list, 4); SListPushBack(&list, 5); SListPrint(list); } //测试尾删 void TestSListPopBack(SListNode** ppHead) { list = NULL; SListPushBack(&list, 0); SListPushBack(&list, 1); SListPushBack(&list, 2); SListPushBack(&list, 3); SListPushBack(&list, 4); SListPushBack(&list, 5); SListPrint(list); SListPopBack(&list); SListPopBack(&list); SListPopBack(&list); SListPopBack(&list); SListPopBack(&list); SListPopBack(&list); SListPrint(list); } //测试头插 void TestSListPushFront() { list = NULL; SListPushFront(&list, 0); SListPushFront(&list, 1); SListPushFront(&list, 2); SListPushFront(&list, 3); SListPushFront(&list, 4); SListPrint(list); } //测试头删 void TestSListPopFront() { list = NULL; SListPushFront(&list, 0); SListPushFront(&list, 1); SListPushFront(&list, 2); SListPushFront(&list, 3); SListPushFront(&list, 4); SListPrint(list); SListPopFront(&list); SListPopFront(&list); SListPopFront(&list); SListPopFront(&list); SListPopFront(&list); SListPrint(list); } //测试查找 void TestSListFind() { list = NULL; SListPushFront(&list, 0); SListPushFront(&list, 1); SListPushFront(&list, 2); SListPushFront(&list, 3); SListPushFront(&list, 4); SListNode* cur = SListFind(list, 3); printf("%d\n", cur->_data); } //测试任意位置插入 void TestSListInsest() { list = NULL; SListPushFront(&list, 0); SListPushFront(&list, 1); SListPushFront(&list, 2); SListPushFront(&list, 3); SListPushFront(&list, 4); SListPrint(list); SListNode *ret = SListFind(list, 0); SListInsest(&list, ret, 78); ret = SListFind(list, 4); SListInsest(&list, ret, 78); ret = SListFind(list, 2); SListInsest(&list, ret, 78); SListPrint(list); } //测试任意位置删除 void TestSListErase(SListNode** ppHead, SListNode* pos) { list = NULL; SListPushFront(&list, 0); SListPushFront(&list, 1); SListPushFront(&list, 2); SListPushFront(&list, 3); SListPushFront(&list, 4); SListPrint(list); SListNode *ret = SListFind(list, 4); SListInsest(&list, ret, 23); SListPrint(list); ret = SListFind(list, 4); SListErase(&list, ret); ret = SListFind(list, 23); SListErase(&list, ret); ret = SListFind(list, 0); SListErase(&list, ret); SListPrint(list); }
相关文章推荐
- 用链表实现大整数加法
- 双向链表-C/C++-多项式操作
- 如何用C++来实现在循环链表里展示除了最后一个节点,然后返回所展示的节点总和
- 【学习笔记----数据结构04-单循环链表】
- leetcode之时间复杂度为O(nlogn)的链表排序
- java基于有序链表的优先级队列实现
- 链表的基本使用
- 内存池性能优化 固定内存块使用 之 链表实现
- 链表逆序
- C语言一个双向链表的实现
- 单链表
- 数据结构学习笔记(二) 链表之单链表的基本操作
- 链表删除偶数
- 在无头节点的单链表里删除元素
- sdut oj数据结构实验之链表五:单链表的拆分
- 看数据结构写代码(52) 广义表的扩展线性链表存储表示
- 单链表
- 数据结构-链表队列
- 2017_4校赛C (模拟链表)
- 第四周项目3---单链表应用