线性结构——单向链表

一、概念

1.1 链表概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
常见链表:单向(不)链表、双向(不)循环链表、静态链表

链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点或者上一个节点地址的指针域。(这里只讨论带头节点单向链表 )
在这里插入图片描述

  1. 头指针:一个普通的指针,它的特点是永远指向链表第一个节点的位置。很明显,头指针用于指明链表的位置,便于后期找到链表并使用表中的数据;
  2. 节点:链表中的节点又细分为头节点、首元节点和其他节点:
  • 头节点:其实就是一个不存任何数据的空节点,通常作为链表的第一个节点。对于链表来说,头节点不是必须的,它的作用只是为了方便解决某些实际问题;
  • 首元节点:由于头节点(也就是空节点)的缘故,链表中称第一个存有数据的节点为首元节点。首元节点只是对链表中第一个存有数据节点的一个称谓,没有实际意义;
  • 其他节点:链表中其他的节点;

1.2 顺序表与链表优缺点

在这里插入图片描述
总结:

  • 当线性表的长度变化不大、易于确定其大小时,采用顺序表作为存储结构。
  • 若线性表主要操作是查找。很少进行插入或删除操作时,采用顺序表作为存储结构。
  • 对于频繁进行插入和删除的线性表,则应该使用链表作为存储结构。

二、单向不循环链表

在这里插入图片描述

2.1 定义数据类型

typedef  int datatype;

typedef struct siglist_t {
  datatype data;           //数据域
  struct siglist_t *next;  //指针域
}siglist;

2.2 生成头节点

siglist *CreateSigList(void)  //创建头节点
{
  siglist *head = NULL;
  head=malloc(sizeof(*head));
  if(head == NULL) {
    return NULL;
  }

  head->next=NULL;
  return head;
}

2.3 插入节点

2.3.1 头/尾插

enum
{
	HEADINSERT=1,
	TRAILINSERT
};

int insert_siglist(siglist *head, datatype data,int option,int datasize) //头插、尾插
{
	siglist *list = NULL;
	siglist  *q   = NULL;
  
  if (head == NULL) {
    printf ("insert head is fail!\n");
    return -1;
  }

	list = malloc(sizeof(siglist));
	memcpy(&list->data, &data, datasize);

	switch(option)
	{
	case HEADINSERT:
		list->next = head->next;
		head->next = list;
		break;
	case TRAILINSERT:
		for(q = head; q->next != NULL; q = q->next);
		  q->next = list;
		  q->next->next = NULL;
		  break;
	default:
		free(list);
		return -1;
	}
	return 0;
}

2.3.2 选择插

int insert_select_siglist (siglist *head, int num, datatype data) //选择在第num位置插入数据
{
  int i;
  siglist *q = head;
  siglist *list = NULL;

  if (ReSiglistSize (head) < num || num <= 1) {
    printf ("insert_select_siglist num is erorr!\n");
    return -1;
  }

  list = malloc(sizeof(siglist));
	memcpy(&list->data, &data, sizeof(datatype));
  
  for (i = 1, q = head; q->next != NULL; i++, q = q->next) {
    if (i == num) {
      list->next = q->next;
      q->next = list;
      return 0;
    } 
  }

  return -1;
}

2.4 打印

int PrintSiglist (siglist *head) //打印
{
  siglist *q = NULL;
  printf ("head : %p -> ",head);
  for (q = head->next ; q != NULL ; q = q->next) {
    printf ("%d - %p -> ",q->data,q);
  }
  printf ("\n");

  return 0;
}

2.5 判空

int IsEmptySiglist(siglist *head)   //判断链表是否为空
{
  if (head == NULL) {
    printf ("insert head is fail!\n");
    return -1;
  }

	return head->next==NULL ? 1:0;
}

2.6 链表长度

int ReSiglistSize (siglist *head)  //返回链表长度,不包括头节点
{
  int i;
  siglist *q = NULL;
  if (head == NULL) {
    printf ("insert head is fail!\n");
    return -1;
  }

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

  return i;
}

2.7 头删

