您的位置:首页 > 理论基础 > 数据结构算法

【数据结构】——较规范的链表操作方法

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

  一般情况下我们会使用一个结构体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在下次遍历的时候会直接段错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: