单链表
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
- 单向、双向
- 带头、不带头
- 循环、非循环
虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:
- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结 构,如哈希桶、图的邻接表等等。另外这种结构在学校的考试中出现很多。
- 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向 循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而 简单了
实现不带头单链表以及相关操作
头文件
#pragma oncetypedef int SLDateType;//一个结点
typedef struct SLNode{SLDateType value;struct SLNode *next;
} SListNode;//不带头动态链表
typedef struct SList{SListNode *first;
}SList;//初始化
void SListInit(SList *list);
//销毁
void SListDestroy(SList *list);
//增
//头插
void SListPushFront(SList *list, SLDateType value);
//尾插
void SListPushBack(SList *list, SLDateType value);//删
//头删
void SListPopFront(SList *list);
//尾删
void SListPopBack(SList *list);//打印
void SListPrint(const SList *list);//改
void SListUpdata(SListNode *node, SLDateType value);//查
//去查找链表中遇到的第一个value,如果没找到,返回NULL
SListNode *SListFind(const SList *list, SLDateType value);//打印
void SListPrint(const SList *list);void SListInsertBefore(SList *list, SListNode *pos, SLDateType value);
// 在pos的后面插入
void SListInsertAfter(SListNode *pos,SLDateType value);
// 删除pos位置的节点
void SListEraseAfter(SListNode *pos);
void ListRemove();
功能实现
#include"SList.h"
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
#include<stdio.h>//初始化
void SListInit(SList *list){assert(list != NULL);list->first = NULL;
}//申请新结点
SListNode* BuyNode(SLDateType value){SListNode *node = (SListNode*)malloc(sizeof(SListNode));assert(node);node->value = value;node->next = NULL;return node;
}
//头插
void SListPushFront(SList *list, SLDateType value){SListNode *node = (SListNode*)malloc(sizeof(SListNode));assert(node);node->value = value;node->next = list->first;list->first = node;
}//头删
void SListPopFront(SList *list){assert(list != NULL); //链表存在assert(list->first != NULL); //链表不为空,里面有结点SListNode *old_first = list->first;list->first = list->first->next;free(old_first);
}
//尾插
void SListPushBack(SList *list, SLDateType value){assert(list != NULL);if (list->first == NULL){ //链表中没有结点的情况就跟头插的情况是一样的SListPushFront(list, value);return;}//链表中有结点的情况SListNode *cur;for (cur = list->first; cur->next != NULL; cur = cur->next);//cur就是最后一个结点SListNode *node = BuyNode(value);cur->next = node;
}//尾删
void SListPopBack(SList *list){assert(list != NULL);assert(list->first != NULL);//只有一个结点if (list->first->next == NULL){SListPopFront(list);return;}SListNode *cur = list->first;while (cur->next->next != NULL){cur = cur->next;}free(cur->next);cur->next = NULL;
}//销毁
void SListDestroy(SList *list){assert(list != NULL);SListNode *cur = list->first;SListNode *next;while (cur!=NULL){next = cur->next;free(cur);cur = cur->next;}list->first = NULL;
}//打印
void SListPrint(const SList *list){for (SListNode *cur = list->first; cur != NULL; cur = cur->next){printf("%d--->", cur->value);}printf("\n");
}//改
void SListUpdata(SListNode *node, SLDateType value){node->value = value;
}//去查找链表中遇到的第一个value,如果没找到,返回NULL
SListNode *SListFind(const SList *list, SLDateType value){for (SListNode *cur = list->first; cur != NULL; cur = cur->next){if (cur->value == value){return cur;}}return NULL;
}//pos 一定是链表中有效结点
//向后面插入
void SListInsertAfter(SListNode *pos, SLDateType value){SListNode *node = BuyNode(value); //申请结点node->next = pos->next;pos->next = node;
}// 删除pos后面位置的节点
void SListEraseAfter(SListNode *pos){SListNode *next = pos->next;pos->next = next->next;free(next);}//向pos前面插入
void SListInsertBefore(SList *list, SListNode *pos, SLDateType value){SListNode *cur;SListNode *node = BuyNode(value);for (cur = list->first; cur->next != pos; cur = cur->next);node->next = pos;cur->next = node;
}
测试用例
#include"SList.h"
#include<stdlib.h>
#include<assert.h>
#include<stdio.h>void TestList1(){SList list;SListInit(&list);assert(list.first == NULL);/*SListPushFront(&list, 1);SListPushFront(&list, 2);SListPushFront(&list, 3);//3 2 1*/SListPushBack(&list, 11);SListPushBack(&list, 12);SListPushBack(&list, 13);//3 2 1 11 12 13/*SListPopBack(&list);SListPopBack(&list);SListPopBack(&list);*/SListNode *n12 = SListFind(&list, 12);assert(n12 != NULL);SListPrint(&list);SListInsertAfter(n12, 103);SListPrint(&list);SListEraseAfter(n12);SListPrint(&list);SListInsertBefore(&list,n12, 101);SListPrint(&list);printf("大成功\n");
}int main()
{TestList1();system("pause");return 0;
}