博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++
座右铭:“不要等到什么都没有了,才下定决心去做”
大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点
目录
单链表
单链表的定义
单链表的打印
单链表的创建节点
单链表的头插
单链表的尾插
单链表的尾删
单链表的头删
单链表的查找
单链表的改动
单链表的元素个数
单链表的任意位置插入元素
单链表的任意位置删除元素
单链表的销毁
单链表中的源码
main文件
头文件test.h
test.c文件
单链表的定义
typedef int SLTDataType; typedef struct SListNode { SLTDataType data; struct SListNode* next;//next存放的下一个节点的地址 }SLT;
单链表的打印
依次打印链表中的数据
void SLTprintf(SLT* phead) { SLT* cur=phead; while(cur!=NULL) { printf("%d ",cur->data); cur=cur->next; } printf("\n"); }
单链表的创建节点
动态开辟一个空间,然后返回这个空间的地址,即动态开辟的节点
SLT* Buylistnode(int x) { SLT* newnode=(SLT*)malloc(sizeof(SLT)); if(newnode==NULL) { perror("malloc fail"); return 0; } newnode->data=x; newnode->next=NULL; return newnode; }
单链表的头插
复用了动态创建节点
void SLTPushFront(SLT** pphead,SLTDataType x) { SLT* newnode= Buylistnode(x); newnode->next=*pphead; *pphead=newnode; }
单链表的尾插
注意一个节点和多个节点时
void SLTPushBack(SLT** pphead,SLTDataType x) { SLT* newnode=Buylistnode(x); if(*pphead==NULL)//当为空链表时 { *pphead=newnode; } else { SLT* tail=*pphead; while(tail->next) { tail=tail->next; } tail->next=newnode; } }
单链表的尾删
这两种方法的本质都是找到倒数第二个节点
第一种尾删的方法
注意一个节点和多个节点时
void SLTPopBack(SLT** pphead) { assert(*pphead); SLT* prev=NULL; SLT* tail=*pphead; if(tail->next==NULL) { free(tail); *pphead=NULL; } else { while(tail->next) { prev=tail; tail=tail->next; } free(tail); prev->next=NULL; } }
第二种尾删的方法
注意一个节点和多个节点时
void SLTPopBack(SLT** pphead) { assert(*pphead); SLT* tail=*pphead; if(tail->next==NULL)//只有一个节点 { free(tail); *pphead=NULL; } else//有多个节点 { while(tail->next->next)//这也是找到倒数第二个节点 { tail=tail->next; } free(tail->next); tail->next=NULL; } }
单链表的头删
注意一个节点和多个节点时
void SLTPopFront(SLT** pphead) { assert(*pphead); SLT* tail=*pphead; if(tail->next==NULL)//一个节点 { free(tail); *pphead=NULL; } else//多个节点 { tail=tail->next; free(*pphead); *pphead=tail; } }
单链表的查找
(找到了,就返回所在的位置,没找到返回-1)
int SLTFind(SLT** pphead,SLTDataType x) { assert(*pphead); SLT* try_b=*pphead; int Count=1; while(try_b->next) { if(try_b->data==x) { return Count; } Count++; try_b=try_b->next; } return -1; }
单链表的改动
需要给出改动的位置以及要改动的值
void SLTChange(SLT** pphead,int pos,SLTDataType x) { assert(*pphead); int Count=Totalsize(pphead); assert(pos<=Count); SLT* tail=*pphead; while(pos--) { tail=tail->next; } tail->data=x; }
单链表的元素个数
计算链表的元素个数,然后返回个数
int Totalsize(SLT** pphead) { SLT* tail=*pphead; int Count=0; while(tail) { tail=tail->next; Count++; } return Count; }
单链表的任意位置插入元素
需要给出插入的位置以及要插入的值(说明一下,这里是插入元素的位置的后面),插入的位置一定要合法
void SLTInsertAfter(SLT** pphead,int pos, SLTDataType x) { assert(pos<=Count); if((*pphead)==NULL) { SLTPushFront(pphead, x); } else { SLT* prev=NULL; SLT* tail=*pphead; while(pos--) { prev=tail; tail=tail->next; } SLT* newnode=Buylistnode(x); prev->next=newnode; newnode->next=tail; } }
单链表的任意位置删除元素
删除的位置一定要合法
void SLTEraseAfter(SLT** pphead,int pos) { assert(*pphead); assert(pos<=Count-1); if((*pphead)->next==NULL) { SLTPopFront(pphead); } else { SLT* prev=NULL; SLT* taillater=NULL; SLT* tail=*pphead; while(pos--) { prev=tail; tail=tail->next; } taillater=tail->next; free(tail); tail=NULL; prev->next=taillater; } }
单链表的销毁
void SLTDestroy(SLT** pphead) { free(*pphead); *pphead=NULL; }
单链表中的源码
为方便调试单链表,这里没有使用了菜单
main文件
#include"test.h" void test1(void) { SLT* plist=NULL; SLTPushFront(&plist, 1); SLTPushFront(&plist, 2); SLTPushFront(&plist, 3); SLTPushFront(&plist, 4); SLTprintf(plist); printf("\n"); SLTPushBack(&plist, 4); SLTPushBack(&plist, 3); SLTPushBack(&plist, 2); SLTPushBack(&plist, 1); SLTprintf(plist); } void test2(void) { SLT* plist=NULL; SLTPushFront(&plist, 1); SLTPushFront(&plist, 2); SLTPushFront(&plist, 3); SLTPushFront(&plist, 4); SLTPushBack(&plist, 4); SLTPushBack(&plist, 3); SLTPushBack(&plist, 2); SLTPushBack(&plist, 1); SLTprintf(plist); // SLTPopBack(&plist); // SLTPopBack(&plist); // SLTPopBack(&plist); // SLTPopBack(&plist); // SLTPopBack(&plist); // SLTPopBack(&plist); // SLTPopBack(&plist); // SLTprintf(plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTprintf(plist); } void test3(void) { SLT* plist=NULL; SLTPushFront(&plist, 1); SLTPushFront(&plist, 2); SLTPushFront(&plist, 3); SLTPushFront(&plist, 4); SLTPushBack(&plist, 4); SLTPushBack(&plist, 3); SLTPushBack(&plist, 2); SLTPushBack(&plist, 1); SLTprintf(plist); int ret=SLTFind(&plist,4); printf("position is('-1'is not find):%d\n",ret); } void test4(void) { SLT* plist=NULL; SLTPushFront(&plist, 1); SLTPushFront(&plist, 2); SLTPushFront(&plist, 3); SLTPushFront(&plist, 4); SLTPushBack(&plist, 4); SLTPushBack(&plist, 3); SLTPushBack(&plist, 2); SLTPushBack(&plist, 1); SLTprintf(plist); SLTChange(&plist, 23, 100); SLTprintf(plist); } void test5(void) { SLT* plist=NULL; SLTPushFront(&plist, 1); SLTPushFront(&plist, 2); SLTPushFront(&plist, 3); SLTPushFront(&plist, 4); SLTPushBack(&plist, 4); SLTPushBack(&plist, 3); SLTPushBack(&plist, 2); SLTPushBack(&plist, 1); SLTprintf(plist); int ret=Totalsize(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTPopFront(&plist); SLTprintf(plist); ret=Totalsize(&plist); printf("total is :%d\n",ret); } void test6(void) { SLT* plist=NULL; // SLTPushFront(&plist, 1); // SLTPushFront(&plist, 2); // SLTPushFront(&plist, 3); // SLTPushFront(&plist, 4); // SLTPushBack(&plist, 4); // SLTPushBack(&plist, 3); // SLTPushBack(&plist, 2); // SLTPushBack(&plist, 1); SLTprintf(plist); SLTInsertAfter(&plist, 1, 100); SLTprintf(plist); } void test7(void) { SLT* plist=NULL; SLTPushFront(&plist, 1); // SLTPushFront(&plist, 2); // SLTPushFront(&plist, 3); // SLTPushFront(&plist, 4); // SLTPushBack(&plist, 4); // SLTPushBack(&plist, 3); // SLTPushBack(&plist, 2); // SLTPushBack(&plist, 1); SLTprintf(plist); SLTEraseAfter(&plist, 1); SLTprintf(plist); } void test8(void) { SLT* plist=NULL; SLTPushFront(&plist, 1); SLTPushFront(&plist, 2); SLTPushFront(&plist, 3); SLTPushFront(&plist, 4); SLTPushBack(&plist, 4); SLTPushBack(&plist, 3); SLTPushBack(&plist, 2); SLTPushBack(&plist, 1); SLTprintf(plist); SLTDestroy(&plist); SLTprintf(plist); } int main() { //test1();//完成头插尾插 //test2();//完成尾删 //test3();//查找 //test4();//改动 //test5();//判断链表有多少个元素 // test6();//任意插入元素 //test7();//任意删除元素 test8();//销毁链表 }
头文件test.h
#ifndef test_h #define test_h #include
#endif /* test_h */ #include #include typedef int SLTDataType; typedef struct SListNode { SLTDataType data; struct SListNode* next;//next存放的下一个节点的地址 }SLT; //单链表的打印 void SLTprintf(SLT* phead); //单链表的头插 void SLTPushFront(SLT** pphead,SLTDataType x); //单链表的尾插 void SLTPushBack(SLT** pphead,SLTDataType x); //单链表的尾删 void SLTPopBack(SLT** pphead); //单链表的头删 void SLTPopFront(SLT** pphead); //单链表的查找(找到了,就返回所在的位置,没找到返回-1) int SLTFind(SLT** pphead,SLTDataType x); //单链表的改动(改变给出位置的值) void SLTChange(SLT** pphead,int pos,SLTDataType x); //单链表的元素个数 int Totalsize(SLT** pphead); //单链表的任意位置插入元素 void SLTInsertAfter(SLT** pphead,int pos, SLTDataType x); //单链表的任意位置删除元素 void SLTEraseAfter(SLT** pphead,int pos); //单链表的销毁 void SLTDestroy(SLT** pphead); test.c文件
#include "test.h" void SLTprintf(SLT* phead) { SLT* cur=phead; while(cur!=NULL) { printf("%d ",cur->data); cur=cur->next; } printf("\n"); } SLT* Buylistnode(int x) { SLT* newnode=(SLT*)malloc(sizeof(SLT)); if(newnode==NULL) { perror("malloc fail"); return 0; } newnode->data=x; newnode->next=NULL; return newnode; } void SLTPushFront(SLT** pphead,SLTDataType x) { SLT* newnode= Buylistnode(x); newnode->next=*pphead; *pphead=newnode; } void SLTPushBack(SLT** pphead,SLTDataType x) { SLT* newnode=Buylistnode(x); if(*pphead==NULL) { *pphead=newnode; } else { SLT* tail=*pphead; while(tail->next) { tail=tail->next; } tail->next=newnode; } } //这两种方法的本质都是找到倒数第二个节点 //第一种尾删的方法 void SLTPopBack(SLT** pphead) { assert(*pphead); SLT* prev=NULL; SLT* tail=*pphead; if(tail->next==NULL) { free(tail); *pphead=NULL; } else { while(tail->next) { prev=tail; tail=tail->next; } free(tail); prev->next=NULL; } } //第二种尾删的方法 //void SLTPopBack(SLT** pphead) //{ // assert(*pphead); // SLT* tail=*pphead; // if(tail->next==NULL)//只有一个节点 // { // free(tail); // *pphead=NULL; // } // else//有多个节点 // { // while(tail->next->next)//这也是找到倒数第二个节点 // { // tail=tail->next; // } // free(tail->next); // tail->next=NULL; // } //} void SLTPopFront(SLT** pphead) { assert(*pphead); SLT* tail=*pphead; if(tail->next==NULL)//一个节点 { free(tail); *pphead=NULL; } else//多个节点 { tail=tail->next; free(*pphead); *pphead=tail; } } int SLTFind(SLT** pphead,SLTDataType x) { assert(*pphead); SLT* try_b=*pphead; int Count=1; while(try_b->next) { if(try_b->data==x) { return Count; } Count++; try_b=try_b->next; } return -1; } int Totalsize(SLT** pphead) { SLT* tail=*pphead; int Count=0; while(tail) { tail=tail->next; Count++; } return Count; } void SLTChange(SLT** pphead,int pos,SLTDataType x) { assert(*pphead); int Count=Totalsize(pphead); assert(pos<=Count); SLT* tail=*pphead; while(pos--) { tail=tail->next; } tail->data=x; } void SLTInsertAfter(SLT** pphead,int pos, SLTDataType x) { if((*pphead)==NULL) { SLTPushFront(pphead, x); } else { SLT* prev=NULL; SLT* tail=*pphead; while(pos--) { prev=tail; tail=tail->next; } SLT* newnode=Buylistnode(x); prev->next=newnode; newnode->next=tail; } } void SLTEraseAfter(SLT** pphead,int pos) { assert(*pphead); if((*pphead)->next==NULL) { SLTPopFront(pphead); } else { SLT* prev=NULL; SLT* taillater=NULL; SLT* tail=*pphead; while(pos--) { prev=tail; tail=tail->next; } taillater=tail->next; free(tail); tail=NULL; prev->next=taillater; } } void SLTDestroy(SLT** pphead) { free(*pphead); *pphead=NULL; }
如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家!