int SiglistDelHead (siglist *head) //头删,删除第一个数据节点(非头节点)
{
  siglist *tmp = NULL;

  if (head == NULL) {
    printf ("SiglistDelHead head is fail!\n");
    return -1;
  } 

  if (ReSiglistSize(head) <= 0) {
    printf ("length is not large !\n");
    return -1;
  }

  tmp = head->next;
  head->next = head->next->next;

  return 0;
}

2.8 尾删

int SiglistDelTail (siglist *head) //尾删,删除最后一个数据节点
{
  siglist *tmp = NULL;

  if (head == NULL) {
    printf ("SiglistDelTail head is fail!\n");
    return -1;
  } 
  
  if (ReSiglistSize(head) <= 0) {
    printf ("length is not large !\n");
    return -1;
  }

  for (tmp = head; tmp->next->next != NULL; tmp=tmp->next);

  free(tmp->next);

  tmp->next = NULL;
  
  return 0;
}

2.9 选择删

int SiglistDelNum (siglist *head, int num) //删除第num个
{
  siglist *q,*p;
  int i;
  
  if (head == NULL) {
    printf ("SiglistDelNum head is fail!\n");
    return -1;
  } 

  if (num < 0 || num > ReSiglistSize(head)) {
    printf ("SiglistDelNum num is out of range!\n");
    return -1;
  }

  for (i = 0, q = head; i < num - 1; i++, q = q->next);
  p = q->next;
  q->next = p->next;
  
  free(p);
  return 0;
}

2.10 排序

int SiglistSort (siglist *head)  //冒泡排序
{
  int     i,num,siglength;
  siglist  *q,*p,*t;
  datatype    Tmpdata;
  if (head == NULL) {
    printf ("SiglistSort head is fail!\n");
    return -1;
  } 
  
  siglength = ReSiglistSize(head);
  if (siglength < 2) {
    printf ("length is not large !\n");
    return -1;
  }

  for (i = 0; i < siglength - 1; i++) {
    num = siglength - i - 1;
    //q指向第一个节点  p指向q的下一个节点 t指向头节点        //t指向原q下一个节点  q指向t下一个节点 p指向q下一个节点
    for (q = head->next, p = q->next, t = head; num > 0; t = t->next,q = t->next, p = q->next,  num--) {
      if (q->data  >  p->data) {
        q->next = p->next;
        p->next = q;
        t->next = p;
      }
    }
  }
  
  return 0;
}

2.11 查找数据

int SiglistFind (siglist *head, datatype data) //在链表中寻找某个数据
{
  siglist *q = NULL;
  if (head == NULL) {
    printf ("SiglistFind head is fail!\n");
    return -1;
  }
  
  for (q = head->next; q != NULL; q = q->next) {
    if (q->data == data) {
      return 0;
    }
  }

  return -1;
}

2.12 读出第n项数据

datatype SiglistFindNum (siglist *head, int num)  //返回第几个数据
{
  int i;
  siglist *q = NULL;
  if (head == NULL) {
    printf ("SiglistFindNum head is fail!\n");
    return -1;
  }

  if (num < 0 || num > ReSiglistSize(head)) {
    printf ("SiglistFindNum num is out of range!\n");
    return -1;
  }

  for (i = 0, q = head->next; i < num - 1; i++, q = q->next);
  
  return q->data;

}

2.13 反转

四种链表反转方法

  • 迭代反转
  • 递归反转
  • 头插法反转
  • 就地逆置法反转

2.13.1 迭代反转

int Sqlist_iteration_reverse (siglist *head)  //迭代翻转
{
  siglist  *pre, *cur, *nxt;
  if (head == NULL || head->next == NULL) {  //空或者只有一个数据节点,不用翻转
    printf ("Sqlist_iteration_reverse is fail!\n");
    return -1;
  }
  
  //pre 初始为NULL cur 初始为首元节点 nxt初始为cur下一个节点
  //第一次变化之后,| pre = cur | cur = nxt | nxt =nxt->next | ,后面每次变化,三个指针都往后面移一位
  //当cur移动到最后一位,退出            
  for (pre = NULL, cur = head->next, nxt = cur->next; nxt != NULL; pre = cur, cur = nxt, nxt = nxt->next) {
    cur->next = pre;
  }

  cur->next = pre;
  head->next = cur;

  return 0;
}

