数据结构和算法系列 - 双向链表结构

来源:互联网 发布:基本法知乎 编辑:程序博客网 时间:2024/05/09 01:50

双向链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

双向链表的数据结构中,会有两个比较重要的参数:pre和next。pre指向前一个数据结构。next指向下一个数据结构。


双向链表的基本操作

我们介绍一些基本的操作。

1. 添加元素。添加元素包括头插法和尾插法。无论是头插法还是尾部插入法,都需要考虑到数据结构中存储的头部和尾部的指针变化。

头插法:将链表的左边称为链表头部,右边称为链表尾部。头插法将右边固定,每次新增的元素都在左边头部增加。

尾插法:将链表的左边称为链表头部,右边称为链表尾部。尾插法是将左边固定,每次新增都在链表的右边最尾部。


2. 查询元素。通过元素信息来查询相关的ITEM,需要从头部遍历到尾部。双向链表有一个好处就是,知道链表中的一个元素结构就可以向左或者向右开始遍历查找需要的元素结构。


3. 删除元素。删除一个元素后,需要将元素左边Item存储的next元素的值指向到该删除元素右边的值,将右边的Item存储的pre元素的值指向删除元素的左边。


双向链表结构体定义

我们定义了一个结构体,结构体中username和age分别用来存储用户名和年龄,而next则用来存储下一个Item元素的内存地址,pre来存储左边Item元素的内存地址。

/** * 定义一个双链表数据结构 */typedef struct double_linke_list_s {char * username;unsigned int age;struct double_linke_list_s *pre; //指向前一个指针节点struct double_linke_list_s *next; //指向下一个指针节点} double_linked_list;

定义两个指针变量,分表指向链表的首部和尾部。

/** * 定义一个双向链表,指向链表的头部 */double_linked_list *head;/** * 定义一个双向链表指向链表的尾部 */double_linked_list *end;

定义四个方法:

/** * 插入一条记录 */void add(char *username, unsigned int age);/** * 从头部读取获取一条记录 */double_linked_list *head_search(char *username);/** * 从尾部读取获取一条记录 */double_linked_list *end_search(char *username);/** * 删除一条记录 */void del(char *username);

具体实现

1. 添加操作,我们使用了尾插入法。

void add(char *username, unsigned int age) {double_linked_list * temp = (double_linked_list *) malloc(sizeof(double_linked_list));if (temp != NULL ) {temp->username = username;temp->age = age;temp->pre = NULL;temp->next = NULL;if (head == NULL ) {head = temp;} else {double_linked_list *temp_list = head;double_linked_list *temp_pre = head;while (temp_list->next != NULL ) {temp_list = temp_list->next;temp_pre = temp_list;}temp_list->next = temp;temp->pre = temp_pre;}end = temp;}}

2. 从双向链表头部开始查询

double_linked_list *head_search(char *username) {if (head == NULL ) {return NULL ;}double_linked_list *temp = NULL;double_linked_list *temp_list = head;while (temp_list->next != NULL ) {if (strcmp(temp_list->username, username) == 0) {temp = temp_list;break;} else {temp_list = temp_list->next;}}if (temp_list->next == NULL ) {if (strcmp(temp_list->username, username) == 0) {temp = temp_list;}}return temp;}

3. 从双向链表尾部开始查询

double_linked_list *end_search(char *username) {if (end == NULL ) {return NULL ;}double_linked_list *temp = NULL;double_linked_list *temp_list = end;while (temp_list->pre != NULL ) {if (strcmp(temp_list->username, username) == 0) {temp = temp_list;break;} else {temp_list = temp_list->pre;}}if (temp_list->pre == NULL ) {if (strcmp(temp_list->username, username) == 0) {temp = temp_list;}}return temp;}

4. 删除一个元素

/** * 删除一条记录 */void del(char *username) {if (head == NULL ) {return;}if (head->pre == NULL && head->next == NULL ) {free(head);free(end);head = NULL;end = NULL;return;}double_linked_list *temp_next = NULL; //下一个元素double_linked_list *temp_current = head; //当前元素double_linked_list *temp_pre = NULL; //前一个元素while (temp_current->next != NULL ) {if (strcmp(temp_current->username, username) == 0) {if (temp_pre != NULL ) {temp_pre->next = temp_next;}if (temp_next != NULL) {temp_next->pre = temp_pre;}break;}temp_pre = temp_current;temp_current = temp_current->next;if (temp_current->next != NULL ) {temp_next = temp_current->next;}}if (end == temp_current) {end = temp_pre;}if (head == temp_current) {head = head->next;}free(temp_current);}

完整例子

double_linked_list.h

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <ctype.h>/** * 定义一个双链表数据结构 */typedef struct double_linke_list_s {char * username;unsigned int age;struct double_linke_list_s *pre; //指向前一个指针节点struct double_linke_list_s *next; //指向下一个指针节点} double_linked_list;/** * 定义一个双向链表,指向链表的头部 */double_linked_list *head;/** * 定义一个双向链表指向链表的尾部 */double_linked_list *end;/** * 插入一条记录 */void add(char *username, unsigned int age);/** * 从头部读取获取一条记录 */double_linked_list *head_search(char *username);/** * 从尾部读取获取一条记录 */double_linked_list *end_search(char *username);/** * 删除一条记录 */void del(char *username);

double_linked_list.c

#include "double_linked_list.h"void add(char *username, unsigned int age) {double_linked_list * temp = (double_linked_list *) malloc(sizeof(double_linked_list));if (temp != NULL ) {temp->username = username;temp->age = age;temp->pre = NULL;temp->next = NULL;if (head == NULL ) {head = temp;} else {double_linked_list *temp_list = head;double_linked_list *temp_pre = head;while (temp_list->next != NULL ) {temp_list = temp_list->next;temp_pre = temp_list;}temp_list->next = temp;temp->pre = temp_pre;}end = temp;}}double_linked_list *head_search(char *username) {if (head == NULL ) {return NULL ;}double_linked_list *temp = NULL;double_linked_list *temp_list = head;while (temp_list->next != NULL ) {if (strcmp(temp_list->username, username) == 0) {temp = temp_list;break;} else {temp_list = temp_list->next;}}if (temp_list->next == NULL ) {if (strcmp(temp_list->username, username) == 0) {temp = temp_list;}}return temp;}double_linked_list *end_search(char *username) {if (end == NULL ) {return NULL ;}double_linked_list *temp = NULL;double_linked_list *temp_list = end;while (temp_list->pre != NULL ) {if (strcmp(temp_list->username, username) == 0) {temp = temp_list;break;} else {temp_list = temp_list->pre;}}if (temp_list->pre == NULL ) {if (strcmp(temp_list->username, username) == 0) {temp = temp_list;}}return temp;}/** * 删除一条记录 */void del(char *username) {if (head == NULL ) {return;}if (head->pre == NULL && head->next == NULL ) {free(head);free(end);head = NULL;end = NULL;return;}double_linked_list *temp_next = NULL; //下一个元素double_linked_list *temp_current = head; //当前元素double_linked_list *temp_pre = NULL; //前一个元素while (temp_current->next != NULL ) {if (strcmp(temp_current->username, username) == 0) {if (temp_pre != NULL ) {temp_pre->next = temp_next;}if (temp_next != NULL) {temp_next->pre = temp_pre;}break;}temp_pre = temp_current;temp_current = temp_current->next;if (temp_current->next != NULL ) {temp_next = temp_current->next;}}if (end == temp_current) {end = temp_pre;}if (head == temp_current) {head = head->next;}free(temp_current);}



0 0
原创粉丝点击