数据结构——链表 1
数据结构——链表1
//链表结点数据类型
struct linknode
{
void * data;
struct linknode *next;
};
//链表数据类型
//记录链表信息,链表头结点,大小等信息
struct linklist
{
struct linknode header;//拿到链表的头结点就相当于拿到整个链表
//也可以*header,但是这个时候要给header分配内存,略显麻烦
int size;//链表的大小
};
说明:在定义结构体的头节点时,如果是个指针类型,比如struct linknode *header;
那么必须在下面malloc必要的内存空间,(在struct linknode里面也是指针类型,一次还要多次malloc出内存空间)为了方便起见这里不用指针类型。
链表的初始化操作
void* Init_list()
{
struct linklist *list = malloc(sizeof(struct linklist));
if(list == NULL)
{
return NULL;
}
list->header.next = NULL;//初始化链表时只有一个头结点,其余为空
}
链表的插入操作
TIP:如果完成插入操作,必须找到插入节点的前一个位置。
编程核心思路:①首先找到要插入节点的前一个节点,利用for循环来实现。②需要一个当前指针,来记录这个节点struct linknode *current = &(mylist->header);
之所以这样,就可以在for循环中用current = current->next;
(我更喜欢叫这个为“代理人战争”,header毕竟是“带头大哥”不能亲自出马,哈哈~皮一下)。③接着,需要newnode节点,完成插入操作
代码实现如下:
//插入节点
void insert_link(void *list,int pos,void* data)
{
int i = 0;
struct linklist *mylist = (struct linklist *)list;
struct linknode *current = &(mylist->header);
struct linknode *newnode = malloc(sizeof(struct linknode));
newnode->data = data;
newnode->next = NULL;
if(list == NULL)
{
return;
}
if(data ==NULL)
{
return;
}
if(pos < 0 || pos > mylist->size-1)
{
pos = mylist->size;
}
//找到要插入的位置,利用for循环
for(i = 0;i<pos;i++)
{
current = current->next;
}
newnode->next = current->next;
current->next = newnode;
mylist->size++;//记录节点个数
}
遍历节点
编程核心思考:①采用回调函数的方式打印出数据。②因为要传入链表,传入节点所以定义如下struct linklist *mylist = (struct linklist *)list; struct linknode *current = mylist->header.next ;
实现代码如下:
//遍历链表
void Foreach_linklist(void *list,void(*reback)(void *))
{
struct linklist *mylist = (struct linklist *)list;
struct linknode *current = mylist->header.next ;
if(list == NULL)
{
return;
}
while(current != NULL)
{
reback(current->data);
current = current->next;
}
}
下面贴出全部的代码,经过测试的,代码比较长,得耐心看。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**************************************************
*特点:链表包含两个域数据域和指针域
* 链表访问时单线访问的
* 链表由一系列节点组成,数据域保存用户数据
* 指针域保存下一个节点的地址
* 链表在内存中是非连续的
***************************************************/
//==========测试数据=============================
struct person
{
char name[30];
int age;
};
//==============================================
//链表结点数据类型
struct linknode
{
void * data;
struct linknode *next;
};
//链表数据类型
//记录链表信息,链表头结点,大小等信息
struct linklist
{
struct linknode header;//拿到链表的头结点就相当于拿到整个链表
//也可以*header,但是这个时候要给header分配内存,略显麻烦
int size;//链表的大小
};
//初始化链表
typedef void *LList;
void* Init_list()
{
struct linklist *list = malloc(sizeof(struct linklist));
if(list == NULL)
{
return NULL;
}
list->header.next = NULL;
list->size = 0;
return list;
}
//插入节点
void insert_link(void *list,int pos,void* data)
{
int i = 0;
struct linklist *mylist = (struct linklist *)list;
struct linknode *current = &(mylist->header);
struct linknode *newnode = malloc(sizeof(struct linknode));
newnode->data = data;
newnode->next = NULL;
if(list == NULL)
{
return;
}
if(data ==NULL)
{
return;
}
if(pos < 0 || pos > mylist->size-1)
{
pos = mylist->size;
}
//找到要插入的位置,利用for循环
for(i = 0;i<pos;i++)
{
current = current->next;
}
newnode->next = current->next;
current->next = newnode;
mylist->size++;
}
//打印函数
void print(void *data)
{
struct person* data1 = (struct person*)data;
printf("姓名:%s,年龄:%d\r\n",data1->name ,data1->age);
}
//遍历链表
void Foreach_linklist(void *list,void(*reback)(void *))
{
struct linklist *mylist = (struct linklist *)list;
struct linknode *current = mylist->header.next ;
if(list == NULL)
{
return;
}
while(current != NULL)
{
reback(current->data);
current = current->next;
}
}
int main()
{
int i;
//创建一些数据便于测试
struct person s1 = {"xioming",20};
struct person s2 = {"xiaoli",23};
struct person s3 = {"xiaozhang",24};
//创建一个链表
struct linklist *list = NULL;
list = Init_list();//初始化
//插入链表
insert_link(list,0,&s1);
insert_link(list,0,&s2);
insert_link(list,0,&s3);
//遍历链表并打印
Foreach_linklist(list,print);
return 0;
}