线性结构——双向链表

一、概念

双向链表概念

( double linked List) 是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以在双向链表中的结点都有两个指针域, 一个指向直接后继,另一个指向直接前驱。

在这里插入图片描述

二、双向不循环链表

在这里插入图片描述

2.1 定义数据类型

typedef void * datatype;
typedef struct list_s
{
  struct list_s *prev;  //指向直接前驱
  datatype data;        //数据域
  struct list_s *next;  //指向直接后驱
}list_t;

2.2 生成头节点

list_t *create_list(void)  //新建双向链表
{
	list_t *list = NULL;
	
	list = malloc(sizeof(*list));
	list->data = NULL;
	list->prev = NULL;
	list->next = NULL;

	return list;
}

2.3 插入节点

2.3.1 头/尾插

enum
{
	HEADLIST,
	TRAILLIST
};

int insert_list (list_t *head,const datatype data,int datasize,int mode)  //头插、尾插数据
{
  list_t *new = NULL;
  list_t *q = NULL;
  
  new = malloc( sizeof(*new) );
  new->data = malloc(sizeof(datasize));
  new->prev = NULL;
  new->next = NULL;
  memcpy(new->data,data,datasize);

  switch(mode) {
	case HEADLIST:
		new->next=head->next;
		new->prev=head;
		head->next->prev = new;  //必须保证至少有一个数据节点
		head->next=new;
		break;
	case TRAILLIST:
      for (q = head; q->next != NULL; q = q->next);
      q->next = new;
      new->prev = q;
		break;
	default:
		free(new->data);
		free(new);
		return -1;
	}

	return 0;
}

2.3.2 选择插

int insert_select_list (list_t *head, int num, datatype data)  //选择插
{
  int i;
  list_t *q = NULL;
  list_t *new = NULL;

  if (doulist_length (head) < num || num <= 1) {
    printf ("insert_select_list num is erorr!\n");
    return -1;
  }
  
  new = malloc( sizeof(*new) );
  new->data = malloc(sizeof (int));
  new->prev = NULL;
  new->next = NULL;
  memcpy(new->data,data,sizeof(int));
  
  for (i = 1, q = head; q->next != NULL; i++, q = q->next) {
    if (i == num) {
      new->next = q->next;
      new->prev = q;
      new->next->prev = new;
      q->next = new;
      return 0;
    } 
  }

  return -1;
}

2.4 打印

int display_list (list_t *head)  //打印链表
{
	list_t *list;
  
  printf ("head : %p <--> ",head);
	for(list = head->next; list != NULL ; list = list->next) {
		printf(" %d - %p < -- > ",*((int *)(list->data)), list);
	}
  printf ("\n");

	return 0;
}

2.5 判空

int isempty_list (list_t *head)  //判空
{
  return head->next == NULL ? 1 : 0;
}

2.6 返回链表长度

int doulist_length (list_t *head) //返回链表长度
{
  int i;
  list_t *q = NULL;

  for (i = 0, q = head; q->next != NULL; q = q->next, i++);

  return i;
}

2.7 删除链表某个节点

int delete_list(list_t *head, const datatype data, int datasize) //删除链表某个节点
{
	list_t *q = NULL;
	if(isempty_list(head))
		return -1;

	for(q = head->next; q != NULL; q = q->next) {
		if(!memcmp(q->data,data,datasize)) {
			q->prev->next=q->next;
			q->next->prev=q->prev;
      free (q->data);
			return -1;
		}
	}
 
	return 0;
}

2.8 排序

int func_order(void *s1, void *s2)        //作为函数指针,顺序
{
	return *((int *)s1) - *((int *)s2);
}

int func_invert(void *s1, void *s2)        //作为函数指针,反序
{
	return *((int *)s2) - *((int *)s1);
}


int sort_list(list_t *head,int (*sort)(void *,void *))  //排序
{
	list_t *p;

	int i, num, length;
  
  length = doulist_length (head);

	for(i = 0; i < length - 1; i++) {
    num = length - i - 1;
    
		for(p = head->next; num > 0; p = p->next, num--)
		{
			if(sort(p->data, p->next->data) > 0) {
				void *tmp = p->data;
				p->data = p->next->data;
				p->next->data = tmp;
			}
		}
	}
	return 0;
}

2.9 查找某个数据

