【数据结构】——较规范的链表操作方法
2016-02-23 14:47
369 查看
net小伙曾在文章【数据结构】双向链表的创建和读取和【数据结构】链式线性表的几种常用用法中写过关于线性表的操作方法,重新阅读发现代码很是稚嫩,现重新整理。
一般情况下我们会使用一个结构体head来作为双向链表的头部,head有两个指针域,一个指向链表的开始,一个指向链表的末尾。双向链表的指针域也有两个,一个指向前一个节点,一个指向后一个节点。两个结构体定义如下:
使用二级指针是为了在遍历链表和删除链表的时候,代码更具有可读性。
完整的链表拓扑如下:
list.c
需要注意的是在删除的所有list的时候,不可以直接使用FOREACH遍历,并使用REMOVE进行循环删除。因为REMOVE会把tmp_info的指针域全部置空,FOREACH在下次遍历的时候会直接段错误。
一般情况下我们会使用一个结构体head来作为双向链表的头部,head有两个指针域,一个指向链表的开始,一个指向链表的末尾。双向链表的指针域也有两个,一个指向前一个节点,一个指向后一个节点。两个结构体定义如下:
#define TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ } #define TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ }
使用二级指针是为了在遍历链表和删除链表的时候,代码更具有可读性。
完整的链表拓扑如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "queue.h" typedef struct _student_data { char name[64]; int age; }student_data_t; typedef struct _student_info{ struct _student_data student_data; TAILQ_ENTRY(_student_info) next_student; }student_info_t; #define MAX_NUM 4 TAILQ_HEAD(student_head, _student_info) student_list; static student_data_t std[MAX_NUM] = { {"lilei", 10}, {"hanmeimei", 12}, {"lili", 20}, {"lucy", 21} }; void insert_info(int num) { int i; student_info_t *student = NULL; for (i = 0; i < num; i++) { student = (student_info_t *)malloc(sizeof(student_info_t)); strncpy(student->student_data.name, std[i].name, strlen(std[i].name)); student->student_data.age = std[i].age; TAILQ_INSERT_TAIL(&student_list, student, next_student); } } void show_info() { student_info_t *tmp_info = NULL; printf("--------------------------------------------------\n"); TAILQ_FOREACH(tmp_info, &student_list, next_student) { printf("name:%s age:%x\n", tmp_info->student_data.name, tmp_info->student_data.age ); } printf("--------------------------------------------------\n"); } void delete_info() { student_info_t *tmp_info = NULL; #if 0 TAILQ_FOREACH(tmp_info, &student_list, next_student) { TAILQ_REMOVE(&student_list, tmp_info, next_student); free(tmp_info); } #else while(1) { TAILQ_FOREACH(tmp_info, &student_list, next_student) { TAILQ_REMOVE(&student_list, tmp_info, next_student); free(tmp_info); break; } if (!tmp_info) break; } #endif } int main(int argc, char *argv[]) { TAILQ_INIT(&student_list); insert_info(MAX_NUM); show_info(); delete_info(); show_info(); return 0; }
list.c
需要注意的是在删除的所有list的时候,不可以直接使用FOREACH遍历,并使用REMOVE进行循环删除。因为REMOVE会把tmp_info的指针域全部置空,FOREACH在下次遍历的时候会直接段错误。
相关文章推荐
- 一个数据结构与算法可视化的网站
- 数据结构(11)--串的模式匹配算法之BF、KMP算法
- 数据结构与算法之数组
- 程序员面试题精选100题(39)-颠倒栈[数据结构]
- 程序员面试题精选100题(35)-两链表的第一个公共结点[数据结构]
- 程序员面试题精选100题(33)-在O(1)时间删除链表结点[数据结构]
- 程序员面试题精选100题(31)-从尾到头输出链表[数据结构]
- 数据结构笔记-----数据结构与算法
- 程序员面试题精选100题(27)-二元树的深度[数据结构]
- 程序员面试题精选100题(24)-栈的push、pop序列[数据结构]
- 《数据结构与算法分析(c 描述)》—— 第六章笔记
- 把数组排成最小的数
- 数据结构: 树
- 数据结构基础 之 图 的 邻接矩阵实现与邻接表实现
- “树”不倒,人不散—数据结构的核心
- 数据结构之队列(三)
- 数据结构中链式存储的注意点(线性与栈)
- brother[扫描线]
- [数据结构]Life_Game
- 程序员面试题精选100题(19)-反转链表[数据结构]