7.数据结构之双链表
双链表每个节点的结构体
struct node {
数据;
struct node *next; // 保存下一个节点的首地址
struct node *prev; // 保存上一个节点的首地址
};
参见图:双链表.png
参考代码:list2.c
/*双链表演示*/
#ifndef __LIST_H
#define __LIST_H
#include <stdio.h>
#include <stdlib.h>
/*声明描述节点信息的结构体*/
typedef struct node {
int data; //数据
struct node *next; //指向下一个节点
struct node *prev; //指向上一个节点
}node_t;
/*声明描述整个链表的结构体*/
typedef struct list {
struct node head; //头节点
struct node tail; //尾节点
}list_t;
/*声明初始化链表函数*/
extern void list_init(list_t *);
/*清理链表函数*/
extern void list_deinit(list_t *);
/*判断链表是否为空,空返回1,非空返回0*/
extern int list_empty(list_t *);
/*获取链表节点个数*/
extern int list_size(list_t *);
/*后插*/
extern void list_add_tail(list_t *, int);
/*前插*/
extern void list_add_head(list_t *, int);
/*小->大插*/
extern void list_add(list_t *, int);
/*只删除第一个节点*/
extern void list_del_head(list_t *);
/*只删除最后一个节点*/
extern void list_del_tail(list_t *);
/*删除某个数字所在的节点*/
extern void list_del(list_t *, int );
/*只获取第一个节点数据*/
extern int list_get_head(list_t *);
/*只获取最后一个节点数据*/
extern int list_get_tail(list_t *);
/*通过节点编号获取节点数据*/
extern int list_get(list_t *, int);
#endif
#include "list.h"
/*定义初始化链表函数*/
/*空链表:head和tail连起来*/
void list_init(list_t *list)
{
list->head.next = &list->tail; //头指向尾
list->tail.prev = &list->head; //尾指向头
list->head.prev = NULL;
list->tail.next = NULL;
}
/*判断链表是否为空*/
int list_empty(list_t *list)
{
return list->head.next == &list->tail; //空返回1,非空返回0
}
/*获取链表节点个数*/
int list_size(list_t *list)
{
int count = 0; //计数
for(node_t *pnode = &list->head;
pnode != &list->tail; pnode = pnode->next) {
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid != &list->tail)
count++; //只要没有到tail,加一个
}
return count;
}
//定义创建节点函数
static node_t *create_node(int data)
{
//给节点分配内存
node_t *p = (node_t *)malloc(sizeof(node_t));
//初始化节点
p->next = NULL;
p->prev = NULL;
p->data = data;
return p;
}
//定义将新节点插入pfirst和pmid之间
static void insert_data(node_t *pfirst, node_t *pmid, node_t *pnode)
{
//将新节点插入pfirst和pmid之间
pfirst->next = pnode;
pnode->prev = pfirst;
pnode->next = pmid;
pmid->prev = pnode;
}
/*后插*/
void list_add_tail(list_t *list, int data)
{
//创建新节点
node_t *pnode = create_node(data);
//定义游标:随意定游标,这个代码仅仅参考
node_t *pfirst = list->tail.prev; //pfirst指向最后一个节点
node_t *pmid = pfirst->next; //pmid指向tail
node_t *plast = pmid->next; //plast指向NULL
//插入
insert_data(pfirst, pmid, pnode);
}
/*前插*/
void list_add_head(list_t *list, int data)
{
//创建新节点
node_t *pnode = create_node(data);
//定义游标
node_t *pfirst = &list->head; //pfirst指向head
node_t *pmid = pfirst->next; //pmid指向第一个节点
node_t *plast = pmid->next; //plast指向第二个节点
//插入
insert_data(pfirst, pmid, pnode);
}
/*由小到大插*/
void list_add(list_t *list, int data)
{
//1.创建新节点
node_t *pnode = create_node(data);
//2.遍历
for(node_t *ptmp = &list->head;
ptmp != &list->tail; ptmp = ptmp->next) {
//3.游标
node_t *pfirst = ptmp;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
//4.将新节点同样插入到pfirst和pmid之间
if(pmid->data > pnode->data || pmid == &list->tail) {
insert_data(pfirst, pmid, pnode); //插入
break;
}
}
}
//删除节点
static void del_data(node_t *pfirst, node_t *pmid, node_t *plast)
{
//1.连接pfirst和plast,干掉pmid
pfirst->next = plast;
plast->prev = pfirst;
//2.释放pmid的内存
free(pmid);
pmid = NULL;
}
/*删除最后一个节点*/
void list_del_tail(list_t *list)
{
//1.判断是否空链表
if(list->head.next == &list->tail) {
printf("链表空了.\n");
return;
}
//2.定义游标
node_t *plast = &list->tail; //plast指向tail
node_t *pmid = plast->prev; //pmid指向最后一个节点
node_t *pfirst = pmid->prev; //pfirst指向倒数第二个节点
//3.删除数据
del_data(pfirst, pmid, plast);
}
/*删除第一个节点*/
void list_del_head(list_t *list)
{
/*1.判断链表是否为空*/
if(list_empty(list)) {
printf("链表空了.\n");
return;
}
//2.定义游标
node_t *pfirst = &list->head; //pfirst指向头节点
node_t *pmid = pfirst->next; //pmid指向第一个节点
node_t *plast = pmid->next; //plast指向第二个节点
//3.删除数据
del_data(pfirst, pmid, plast);
}
/*删除某个数字所在的节点*/
void list_del(list_t *list, int data)
{
//通过data遍历遍历找到要删除的节点pmid
for(node_t *pnode = &list->head;
pnode != &list->tail; pnode=pnode->next) {
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
if(pmid->data == data && pmid != &list->tail) {
//删除数据
del_data(pfirst, pmid, plast);
}
}
}
/*获取最后一个节点的数据并返回*/
int list_get_tail(list_t *list)
{
//判断链表是否为空
if(list_empty(list))
return -1;
//定义游标
node_t *plast = &list->tail; //plast指向tail
node_t *pmid = plast->prev; //pmid指向最后一个节点
node_t *pfirst = pmid->prev; //pfirst指向倒数第二个节点
//返回pmid指向的最后一个节点中的数据
return pmid->data;
}
/*获取第一个节点的数据并返回*/
int list_get_head(list_t *list)
{
//判断链表是否为空
if(list_empty(list))
return -1;
//定义游标
node_t *pfirst = &list->head; //pfirst指向head
node_t *pmid = pfirst->next; //pmid指向第一个节点
node_t *plast = pmid->next; //pfirst指向第二个节点
//返回pmid指向的第一个节点中的数据
return pmid->data;
}
/*根据节点编号获取对应的数据*/
int list_get(list_t *list, int index)
{
//1.计数
int count = 0;
//2.找节点
for(node_t *pnode = &list->head;
pnode != &list->tail; pnode=pnode->next) {
//3.定义游标
node_t *pfirst = pnode;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
//4.判断count和index
if(count == index && pmid != &list->tail) {
return pmid->data;
}
count++;
}
return -1; //没有找到
}
/*清理链表*/
void list_deinit(list_t *list)
{
while(list->head.next != &list->tail) {
//定义游标
node_t *pfirst = &list->head;
node_t *pmid = pfirst->next;
node_t *plast = pmid->next;
//先连接pfirst和plast
pfirst->next = plast;
plast->prev = pfirst;
//干掉pmid节点的内存
free(pmid);
pmid = NULL;
}
}
#include "list.h"
int main(void)
{
//1.创建链表
list_t list;
//2.初始化链表
list_init(&list);
//3.前插
list_add_head(&list, 50); //50
list_add_head(&list, 20); //20 50
//4.后插
list_add_tail(&list, 70); //20 50 70
list_add_tail(&list, 100); //20 50 70 100
//5.小到大插
list_add(&list, 80);
list_add(&list, 30);
list_add(&list, 40);
list_add(&list, 60);
list_add(&list, 90);
list_add(&list, 10);
//6.获取节点个数
int size = list_size(&list);
printf("节点个数为%d\n", size);
//7.打印节点数据
for(int i = 0; i < size; i++) {
printf("%d ", list_get(&list, i));
}
printf("\n");
//8.获取第一个节点数据
printf("第一个节点数据是%d\n", list_get_head(&list));
//9.获取最后一个节点数据
printf("最后一个节点数据是%d\n", list_get_tail(&list));
//10.删除第一个节点
list_del_head(&list);
//11.删除最后一个节点
list_del_tail(&list);
//12.删除50所在的节点
list_del(&list, 50);
//13.打印节点数据
for(int i = 0; i < list_size(&list); i++) {
printf("%d ", list_get(&list, i));
}
printf("\n");
//14.清理
list_deinit(&list);
return 0;
}