实现方法:

首先生成三个指针,pre指向NULL,cur指向首元节点,nxt指向元首节点下一个节点
在这里插入图片描述

使第一个节点与pre指向相同,然后依次使三个指针向原来指向后移动一位
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

当cur移动到最后链表一位时,使head跟cur指向相同
在这里插入图片描述

2.13.2 递归反转

实现方法:

和迭代反转法的思想恰好相反,递归反转法的实现思想是从链表的尾节点开始,依次向前遍历,遍历过程依次改变各节点的指向,即另其指向前一个节点。

int Sqlist_recursive_reverse (siglist *head) //递归收尾
{
  siglist *Sq = head->next; //原链表的首元节点
  siglist *q = NULL;
  if (head == NULL || head->next == NULL) {  // 空链或只有一个结点,直接返回头指针
    printf ("Sq_recursive_reverse_start return!\n");
    return head;
  }
  
  //q = 原链表最后一个节点(反转之后的第一个节点)
  q = Sq_recursive_reverse_start (head);  //开始递归

  Sq->next = NULL;  //反转之后 原 首元节点  变为反转之后最后一个节点
  head->next = q;   //原 头节点指向反转之后的第一个节点,使反转之后第一个节点成为新链表 的首元节点
  
  return 0;
}

siglist *Sq_recursive_reverse_start (siglist *head) //递归翻转
{
  if (head == NULL || head->next == NULL) {  //设置返回条件
    printf ("Sq_recursive_reverse_start return!\n");
    return head;
  }
  
  //一直递归,找到链表中最后一个节点
  siglist *last = Sq_recursive_reverse_start(head->next);
  //当逐层退出时,last 一直是原链表中最后一个节点;
  //递归每退出一层,函数中 head 指针的指向都会发生改变,都指向上一个节点。
  
  //每退出一层,都需要改变 head->next 节点指针域的指向,同时令 head 所指节点的指针域为 NULL。
  //每一层递归结束,都要将新的头指针返回给上一层。由此,即可保证整个递归过程中,能够一直找得到新链表的表头。
  head->next->next = head;
  head->next = NULL;
  
  return last;
}

调用Sq_recursive_reverse_start 一直递归,找到最后一个节点,从最后一个节点开始反转,如下:
head->next->next = head;
head->next = NULL;

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
再把原头节点指向新链表的第一个节点,形成反转
Sq->next = NULL;
head->next = q;

在这里插入图片描述
在这里插入图片描述

2.13.3 就地逆置反转链表

直接对原链表修改,使用头插法,将链表反转

int Sqlist_situ_insertion_reverse (siglist *head) //就地逆置反转
{
  siglist *head_tmp = head->next->next;
  siglist *t = NULL;

  if (head == NULL || head->next == NULL || head->next->next == NULL) {  
    printf ("Sqlist_situ_insertion_reverse is head fail!\n");
    return -1;
  }

   head->next->next = NULL;
  for(t = head_tmp->next; t != NULL; head_tmp = t, t = t->next) {
    head_tmp->next = head->next;
    head->next = head_tmp;
  }
  head_tmp->next = head->next;
  head->next = head_tmp;
  return 0;
}

在这里插入图片描述

2.13.4 头插法反转链表

跟就地逆置法相似,不同的是需生成新的头节点,使用头插法,将链表反转

siglist *Sqlist_head_insert_reverse (siglist *head)  //头插法反转
{
  siglist *new_head = NULL;
  siglist *t = NULL;
  siglist *head_tmp = head->next->next;
  
  if (head == NULL || head->next == NULL || head->next->next == NULL) {  
    printf ("Sqlist_head_insert_reverse is head fail!\n");
    return head;
  }
  new_head = malloc(sizeof(*new_head));  //初始化新链表
  new_head->next = NULL;
  
  new_head->next = head->next;
  new_head->next->next = NULL;
  for (t = head_tmp->next; t != NULL ; head_tmp = t,t = t->next) {
    head_tmp->next = new_head->next;
    new_head->next = head_tmp;
  }
  head_tmp->next = new_head->next;
  new_head->next = head_tmp;
  
  free (head);
  return new_head;
}

