zoukankan      html  css  js  c++  java
  • 【数据结构】——较规范的链表操作方法

      net小伙曾在文章【数据结构】双向链表的创建和读取【数据结构】链式线性表的几种常用用法中写过关于线性表的操作方法,重新阅读发现代码很是稚嫩,现重新整理。

      一般情况下我们会使用一个结构体head来作为双向链表的头部,head有两个指针域,一个指向链表的开始,一个指向链表的末尾。双向链表的指针域也有两个,一个指向前一个节点,一个指向后一个节点。两个结构体定义如下:

     1 #define TAILQ_HEAD(name, type)          
     2   struct name {                           
     3       struct type *tqh_first; /* first element */      
     4       struct type **tqh_last; /* addr of last next element */    
     5   }   
     6 #define TAILQ_ENTRY(type)                       
     7     struct {                                
     8         struct type *tqe_next;  /* next element */          
     9         struct type **tqe_prev; /* address of previous next element */  
    10     }

      使用二级指针是为了在遍历链表和删除链表的时候,代码更具有可读性。

      完整的链表拓扑如下:

      接下来直接给出代码,并附上一个小例子:

     1 #define TAILQ_HEAD(name, type)                  
     2         struct name {                                                   
     3                 struct type *tqh_first; /* first element */              
     4                 struct type **tqh_last; /* addr of last next element */    
     5         }
     6 #define TAILQ_ENTRY(type)                       
     7         struct {                                
     8                 struct type *tqe_next;  /* next element */          
     9                 struct type **tqe_prev; /* address of previous next element */  
    10         }
    11 
    12 #define TAILQ_FIRST(head)   ((head)->tqh_first)
    13 #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
    14 #define TAILQ_EMPTY(head)   ((head)->tqh_first == NULL)
    15 #define TRASHIT(x)  do {(x) = (void *)-1;} while (0)
    16 
    17 #define TAILQ_INIT(head) do {                       
    18         TAILQ_FIRST((head)) = NULL;                 
    19         (head)->tqh_last = &TAILQ_FIRST((head));            
    20 } while (0)
    21 
    22 #define TAILQ_INSERT_HEAD(head, elm, field) do {            
    23         if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)   
    24                 TAILQ_FIRST((head))->field.tqe_prev =           
    25                 &TAILQ_NEXT((elm), field);              
    26         else                                
    27                 (head)->tqh_last = &TAILQ_NEXT((elm), field);       
    28         TAILQ_FIRST((head)) = (elm);                    
    29         (elm)->field.tqe_prev = &TAILQ_FIRST((head));           
    30 } while (0)
    31 
    32 #define TAILQ_INSERT_TAIL(head, elm, field) do {            
    33         TAILQ_NEXT((elm), field) = NULL;                
    34         (elm)->field.tqe_prev = (head)->tqh_last;           
    35         *(head)->tqh_last = (elm);                  
    36         (head)->tqh_last = &TAILQ_NEXT((elm), field);           
    37 } while (0)
    38 
    39 #define TAILQ_FOREACH(var, head, field)                 
    40         for ((var) = TAILQ_FIRST((head));               
    41                         (var);                          
    42                         (var) = TAILQ_NEXT((var), field))
    43 
    44 #define TAILQ_REMOVE(head, elm, field) do {             
    45         if ((TAILQ_NEXT((elm), field)) != NULL)             
    46                 TAILQ_NEXT((elm), field)->field.tqe_prev =      
    47                 (elm)->field.tqe_prev;              
    48         else {                              
    49                 (head)->tqh_last = (elm)->field.tqe_prev;       
    50         }                               
    51         *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);      
    52         TRASHIT((elm)->field.tqe_next);                 
    53         TRASHIT((elm)->field.tqe_prev);                 
    54 } while (0)
    queue.h
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 #include "queue.h"
     6 
     7 typedef struct _student_data {
     8         char name[64];
     9         int age;
    10 }student_data_t;
    11 
    12 typedef struct _student_info{
    13         struct _student_data student_data;
    14         TAILQ_ENTRY(_student_info) next_student;
    15 }student_info_t;
    16 
    17 #define MAX_NUM         4
    18 
    19 TAILQ_HEAD(student_head, _student_info) student_list;
    20 
    21 static student_data_t std[MAX_NUM] = {
    22         {"lilei", 10},
    23         {"hanmeimei", 12},
    24         {"lili", 20},
    25         {"lucy", 21}
    26 };
    27 
    28 void insert_info(int num) {
    29         int i;
    30         student_info_t *student = NULL;
    31 
    32         for (i = 0; i < num; i++) {
    33                 student = (student_info_t *)malloc(sizeof(student_info_t));
    34                 strncpy(student->student_data.name, std[i].name, strlen(std[i].name));
    35                 student->student_data.age = std[i].age;
    36 
    37                 TAILQ_INSERT_TAIL(&student_list, student, next_student);
    38         }
    39 }
    40 
    41 void show_info() {
    42         student_info_t *tmp_info = NULL;
    43 
    44         printf("--------------------------------------------------
    ");
    45         TAILQ_FOREACH(tmp_info, &student_list, next_student) {
    46                 printf("name:%s age:%x
    ", 
    47                                 tmp_info->student_data.name,
    48                                 tmp_info->student_data.age
    49                                 );
    50         }
    51         printf("--------------------------------------------------
    ");
    52 }
    53 
    54 void delete_info() {
    55         student_info_t *tmp_info = NULL;
    56 
    57 #if 0
    58         TAILQ_FOREACH(tmp_info, &student_list, next_student) {
    59                 TAILQ_REMOVE(&student_list, tmp_info, next_student);
    60                 free(tmp_info);
    61         }
    62 #else
    63         while(1) {
    64                 TAILQ_FOREACH(tmp_info, &student_list, next_student) {
    65                         TAILQ_REMOVE(&student_list, tmp_info, next_student);
    66                         free(tmp_info);
    67                         break;
    68                 }
    69                 if (!tmp_info)
    70                         break;
    71         }
    72 #endif
    73 }
    74 
    75 int main(int argc, char *argv[]) {
    76 
    77         TAILQ_INIT(&student_list);
    78 
    79         insert_info(MAX_NUM);
    80         show_info();
    81         delete_info();
    82         show_info();
    83 
    84         return 0;
    85 }
    list.c

      需要注意的是在删除的所有list的时候,不可以直接使用FOREACH遍历,并使用REMOVE进行循环删除。因为REMOVE会把tmp_info的指针域全部置空,FOREACH在下次遍历的时候会直接段错误。

  • 相关阅读:
    Smartforms 设置纸张打印格式
    JVM的垃圾回收算法
    JVM垃圾回收器
    Java类加载过程
    Java内存模型
    计算机模型
    C#----对时间结构DateTime的使用(时间日期的使用)
    C#----我对坐标系的理解和图形转动
    C#----格式化字符串的操作
    其他----
  • 原文地址:https://www.cnblogs.com/ngnetboy/p/5209882.html
Copyright © 2011-2022 走看看