对于c语言的单链表来说,应该是数据结构中比较简单的一类结构,我们只要认识链表结构,对指针和结构体掌握好,其实编写代码并不算太难。
链表结构:
对于链表中的每一个结点,我们可以定义如下的结构体:
基本操作:
1.创造结点:
为新节点newnode动态开辟一块空间,结点值为x,指针域指向NULL
2.头插结点:
在进行头插元素的时候,第一步和第二步不能进行交换,如果先进pre->next=s,此时pre->next指向了s,在进行s->next=pre->next,就会使s->next指向自己本身,无法达到预期效果
3.头删结点:
直接将头指针指向原来指向的下一个位置,即pplist->next=cur->next
4.尾插:
当链表为空时,直接将pplist指针指向这个新结点即可;当链表不为空时,则需循环遍历链表,找到链表中最后一个结点,然后将其的next域指向新节点,即cur->next=newnode,此时,不需要将新节点的next域赋值为空,因为在创建结点函数中已将next域赋值为空
5.尾删:
当链表中只有一个结点时候,直接将其free掉;当链表中有多个结点时,用俩个指针依次向后遍历,直到快指针的next为空,此时慢指针指向链表中倒数第二个节点,直接将其指向空即可。
5.任意位置后插入元素:
给定一个位置pos,在其后面插入新节点,这种情况与头插法类似,只是在链表中间进行头插,只需要按照头插法的方法即可。
6.任意位置后删除元素:
对于这种情况,同样是给定一个位置,如果此位置为空或者它的next为空,则无法删除,直接返回;如果给定位置正常,则直接将给定位置的next指向,给定位置的next的next。
7.查找元素:
在查找元素的时候,只需遍历一遍链表,找到链表当中值与要查找的值相同的结点,并返回(注意,链表中各节点值不相同)。
完整代码:
SList.h#pragma once
typedef int DateType;
typedef struct SListNode
{DateType data;struct SListNode* next;
}SListNode;// 动态申请一个结点
SListNode* BuySListNode(DateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, DateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, DateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, DateType x);
// 单链表在pos位置之后插入x
SListNode* SListInsertAfter(SListNode* pos, DateType x);
// 单链表删除pos位置之后的值
SListNode* SListEraseAfter(SListNode* pos);
//销毁单链表
void SListDestory(SListNode** pplist);
//统计链表元素个数
int SListSize(SListNode* plist);void Test();
SList.c#include"SList.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//创造结点
SListNode* BuySListNode(DateType x)
{SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));if (newnode == NULL){exit(0);}newnode->data = x;newnode->next = NULL;return newnode;
}
//尾插
void SListPushBack(SListNode** pplist, DateType x)
{assert(pplist != NULL);if (NULL == *pplist){*pplist = BuySListNode(x);}else{// pplist的链表不为空// 1. 找到原链表中的最后一个节点SListNode* cur = *pplist;while (cur->next){cur = cur->next;}// 2. 插入新节点cur->next = BuySListNode(x);}
}
//尾删
void SListPopBack(SListNode** pplist)
{assert(pplist != NULL);//1.链表中午结点if (NULL == *pplist)return;else if (NULL == (*pplist)->next){// 2. 链表中只有一个节点free(*pplist);*pplist = NULL;}else{// 3. 链表中有多个节点(至少是2个)// a. 找到最后一个节点并保存其前一个节点SListNode* cur = *pplist;SListNode* prev = NULL; // 保存cur的前一个节点while (cur->next){prev = cur;cur = cur->next;}// cur是最后一个节点 prev刚好是cur的前一个free(cur);prev->next = NULL;/*方法二:1. 找到链表倒数第二个节点while(cur->next->next){cur = cur->next;}// 2. 删除最后一个节点;cur刚好是最后一个节点的前一个节点free(cur->nexr);cur->next = NULL;*/}}
//头插
void SListPushFront(SListNode** pplist, DateType x)
{assert(pplist != NULL);//创造一个新结点SListNode* newnode = BuySListNode(x);newnode->next = *pplist;*pplist = newnode;}
//头删
void SListPopFront(SListNode** pplist)
{assert(pplist != NULL);if (*pplist == NULL){printf("链表为空!!!\n");return;}else{SListNode* cur = *pplist;*pplist = cur->next;free(cur);cur = NULL;}
}
SListNode* SListInsertAfter(SListNode* pos, DateType x)
{if (pos){return;}SListNode* newnode = BuySListNode(x);newnode->next = pos->next;pos->next = newnode;
}
SListNode* SListEraseAfter(SListNode* pos)
{if (pos||pos->next){return;}SListNode* p = pos->next;pos->next = p->next;free(p);p = NULL;
}
//查找元素
SListNode* SListFind(SListNode* plist, DateType x)
{SListNode* cur = plist;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
//统计链表的元素个数
int SListSize(SListNode* plist)
{SListNode* cur = plist;int count = 0;while (cur){count++;cur = cur->next;}return count;
}
//销毁链表
void SListDestory(SListNode** pplist)
{assert(pplist != NULL);SListNode* cur = *pplist;while (cur){*pplist = cur->next;free(cur);cur = *pplist;}*pplist = NULL;
}
//打印单链表
void SListPrint(SListNode* plist)
{SListNode* p = plist;while (p != NULL){printf("%d---->", p->data);p = p->next;}printf("NULL\n");
}void Test()
{SListNode* s =NULL;SListPushBack(&s,1);SListPushBack(&s, 2);SListPushBack(&s, 3);SListPushBack(&s, 4);SListPushBack(&s, 5);SListPopBack(&s);SListPushFront(&s, 4);SListPushFront(&s, 3);SListPushFront(&s, 2);SListPushFront(&s, 1);SListPrint(s);int num=SListSize(s);printf("\nnum=%d\n", num);SListDestory(&s);
}
SList_Main.c#include"SList.h"int main()
{Test();return 0;
}