做购物网站需不需要交税费,wordpress开启hppts后格式,网页html,网站自助平台目录
1.链表
1.1 链表的概念及结构
2.不带头单链表的实现 2.1创建头文件“SList.h”
2.2 创建具体接口实现文件SList.c
2.2.1打印
2.2.2申请链表结点
2.2.3创建一个长度为n的链表 2.2.4尾插尾删
2.2.5头插头删
2.2.6寻找x元素#xff0c;返回pos
2.2.7插入和删除pos…
目录
1.链表
1.1 链表的概念及结构
2.不带头单链表的实现 2.1创建头文件“SList.h”
2.2 创建具体接口实现文件SList.c
2.2.1打印
2.2.2申请链表结点
2.2.3创建一个长度为n的链表 2.2.4尾插尾删
2.2.5头插头删
2.2.6寻找x元素返回pos
2.2.7插入和删除pos之后的位置 2.2.8插入pos之前的位置和删除pos位置
2.2.9 销毁链表
3.主函数的实现 1.链表
1.1 链表的概念及结构 概念链表是一种物理存储结构上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链 接次序实现的 实际中链表的结构非常多样以下情况组合起来就有8种链表结构 1. 单向、双向 2. 带头、不带头 3. 循环、非循环 虽然有这么多的链表的结构但是我们实际中最常用还是两种结构 1. 无头单向非循环链表结构简单一般不会单独用来存数据。实际中更多是作为其他数据结构的子结 构如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。 2. 带头双向循环链表结构最复杂一般用在单独存储数据。实际中使用的链表数据结构都是带头双向 循环链表。另外这个结构虽然结构复杂但是使用代码实现以后会发现结构会带来很多优势实现反而 简单了后面我们代码实现了就知道了。 2.不带头单链表的实现 2.1创建头文件“SList.h” 为什么要创立头文件 #pragma once
#include stdio.h
#include string.h
#include stdlib.h
#include assert.htypedef int SLTDataType;
typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;SLTNode* BuySLTNode(SLTDataType);//申请结点SLTNode* CreateSList(int n);//创建一个多长的链表void SLTPrint(SLTNode* phead);void SLTPushBack(SLTNode**pphead,SLTDataType x);
void SLTPopBack(SLTNode**pphead);
void SLTPushFront(SLTNode** pphead, SLTDataType x);
void SLTPopFront(SLTNode** pphead);SLTNode* SListFind(SLTNode* plist, SLTDataType x);//找x的位置void SListInsertAfter(SLTNode* pos, SLTDataType x);//插入pos之后的位置
void SListErasetAfter(SLTNode* pos);//删除pos后面的位置void SListInsert(SLTNode**pphead,SLTNode* pos, SLTDataType); //插入pos之前的位置
void SLTErase(SLTNode** pphead,SLTNode* pos);//删除posvoid SLTDestroy(SLTNode** pphead);//销毁链表 这里我们用来结构体的嵌套来定义单链表的节点结构体的嵌套定义 2.2 创建具体接口实现文件SList.c
先引用#include SList.h 2.2.1打印 void SLTPrint(SLTNode* phead)
{SLTNode* cur phead;/*if (cur NULL){printf(NULL);}*/while (cur){printf(%d-, cur-data);cur cur-next;}printf(NULL\n);
} 在这里我们没有断言assert如果头指针为空指针程序就会打印出NULL。 2.2.2申请链表结点 SLTNode* BuySLTNode(SLTDataType x)//申请结点
{SLTNode* newnode (SLTNode*)malloc(sizeof(SLTNode));if (newnode NULL){perror(melloc fail);exit(-1);}newnode-data x;newnode-next NULL;return newnode;
} 在这里我们用了扩容但我们使用的是malloc和顺序表有所不同的是我们并不需要异地扩容对于链表来说存储的位置本就是随机的不需要整块连续的空间。 2.2.3创建一个长度为n的链表 SLTNode* CreateSList(int n)//创建一个多长的链表
{SLTNode* phead NULL, * ptail NULL;int x 0;for (int i 0 ; i n; i){SLTNode* newnode BuySLTNode(i);if (phead NULL){phead ptail newnode;}else{ptail-next newnode;ptail newnode;}}return phead;
} 2.2.4尾插尾删 void SLTPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* cur *pphead;SLTNode* newnode BuySLTNode(x);if (*pphead NULL){*pphead newnode;}else {while (cur-next){cur cur-next;}cur-next newnode;}
}void SLTPopBack(SLTNode** pphead)
{assert(*pphead);SLTNode* tail *pphead;SLTNode* prev *pphead;if ((* pphead)-next NULL){free(*pphead);*pphead NULL;}else {while (tail-next-next){tail tail-next;}free(tail-next);tail-next NULL;}
} 注意 我们可以看到我们这里与顺序表明显不同的是我们这里传入了二级指针这到底是为什么看这篇博文单链表尾插过程中为什么传入二级指针尾删时注意 freetail与 freetail-next的区别其实原理和上述问题类似因为后者修改的是结构体指针直接改变到了结构体而仅仅freetail会导致出了函数的作用域tail栈帧销毁无法真正的改变到结构体 2.2.5头插头删 void SLTPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode BuySLTNode(x);newnode-next *pphead;*pphead newnode;}void SLTPopFront(SLTNode** pphead) {assert(*pphead);SLTNode* cur *pphead;cur cur-next;free(*pphead);*pphead cur;} 2.2.6寻找x元素返回pos SLTNode* SListFind(SLTNode* plist, SLTDataType x)
{assert(plist);SLTNode* cur plist;while (cur){if (cur-data x){return cur;}cur cur-next;}return NULL;}//找x的位置 2.2.7插入和删除pos之后的位置 void SListInsertAfter(SLTNode* pos, SLTDataType x)
{/*if (pos NULL){SLTPushBack(pos, x);}else {*/assert(pos);SLTNode*newnodeBuySLTNode(x);SLTNode* cur pos;SLTNode* lnext pos-next;cur-next newnode;newnode-next lnext;/*}*/
}//插入pos之后的位置} 2.2.8插入pos之前的位置和删除pos位置 void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) {assert(pos);if (*pphead pos){SLTPushFront(pphead, x);}else{SLTNode* prev *pphead;SLTNode* newnode BuySLTNode(x);/*while (prev-next){if (prev-next pos){prev-next newnode;newnode-next pos;}prev prev-next;}*/while (prev-next-next ! pos){prev prev-next;}prev-next newnode;newnode-next pos;}} //插入pos之前的位置void SLTErase(SLTNode** pphead, SLTNode* pos)//删除pos
{assert(pos);//写错了if (pos *pphead){SLTPopFront(pphead);}else {SLTNode* prev *pphead;while (prev-next ! pos){prev prev-next;}SLTNode* lnext pos;prev-next prev-next-next;free(pos);}
}//删除pos 2.2.9 销毁链表 void SLTDestroy(SLTNode** pphead)
{SLTNode* cur *pphead;while (cur){SLTNode* tail cur-next;free(cur);cur tail;cur cur-next;}*pphead NULL;
}//销毁链表 注意置空防止野指针打印的时候没断言。 3.主函数的实现 #include SList.h
void SListTest1() {SLTNode* n1 BuySLTNode(1);SLTNode* n2 BuySLTNode(2);SLTNode* n3 BuySLTNode(3);SLTNode* n4 BuySLTNode(4);SLTNode* n5 BuySLTNode(5);n1-next n2;n2-next n3;n3-next n4;n4-next n5;n5-next NULL;
// SLTNode*plistCreateSList(5);SLTPrint(n1);
}
void SListTest2() {SLTNode* plist CreateSList(1);SLTPrint(plist);/*SLTPushBack(plist, 100);*/SLTPrint(plist);SLTPopBack(plist);SLTPrint(plist);SLTPushFront(plist,9);SLTPushFront(plist,99);SLTPushFront(plist,999);SLTPrint(plist);SLTPopFront(plist);SLTPrint(plist);
}
void SListTest3() {SLTNode* plist CreateSList(5);SLTPrint(plist);/*SLTNode*pSListFind(plist, 3);SListInsertAfter(p, 100);SLTPrint(plist);SListErasetAfter(p);SLTPrint(plist);*/SLTNode*p SListFind(plist, 0);/*SListInsert(plist, p, 999);SLTPrint(plist);*/SLTErase(plist, p);SLTPrint(plist);SLTDestroy(plist);SLTPrint(plist);
}int main()
{SListTest1();SListTest2();SListTest3();return 0;
}