int find_list(list_t *head,const datatype data,int datasize) //查找某个数据
{
	list_t *q = NULL;

	for(q = head->next; q != NULL; q = q->next) {
		if( !memcmp (q->data,data,datasize) ) {
			printf ("find data: %d\n",*((int *)(q->data)));
      return 0;
		}
	}

	return -1;
}

2.10 销毁链表

void destory_list (list_t *head)  //销毁链表
{
	list_t *q = NULL;

	for(q = head->next->next; q != NULL; q = q->next) {
		free(q->prev->data);
		free(q->prev);
	}

	free(head->data);
	free(head);
}

2.11 测试

int main(void)
{
  list_t *list = NULL;
  int data[10] = {8, 10, 7, 1, 6, 4, 9, 2, 3, 5};
  
  list = create_list ();
  if (isempty_list (list) ) {
    printf ("doulist is null !\n");
  }
  insert_list (list, &data[0], sizeof (int), TRAILLIST);
  insert_list (list, &data[1], sizeof (int), TRAILLIST);
  insert_list (list, &data[2], sizeof (int), TRAILLIST);
  insert_list (list, &data[3], sizeof (int), TRAILLIST);
  printf ("tail insert, doulist length is : %d\n",doulist_length(list));
  display_list (list);

  insert_list (list, &data[4], sizeof (int), HEADLIST);
  insert_list (list, &data[5], sizeof (int), HEADLIST);
  insert_list (list, &data[6], sizeof (int), HEADLIST);
  insert_list (list, &data[7], sizeof (int), HEADLIST);
  printf ("head insert, doulist length is : %d\n",doulist_length(list));
  display_list (list);

  insert_select_list (list, 2, &data[8]);
  insert_select_list (list, 2, &data[9]);
  printf ("select insert, doulist length is : %d\n",doulist_length(list));
  display_list (list);

  delete_list(list, &data[1], sizeof (int));
  printf ("delete data: 10, doulist length is : %d\n",doulist_length(list));
  display_list (list);
  
  sort_list (list, func_order);
  printf ("order sort data, doulist length is : %d\n",doulist_length(list));
  display_list (list);

  sort_list (list, func_invert);
  printf ("invert sort data, doulist length is : %d\n",doulist_length(list));
  display_list (list);
  
  find_list(list,  &data[2], sizeof (int));

  destory_list(list);

	return 0;
}

在这里插入图片描述

三、双向循环链表

3.1 定义数据类型

在这里插入图片描述

typedef void * datatype;

typedef struct list_s
{
	struct list_s *prev;  //指向直接前驱
  datatype data;        //数据域
	struct list_s *next;  //指向直接后驱
}list_t;

3.2 生成节点

list_t *create_listloop(void)  //新建双向链表
{
	list_t *list = NULL;
	
	list = malloc(sizeof(*list));
	list->data = NULL;
	list->prev = list;
	list->next = list;

	return list;
}

3.3 插入节点

3.3.1 头/尾插

enum
{
	HEADLIST,
	TRAILLIST
};

int insert_listloop (list_t *head,const datatype data,int datasize,int mode)  //头插、尾插数据
{
	list_t *new = NULL;
  list_t *q = NULL;

	new = malloc( sizeof(*new) );
	new->data = malloc(sizeof(datasize));
  new->prev = NULL;
  new->next = NULL;
	memcpy(new->data,data,datasize);

	switch(mode) {
	case HEADLIST:
		new->next=head->next;
		new->prev=head;
		head->next->prev = new;  //必须保证至少有一个数据节点
		head->next=new;
		break;

	case TRAILLIST:
    for (q = head; q->next != head; q = q->next);
    q->next = new;
    new->next = head;
    new->prev = q;
		break;

	default:
		free(new->data);
		free(new);
		return -1;
	}

	return 0;
}

3.3.2 选择插

int insert_select_listloop (list_t *head, int num, datatype data)  //选择插
{
  int i;
  list_t *q = NULL;
  list_t *new = NULL;

  if (doulistloop_length (head) < num || num <= 1) {
    printf ("insert_select_list num is erorr!\n");
    return -1;
  }
  
  new = malloc( sizeof(*new) );
	new->data = malloc(sizeof (int));
  new->prev = NULL;
  new->next = NULL;
	memcpy(new->data,data,sizeof(int));
  
  for (i = 1, q = head; q->next != head; i++, q = q->next) {
    if (i == num) {
      new->next = q->next;
      new->prev = q;
      new->next->prev = new;
      q->next = new;
      return 0;
    } 
  }

  return -1;
}

3.4 打印