在这里插入图片描述

2.14 链表删除

int SiglistErase (siglist *head) //链表删除
{
  siglist *q,*p;

  if (head == NULL) {
    printf ("SiglistErase head is fail!\n");
    return -1;
  }
  
  for (p = head->next, q = p; q != NULL; q = p) {
    p = q->next;
    q->next = NULL;
    free (q);
  }
  
  head->next = NULL;

  return 0;
}

2.15 链表销毁

int SiglistDestory (siglist *head)  //销毁链表
{
  siglist *q = head;
  if (head == NULL) {
    printf ("SiglistDestory head is fail!\n");
    return -1;
  } 
  
  SiglistErase (head);
  free (head);
  head = NULL;

  return 0;
}

2.16 测试

int main (int argc, char *argv[]) 
{
  siglist *list =NULL;
  siglist *new_list =NULL;
  
  list = CreateSigList();

  if (IsEmptySiglist(list)) {
    printf ("siglist is null!\n");
  }

  insert_siglist(list, 8, HEADINSERT, sizeof(datatype));
  insert_siglist(list, 5, HEADINSERT, sizeof(datatype));
  insert_siglist(list, 9, HEADINSERT, sizeof(datatype));
  insert_siglist(list, 1, HEADINSERT, sizeof(datatype));
  insert_siglist(list, 3, HEADINSERT, sizeof(datatype));
  printf ("head insert, siglist length is : %d\n",ReSiglistSize(list));
  PrintSiglist (list);

  insert_siglist(list, 10, TRAILINSERT, sizeof(datatype));
  insert_siglist(list, 2, TRAILINSERT, sizeof(datatype));
  insert_siglist(list, 6, TRAILINSERT, sizeof(datatype));
  printf ("tail insert, siglist length is : %d\n",ReSiglistSize(list));
  PrintSiglist (list);

  insert_select_siglist (list, 2, 7);
  insert_select_siglist (list, 2, 4);
  printf ("insert num 2, siglist length is : %d\n",ReSiglistSize(list));
  PrintSiglist (list);

  SiglistDelHead(list);
  printf ("siglist length is : %d\n",ReSiglistSize(list));
  PrintSiglist (list);

  SiglistDelTail(list);
  printf ("siglist length is : %d\n",ReSiglistSize(list));
  PrintSiglist (list);
  
  SiglistDelNum(list, 3);
  printf ("siglist length is : %d\n",ReSiglistSize(list));
  PrintSiglist (list);

  SiglistSort(list);
  printf ("siglist length is : %d\n",ReSiglistSize(list));
  PrintSiglist (list);

  if (!SiglistFind(list, 10)) {
    printf ("find this data : 10!\n");
  }

  printf ("num 5 data : %d \n",SiglistFindNum (list, 5));

  printf ("sqlist iteration reverse:\n");
  Sqlist_iteration_reverse (list);
  PrintSiglist (list);
  
  printf ("sqlist recursive reverse:\n");
  Sqlist_recursive_reverse (list);
  PrintSiglist (list);
  
  printf("sqlist situ insertion reverse:\n");
  Sqlist_situ_insertion_reverse (list);
  PrintSiglist (list);
  
  printf("sqlist head insertion reverse:\n");
  new_list = Sqlist_head_insert_reverse (list);
  PrintSiglist (new_list);
  
  SiglistErase(new_list);
  printf ("SiglistErase , and siglist length is : %d\n",ReSiglistSize(new_list));
  
  SiglistDestory (new_list);
  
  return 0;
}

在这里插入图片描述

三、单向循环链表

在这里插入图片描述

3.1 定义数据类型

typedef int datatype;

typedef struct list
{
	datatype data;
	struct list *next;
}list_t;

3.2 生成头节点

