02黑马数据结构笔记之单向链表搭建(list)

02黑马数据结构笔记之单向链表搭建(list)

1 思路:以STL的容器list类似,将各个数据节点存放在链表当中。实现是靠一个结构体来管理各个数据节点

//定义一个节点类型
typedef struct Node{
	//接收任何数据
	void* data; 
	struct Node *next;	
}SNode;

//定义一个结构体管理链表
typedef struct LinkList{
	SNode *head;
	int size;           //链表大小
}SList;                 //和动态数组比,需要容量吗? 不需要,动态且内存不连续,在关系上线性

代码实现:
1)头文件.h:

#ifndef MYLIST_H
#define MYLIST_H

#include<stdio.h>
#include<stdlib.h>

//定义一个节点类型
typedef struct Node{
	//接收任何数据
	void* data; 
	struct Node *next;	
}SNode;

//定义一个结构体管理链表
typedef struct LinkList{
	SNode *head;
	int size;           //链表大小
}SList;                 //和动态数组比,需要容量吗? 不需要,动态且内存不连续,在关系上线性

//使用函数指针对万能数据打印
typedef void(*PrintList)(void* data);

//链表初始化
SList *List_Init();
//链表的打印
int Print_List(SList *l,PrintList print);
//插入链表
int Insert_List(SList *l,int pos,void* data);
//删除一个指定位置链表节点
int Del_List_One(SList *l,int pos);
//查找链表
int Find_List(SList *l,void* data);
//返回第一个节点
void *Get_Effitive_First(SList *l);
//返回链表大小
int Get_Size(SList *l);
//销毁内存
int Destory_List(SList *l);

#endif

2).cpp文件:

#include"MyList.h"

//链表初始化
SList *List_Init(){

	//给结构体赋值
	SList *list=(SList *)malloc(sizeof(SList));
	list->head=(SNode *)malloc(sizeof(SNode));
	list->size=0;
	
	//给头结点赋值
	list->head->data=NULL;
	list->head->next=NULL;

	return list;
}
//链表的打印
int Print_List(SList *l,PrintList print){

	if(l==NULL){
		return -1;
	}

	SNode *pCur=l->head->next;
	while(pCur!=NULL){
		print(pCur->data);  //将参数传给自定义函数打印
		pCur=pCur->next;
	}

	return 0;
}
//利用下标插入链表
int Insert_List(SList *l,int pos,void* data){
	//链表为空,直接返回
	if(l==NULL ){
		return -1;
	}
	//如果下标越界,则插入尾部
	if(pos<0 || pos >= l->size){
		pos=l->size;
	}

	   //插入
	//1.先找到插入点的前一节点——————与C语言用两个节点插入的有点差别,但道理是一样的
	SNode *pCur=l->head;
	for(int i=0;i<pos-1;i++){
		pCur=pCur->next;
	}

	//2.创建新节点
	SNode *New=(SNode*)malloc(sizeof(SNode));
	New->data=data;
	New->next=NULL;

	//3.与链表建立关系
	New->next=pCur->next;
	pCur->next=New;

	l->size++;

	return 0;
}
//删除一个指定位置链表节点
int Del_List_One(SList *l,int pos){

	if(l==NULL){
		return -1;
	}
	if(pos<0|| pos >= l->size){
		return -1;
	}
	//找到要删除的节点的前一节点
	SNode *pPre=l->head;	
	for(int i=0;i<pos-1;i++){
		pPre=pPre->next;
	}
	//使用临时变量删除pos节点
	SNode *pCur=pPre->next;

	//删除
	pPre->next=pCur->next;
	free(pCur);
	pCur->next=NULL;

	l->size--;

	return 0;
}
//查找链表 返回第一个相等数据的下标
int Find_List(SList *l,void* data){

	if(l==NULL){
		return -1;
	}
	//计算节点的返回值下标
	int count=0;

	SNode *pCur=l->head->next;
	while(pCur!=NULL){
		if(pCur->data==data){
			break;
		}
		pCur=pCur->next;
		count++;
	}
	//判断是否找到
	if(count==l->size){
		printf("找到链表尾部,没找到\n");
		return -1;
	}

	return count;

}
//返回第一个节点
void *Get_Effitive_First(SList *l){
	return l->head->next->data;
}
//返回链表大小
int Get_Size(SList *l){
	return l->size;
}
//销毁内存
int Destory_List(SList *l){

	if(l==NULL){
		return -1;
	}
	//销毁内存
	while(l->head!=NULL){
		SNode *pCur=l->head->next;
		free(l->head);
		//l->head->next=NULL; //可以不要
		l->head=pCur;
	}

	//最后释放管理链表的结构体内存
	free(l);

	return 0;
}

3)主函数测试:

#include"MyList.h"

//自定义数据类型
typedef struct Student{
	char name[64];
	int age;
	int score;
}Stu;

//回调打印函数 打印时需要用户自定义一个打印函数传进来
void MyPrint(void *data){
	//将void*数据转成用户自定义数据
	Stu *s=(Stu*)data;
	printf("名字:%s 年龄:%d 分数:%d\n",s->name,s->age,s->score);
}

void test01(){

	//创建链表
	SList *list=List_Init();

	//创建数据
	Stu s1={"aaa",18,100};
	Stu s2={"bbb",19,77};
	Stu s3={"ccc",20,88};
	Stu s4={"ddd",22,99};
	Stu s5={"eee",12,59};

	//插入数据 因为是void*,所以要传地址
	Insert_List(list,0,&s1);
	Insert_List(list,0,&s2);
	Insert_List(list,0,&s3);
	Insert_List(list,0,&s4);
	Insert_List(list,0,&s5);

	//打印数据    需要给函数指针传函数名调用该自定义函数
	Print_List(list,MyPrint);

	printf("============\n");

	//删除
	Del_List_One(list,3);
	Print_List(list,MyPrint);

	//返回第一个有效节点
	printf("============\n");
	Stu *s=(Stu*)Get_Effitive_First(list);
	printf("名字:%s 年龄:%d 分数:%d\n",s->name,s->age,s->score);

	printf("============\n");
	//查找
	int pos=Find_List(list,&s2);
	printf("查找到的节点下标:%d\n",pos);
	Del_List_One(list,pos);
	Print_List(list,MyPrint);

	//返回链表大小
	int size=Get_Size(list);
	printf("链表大小为:%d\n",size);

	//销毁内存
	Destory_List(list);

}

int main(){

	test01();

	return 0;
}

发布了54 篇原创文章 · 获赞 1 · 访问量 715

猜你喜欢

转载自blog.csdn.net/weixin_44517656/article/details/105286696
今日推荐