1-单向链表
笔记
链表是一种线性的链式存储结构,可以不用事先确定节点的个数,插入删除节点需要的操作量较少。但只能通过遍历链表来查找想找的节点。
每个节点用一个结构体表示,节点结构体内分成两部分(数据域、指针域)。指针域用来指向下一个节点、数据域存放数据。
单向链表需要维护一个头节点,之后所有的操作都需要通过头节点。定义一个结构体来管理链表,管理结构体包含一个头节点和记录链表长度的变量。头节点里不存放数据,只用来指向下一节点。最好手动维护链表长度(插入和删除时手动计数),这样不用每次遍历到next==NULL来确认链表结束。
单向链表的结构示意图
要实现的功能
初始化、遍历、插入、按位置删除、按值删除、清空链表、释放链表
代码
myLinkList.c
#include"myLinkList.h"
#include<stdio.h>
#include<stdlib.h>
void SayHello(){
printf("Hello\n");
}
ManageLinkListType* init_ll(){
ManageLinkListType* pmll = malloc(sizeof( ManageLinkListType));
pmll->head.data = NULL;
pmll->head.next = NULL;
pmll->m_szie = 0;
return pmll;
}
//按位置插入数据,这里的data要保证生存周期正常,链表并不维护data的释放
void insert_ll(ManageLinkListType* pmll,int pos, void * data){
if(NULL == pmll){
return;
}
if(pos < 0 || pos > pmll->m_szie){
pos = pmll->m_szie;
}
//创建临时节点,赋值为头节点
struct lNodeStruct * currNode = &(pmll->head);
//将临时节点移动到要插入位置
for(int i=0; i<pos; i++){
currNode = currNode->next;
}
struct lNodeStruct * newNode = malloc(sizeof(struct lNodeStruct));
newNode->data = data;
//插入临时节点所在的位置
newNode->next = currNode->next;
currNode->next = newNode;
pmll->m_szie++;
}
//遍历函数
void foreach_ll(ManageLinkListType* pmll, void(*myForeach)(void*)){
if(NULL == pmll || NULL == myForeach){
return;
}
struct lNodeStruct * currNode = &(pmll->head);
for(int i=0; i<pmll->m_szie; i++){
currNode = currNode->next;
myForeach(currNode->data);
}
}
//删除,通过位置
void remove_ll(ManageLinkListType* pmll, int pos){
if(NULL == pmll || pos>=pmll->m_szie){
return;
}
struct lNodeStruct* currNode = &(pmll->head);
struct lNodeStruct* delNode = NULL;
//找到前驱节点
for(int i=0; i<pos; i++){
currNode = currNode->next;
}
//要删除的节点
delNode = currNode->next;
//将前驱节点的next指向本节点的next(即后驱节点)
currNode->next = delNode->next;
//释放要删除的节点
free(delNode);
delNode = NULL;
pmll->m_szie--;
}
//通过值删除
void removeByVal_ll(ManageLinkListType* pmll,void* data, int (*myCompare)(void*,void*)){
if(NULL==pmll || NULL==data){
return;
}
struct lNodeStruct* currNode = &(pmll->head);
struct lNodeStruct* perNode = &(pmll->head);
for(int i=0;i<pmll->m_szie;i++){
perNode = currNode;
currNode = currNode->next;
if(myCompare(currNode->data,data) ){
perNode->next = currNode->next;
free(currNode);
currNode = NULL;
pmll->m_szie--;
break;
}
}
}
//清除链表
void clear_ll(ManageLinkListType* pmll){
if(NULL==pmll || pmll->m_szie==0){
return;
}
struct lNodeStruct* currNode = pmll->head.next;
struct lNodeStruct* nextNode = NULL;
for(int i=0;i<pmll->m_szie;i++){
nextNode = currNode->next;
free(currNode);
currNode = NULL;
currNode = nextNode;
}
pmll->m_szie = 0;
}
myLinkList.h
#ifndef __MY_LINK_LIST_H
#define __MY_LINK_LIST_H
struct lNodeStruct
{
void * data;
struct lNodeStruct * next;
};
typedef struct
{
struct lNodeStruct head;
int m_szie;
}ManageLinkListType;
void SayHello(void);
ManageLinkListType* init_ll(void);
void insert_ll(ManageLinkListType* pmll,int pos, void * data);
void foreach_ll(ManageLinkListType* pmll, void(*myForeach)(void*));
void remove_ll(ManageLinkListType* pmll, int pos);
void removeByVal_ll(ManageLinkListType* pmll,void* data, int (*myCompare)(void*,void*));
void clear_ll(ManageLinkListType* pmll);
#endif
start0.c
#include "myLinkList.h"
#include<stdio.h>
#include<string.h>
struct Persion{
int m_age;
char m_name[64];
};
void myPrint(void * data){
struct Persion *p = data;
printf("age=%d\tname=%s\n",p->m_age,p->m_name);
}
void test0(ManageLinkListType* pmll){
struct Persion p0={100,"hhhh"};
insert_ll(pmll,0,&p0);
}
int myCompare(void* data1,void* data2){
struct Persion *p1 = data1;
struct Persion *p2 = data2;
if(p1->m_age == p2->m_age){
if(strcmp(p1->m_name,p2->m_name) == 0){
return 1;
}
}
return 0;
}
int main(){
ManageLinkListType* pmll = init_ll();
//test0(pmll);
struct Persion p1={10,"aaaa"};
struct Persion p2={11,"bbbb"};
struct Persion p0={100,"hhhh"};
insert_ll(pmll,0,&p1);
insert_ll(pmll,0,&p2);
insert_ll(pmll,0,&p0);
foreach_ll(pmll,myPrint);
printf("------------------------\n");
//remove_ll(pmll,0);
struct Persion p4={10,"aaaa"};
removeByVal_ll(pmll,&p4,myCompare);
foreach_ll(pmll,myPrint);
printf("----------------------\n");
clear_ll(pmll);
foreach_ll(pmll,myPrint);
free(pmll);
return 0;
}