list_t *CreateSigListloog(void)  //创建头节点
{
  list_t *head = NULL;
  head=malloc(sizeof(*head));

	if(head == NULL) {
		return NULL;
	}
	
	head->next = head;

	return head;
}

3.3 插入节点

3.3.1 头/尾插

int insert_siglist_loop(list_t *head, datatype data,int option,int datasize) //头插、尾插
{
	list_t *list = NULL;
	list_t  *q   = NULL;
  
  if (head == NULL) {
    printf ("insert head is fail!\n");
    return -1;
  }

	list = malloc(sizeof(list_t));
	memcpy(&list->data, &data, datasize);

	switch(option)
	{
	case HEADINSERT:
		list->next = head->next;
		head->next = list;
		break;
	case TRAILINSERT:
		for(q = head; q->next != head; q = q->next);
      list->next = q->next;
      q->next = list;
		  break;
	default:
		free(list);
		return -1;
	}
	return 0;
}

3.3.2 选择插

int insert_select_siglistloop (list_t *head, int num, datatype data) //选择在第num位置插入数据
{
  int i;
  list_t *q = head;
  list_t *list = NULL;

  if (ReSiglistSizeloop (head) < num || num <= 1) {
    printf ("insert_select_siglist num is erorr!\n");
    return -1;
  }

  list = malloc(sizeof(list_t));
	memcpy(&list->data, &data, sizeof(datatype));
  
  for (i = 1, q = head; q->next != head; i++, q = q->next) {
    if (i == num) {
      list->next = q->next;
      q->next = list;
      return 0;
    } 
  }

  return -1;
}

3.4 打印

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

  return 0;
}

3.5 判空

int IsEmptySiglistloop (list_t *head)   //判断链表是否为空
{
  if (head == NULL) {
    printf ("insert head is fail!\n");
    return -1;
  }

	return head->next==head ? 1:0;
}

3.6 链表长度

int ReSiglistSizeloop (list_t *head)  //返回链表长度,不包括头节点
{
  int i;
  list_t *q = NULL;
  if (head == NULL) {
    printf ("insert head is fail!\n");
    return -1;
  }

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

  return i;
}

3.7 选择删

int SiglistloopDelNum (list_t *head, int num) //删除第num个
{
  list_t *q,*p;
  int i;
  
  if (head == NULL) {
    printf ("SiglistloopDelNum head is fail!\n");
    return -1;
  } 

  if (num < 0 || num > ReSiglistSizeloop(head)) {
    printf ("SiglistloopDelNum num is out of range!\n");
    return -1;
  }

  for (i = 0, q = head; i < num - 1; i++, q = q->next);
  p = q->next;
  q->next = p->next;
  
  free(p);
  return 0;
}

3.8 排序

int SiglistloopSort (list_t *head)  //冒泡排序
{
  int     i,num,siglength;
  list_t  *q,*p,*t;
  datatype    Tmpdata;
  if (head == NULL) {
    printf ("SiglistloopSort head is fail!\n");
    return -1;
  } 
  
  siglength = ReSiglistSizeloop(head);
  if (siglength < 2) {
    printf ("length is not large !\n");
    return -1;
  }

  for (i = 0; i < siglength - 1; i++) {
    num = siglength - i - 1;
    //q指向第一个节点  p指向q的下一个节点 t指向头节点        //t指向原q下一个节点  q指向t下一个节点 p指向q下一个节点
    for (q = head->next, p = q->next, t = head; num > 0; t = t->next,q = t->next, p = q->next,  num--) {
      if (q->data  >  p->data) {
        q->next = p->next;
        p->next = q;
        t->next = p;
      }
    }
  }
  
  return 0;
}

3.9 查找数据

int SiglistloopFind (list_t *head, datatype data) //在链表中寻找某个数据
{
  list_t *q = NULL;
  if (head == NULL) {
    printf ("SiglistFind head is fail!\n");
    return -1;
  }
  
  for (q = head->next; q != NULL; q = q->next) {
    if (q->data == data) {
      return 0;
    }
  }

  return -1;
}

3.9 读出第n个数据