int display_listloop (list_t *head)  //打印链表
{
	list_t *list;
  
  printf ("head : %p <--> ",head);
	for(list = head->next; list != head ; list = list->next) {
		printf(" %d - %p < -- > ",*((int *)(list->data)), list);
	}
  printf ("\n");

	return 0;
}

3.5 判空

int isempty_listloop (list_t *head)  //判空
{
	return head->next == head ? 1 : 0;
}

3.6 返回链表长度

int doulistloop_length (list_t *head) //返回链表长度
{
  int i;
  list_t *q = NULL;

  for (i = 0, q = head; q->next != head; q = q->next, i++);

  return i;
}

3.7 删除链表某个节点

int delete_listloop(list_t *head, const datatype data, int datasize) //删除链表某个节点
{
	list_t *q = NULL;
	if(isempty_listloop(head))
		return -1;

	for(q = head->next; q != head; q = q->next) {
		if(!memcmp(q->data,data,datasize)) {
			q->prev->next=q->next;
			q->next->prev=q->prev;
      free (q->data);
			return -1;
		}
	}
 
	return 0;
}

3.8 排序

int func_order(void *s1, void *s2)        //作为函数指针,顺序
{
	return *((int *)s1) - *((int *)s2);
}

int func_invert(void *s1, void *s2)        //作为函数指针,反序
{
	return *((int *)s2) - *((int *)s1);
}


int sort_listloop(list_t *head,int (*sort)(void *,void *))  //排序
{
	list_t *p;

	int i, num, length;
  
  length = doulistloop_length (head);

	for(i = 0; i < length - 1; i++) {
    num = length - i - 1;
    
		for(p = head->next; num > 0; p = p->next, num--)
		{
			if(sort(p->data, p->next->data) > 0) {
				void *tmp = p->data;
				p->data = p->next->data;
				p->next->data = tmp;
			}
		}
	}
	return 0;
}

3.9 查找某个数据

int find_listloop(list_t *head,const datatype data,int datasize) //查找某个数据
{
	list_t *q = NULL;

	for(q = head->next; q != head; q = q->next) {
		if( !memcmp (q->data,data,datasize) ) {
			printf ("find data: %d\n",*((int *)(q->data)));
      return 0;
		}
	}

	return -1;
}

3.10 销毁链表

void destory_listloop (list_t *head)  //销毁链表
{
	list_t *q = NULL;

	for(q = head->next->next; q != head; q = q->next) {
		free(q->prev->data);
		free(q->prev);
	}

	free(head->data);
	free(head);
}

3.11 测试

int main(void)
{
  list_t *list = NULL;
  int data[10] = {8, 10, 7, 1, 6, 4, 9, 2, 3, 5};
  
  list = create_listloop ();
  if (isempty_listloop (list) ) {
    printf ("doulist loop is null !\n");
  }

  insert_listloop (list, &data[0], sizeof (int), TRAILLIST);
  insert_listloop (list, &data[1], sizeof (int), TRAILLIST);
  insert_listloop (list, &data[2], sizeof (int), TRAILLIST);
  insert_listloop (list, &data[3], sizeof (int), TRAILLIST);
  printf ("tail insert, doulist loop length is : %d\n",doulistloop_length(list));
  display_listloop (list);

  insert_listloop (list, &data[4], sizeof (int), HEADLIST);
  insert_listloop (list, &data[5], sizeof (int), HEADLIST);
  insert_listloop (list, &data[6], sizeof (int), HEADLIST);
  insert_listloop (list, &data[7], sizeof (int), HEADLIST);
  printf ("head insert, doulist loop length is : %d\n",doulistloop_length(list));
  display_listloop (list);

  insert_select_listloop (list, 2, &data[8]);
  insert_select_listloop (list, 2, &data[9]);
  printf ("select insert, doulist loop length is : %d\n",doulistloop_length(list));
  display_listloop (list);

  delete_listloop(list, &data[1], sizeof (int));
  printf ("delete data: 10, doulist loop length is : %d\n",doulistloop_length(list));
  display_listloop (list);
  
  sort_listloop (list, func_order);
  printf ("order sort data, doulist loop length is : %d\n",doulistloop_length(list));
  display_listloop (list);

  sort_listloop (list, func_invert);
  printf ("invert sort data, doulist loop length is : %d\n",doulistloop_length(list));
  display_listloop (list);
  
  find_listloop(list,  &data[2], sizeof (int));

  destory_listloop(list);

	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值