datatype SiglistloopFindNum (list_t *head, int num)  //返回第几个数据
{
  int i;
  list_t *q = NULL;
  if (head == NULL) {
    printf ("SiglistFindNum head is fail!\n");
    return -1;
  }

  if (num < 0 || num > ReSiglistSizeloop(head)) {
    printf ("SiglistFindNum num is out of range!\n");
    return -1;
  }

  for (i = 0, q = head->next; i < num - 1; i++, q = q->next);
  
  return q->data;

}

3.11 反转

3.11.1 迭代反转

int Sqlistloop_iteration_reverse (list_t *head)  //迭代翻转
{
  list_t  *pre, *cur, *nxt;
  if (head->next == head) {  //空或者只有一个数据节点,不用翻转
    printf ("Sqlistloop_iteration_reverse is fail!\n");
    return -1;
  }
  
  //pre 初始为head cur 初始为首元节点 nxt初始为cur下一个节点
  //第一次变化之后,| pre = cur | cur = nxt | nxt =nxt->next | ,后面每次变化,三个指针都往后面移一位
  //当cur移动到最后一位,退出            
  for (pre = head, cur = head->next, nxt = cur->next; nxt != head; pre = cur, cur = nxt, nxt = nxt->next) {
    cur->next = pre;
  }

  cur->next = pre;
  head->next = cur;

  return 0;
}

3.11.2 递归反转

list_t *head_t;
int Sqlistloop_recursive_reverse (list_t *head) //递归收尾
{
  list_t *Sq = head->next; //原链表的首元节点
  list_t *q = NULL;

  if (head == NULL || head->next == NULL) {  // 空链或只有一个结点,直接返回头指针
    printf ("Sqlistloop_recursive_reverse head is fail!\n");
    return -1;
  }

  head_t = head;  //保留原始头节点
  //q = 原链表最后一个节点(反转之后的第一个节点)
  q = Sqloop_recursive_reverse_start (head);  //开始递归
  Sq->next = head;  //反转之后 原 首元节点  变为反转之后最后一个节点
  head->next = q;   //原 头节点指向反转之后的第一个节点,使反转之后第一个节点成为新链表 的首元节点
  
  return 0;
}

list_t *Sqloop_recursive_reverse_start (list_t *head) //递归翻转
{
  if (head->next == head_t) {  // 空链或只有一个结点,直接返回头指针
    printf ("Sq_recursive_reverse_start return!\n");
    return head;
  }
  //一直递归,找到链表中最后一个节点
  list_t *last = Sqloop_recursive_reverse_start (head->next);
  //当逐层退出时,last 一直是原链表中最后一个节点;
  //递归每退出一层,函数中 head 指针的指向都会发生改变,都指向上一个节点。
  
  //每退出一层,都需要改变 head->next 节点指针域的指向,同时令 head 所指节点的指针域为 NULL。
  //每一层递归结束,都要将新的头指针返回给上一层。由此,即可保证整个递归过程中,能够一直找得到新链表的表头。
  head->next->next = head;
  head->next = NULL;
  
  return last;
}

3.11.3 就地逆置法反转

int Sqlistloop_situ_insertion_reverse (list_t *head) //就地逆置反转
{
  list_t *head_tmp = head->next->next;
  list_t *t = NULL;

  if (head->next == head || head->next->next == head) {  
    printf ("Sqlistloop_situ_insertion_reverse is head fail!\n");
    return -1;
  }

  head->next->next = head;
  for(t = head_tmp->next; t != head; head_tmp = t, t = t->next) {
    head_tmp->next = head->next;
    head->next = head_tmp;
  }
  head_tmp->next = head->next;
  head->next = head_tmp;
  return 0;
}

3.11.4 头插法法反转

list_t *Sqlistloop_head_insert_reverse (list_t *head)  //头插法反转
{
  list_t *new_head = NULL;
  list_t *t = NULL;
  list_t *head_tmp = head->next->next;
  
  if (head == NULL || head->next == NULL || head->next->next == NULL) {  
    printf ("Sqlist_head_insert_reverse is head fail!\n");
    return head;
  }
  new_head = malloc(sizeof(*new_head));  //初始化新链表
  new_head->next = new_head;
  
  new_head->next = head->next;
  new_head->next->next = new_head;
  for (t = head_tmp->next; t != head ; head_tmp = t,t = t->next) {
    head_tmp->next = new_head->next;
    new_head->next = head_tmp;
  }
  head_tmp->next = new_head->next;
  new_head->next = head_tmp;
  
  free (head);
  return new_head;
}

3.12 链表删除

int SiglistloopErase (list_t *head) //链表删除
{
  list_t *q,*p;

  if (head == NULL) {
    printf ("SiglistErase head is fail!\n");
    return -1;
  }
  
  for (p = head->next, q = p; q != head; q = p) {
    p = q->next;
    q->next = NULL;
    free (q);
  }
  
  head->next = head;

  return 0;
}

3.13 销毁链表

int SiglistloopDestory (list_t *head)  //销毁链表
{
  list_t *q = head;
  if (head == NULL) {
    printf ("SiglistloopDestory head is fail!\n");
    return -1;
  } 
  
  SiglistloopErase (head);
  free (head);
  head = NULL;

  return 0;
}

3.14 测试

int main (void) 
{
  list_t *list = CreateSigListloog();
  list_t *new_list = CreateSigListloog();

  if (IsEmptySiglistloop(list)) {
    printf ("siglist is null!\n");
  }

  insert_siglist_loop(list, 8, HEADINSERT, sizeof(datatype));
  insert_siglist_loop(list, 5, HEADINSERT, sizeof(datatype));
  insert_siglist_loop(list, 9, HEADINSERT, sizeof(datatype));
  insert_siglist_loop(list, 1, HEADINSERT, sizeof(datatype));
  insert_siglist_loop(list, 3, HEADINSERT, sizeof(datatype));
  printf ("siglist loop length is : %d\n",ReSiglistSizeloop(list));
  PrintSiglistloop (list);

  insert_siglist_loop(list, 10, TRAILINSERT, sizeof(datatype));
  insert_siglist_loop(list, 2, TRAILINSERT, sizeof(datatype));
  insert_siglist_loop(list, 6, TRAILINSERT, sizeof(datatype));
  printf ("siglist loop length is : %d\n",ReSiglistSizeloop(list));
  PrintSiglistloop (list);

  insert_select_siglistloop (list, 2, 7);
  insert_select_siglistloop (list, 2, 4);
  printf ("insert num 2, siglist length is : %d\n",ReSiglistSizeloop(list));
  PrintSiglistloop (list);


  SiglistloopDelNum(list, 2);
  printf ("siglistloop length is : %d\n",ReSiglistSizeloop(list));
  PrintSiglistloop (list);
  
  SiglistloopDelNum(list, 4);
  printf ("siglistloop length is : %d\n",ReSiglistSizeloop(list));
  PrintSiglistloop (list);

  SiglistloopSort(list);
  printf ("siglistloop length is : %d\n",ReSiglistSizeloop(list));
  PrintSiglistloop (list);

  if (!SiglistloopFind(list, 10)) {
    printf ("find this data : 10\n");
  }

  printf ("num 5 data : %d \n",SiglistloopFindNum (list, 5));

  printf ("sqlist loop iteration reverse:\n");
  Sqlistloop_iteration_reverse (list);
  PrintSiglistloop (list);
  
  printf ("sqlist loop recursive reverse:\n");
  Sqlistloop_recursive_reverse (list);
  PrintSiglistloop (list);

  printf("sqlist loop situ insertion reverse:\n");
  Sqlistloop_situ_insertion_reverse (list);
  PrintSiglistloop (list);

  printf("sqlist loop head insertion reverse:\n");
  new_list = Sqlistloop_head_insert_reverse (list);
  PrintSiglistloop (new_list);

  SiglistloopErase(new_list);
  printf ("siglistloop length is : %d\n",ReSiglistSizeloop(new_list));
  
  SiglistloopDestory (new_list);

  return 0;
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值