数据结构学习笔记(4.线性表之双向链表)

本节知识点:

1.为什么选择双向链表:因为单向链表只能一直指向下一个链表元素,不能获得前一个元素,如果要进行逆序访问操作是极其耗时的,所以引入双向链表。
2.双向链表的结构:在单向链表的基础上增加了一个链表结构pre,如图。
注意:链表第一个元素的前驱pre不是指向头结点head,而是指向NULL,链表尾结点的后继next指向NULL
3.如何将一个单向链表改成双向链表:
   第一步 (改变链表的结构加入前驱):
  1. struct Str_DLinkList   //每一个链表元素的结构都会包含这个结构  因为当给链表元素强制类型   
  2. {                     //转换成(DLinkListNode* )的时候  其实就是要开始对每个元素中的 DLinkListNode进行赋值了   
  3.     DLinkListNode* next;  
  4.     DLinkListNode* pre;  
  5. };  
struct Str_DLinkList   //每一个链表元素的结构都会包含这个结构  因为当给链表元素强制类型 
{                     //转换成(DLinkListNode* )的时候  其实就是要开始对每个元素中的 DLinkListNode进行赋值了 
	DLinkListNode* next;
	DLinkListNode* pre;
};

   第二步 (改写插入函数):
   对于一个尾插法,如图:
  
    (1).正常的链表插入操作,代码如下:
  1. for(i=1; ( (i<pos) && (node->next != NULL) ); i++)  
  2. {  
  3.     node = node->next;  
  4. }  
  5. /*此处的node是要插入元素的前一个值  Node是要删除的值*/   
  6. Node -> next = node -> next;  
  7. node -> next = Node;  
for(i=1; ( (i<pos) && (node->next != NULL) ); i++)
{
	node = node->next;
}
/*此处的node是要插入元素的前一个值  Node是要删除的值*/ 
Node -> next = node -> next;
node -> next = Node;
    (2).把刚刚插入的数据的前驱pre跟前一个数据元素相连,代码如下:
  1. Node->pre = node;  
Node->pre = node;
    对于一个正常插入,如图:

    (1).正常的链表插入操作,代码如下:
  1. for(i=1; ( (i<pos) && (node->next != NULL) ); i++)  
  2. {  
  3.     node = node->next;  
  4. }  
  5. /*此处的node是要插入元素的前一个值  Node是要删除的值*/   
  6. Node -> next = node -> next;  
  7. node -> next = Node;  
for(i=1; ( (i<pos) && (node->next != NULL) ); i++)
{
	node = node->next;
}
/*此处的node是要插入元素的前一个值  Node是要删除的值*/ 
Node -> next = node -> next;
node -> next = Node;
    (2).先判断是不是尾插法,如果是尾插法,就像上一个情况一样,就不进行这一步的操作了,代码如下:
  1. if(NULL != Node->next) //判断是否为尾插法 如果不是进入如下操作   如果是尾插法  最后一个链表元素不当作NULL的前驱   
  2. {  
  3.     Node->next->pre = Node;   
  4. }  
if(NULL != Node->next) //判断是否为尾插法 如果不是进入如下操作   如果是尾插法  最后一个链表元素不当作NULL的前驱 
{
	Node->next->pre = Node; 
}
   (3).把刚刚插入的数据的前驱pre跟前一个数据元素相连,代码如下:
  1. Node->pre = node;  
Node->pre = node;
   对于一个头插法,如图:



     (1).正常的链表插入操作,代码如下:
  1. for(i=1; ( (i<pos) && (node->next != NULL) ); i++)  
  2. {  
  3.     node = node->next;  
  4. }  
  5. /*此处的node是要插入元素的前一个值  Node是要删除的值*/   
  6. Node -> next = node -> next;  
  7. node -> next = Node;  
for(i=1; ( (i<pos) && (node->next != NULL) ); i++)
{
	node = node->next;
}
/*此处的node是要插入元素的前一个值  Node是要删除的值*/ 
Node -> next = node -> next;
node -> next = Node;
     (2).把附近的两个链表的前驱pre都赋值为正确的值,代码如下:
  1. if(NULL != Node->next) //判断是否为尾插法 如果不是进入如下操作   如果是尾插法  最后一个链表元素不当作NULL的前驱   
  2. {  
  3.     Node->next->pre = Node;   
  4. }  
  5. Node->pre = node;  
if(NULL != Node->next) //判断是否为尾插法 如果不是进入如下操作   如果是尾插法  最后一个链表元素不当作NULL的前驱 
{
	Node->next->pre = Node; 
}
Node->pre = node;
     (3).如果是头插法,要记得把插入的元素结点的前驱pre赋值为NULL,代码如下:
  1. if( node == (DLinkListNode* )head)  //如果是头插法 就要将第一个链表元素的前驱写成NULL  不然前驱就变成了头节点了   
  2. {  
  3.     Node->pre = NULL;  
  4. }  
if( node == (DLinkListNode* )head)  //如果是头插法 就要将第一个链表元素的前驱写成NULL  不然前驱就变成了头节点了 
{
	Node->pre = NULL;
}
    (4).第一次插入链表元素,要把游标指向插入的链表元素,代码如下:
  1. if( 0==lhead->length ) //在第一次插入元素的时候  把游标指向第一次个元素   
  2. {  
  3.     lhead->slider = Node;  
  4. }  
if( 0==lhead->length ) //在第一次插入元素的时候  把游标指向第一次个元素 
{
	lhead->slider = Node;
}
     第三步 (改写删除函数):
     有三种情况分别是:删除的是第一个结点元素,删除的是最后一个结点元素,删除的是中间结点元素。
     (1).删除第一个结点元素:要注意给下一个结点元素的前驱pre赋值为NULL,不是指向head
     (2).删除最后一个结点元素:要注意不要给next的前驱再赋值了,因为next已经为NULL了。并且此时要把游标往再往前面移动一个位置。代码如下:
  1. DLinkListNode* Del_DLinkListNode(DLinkList* head, int pos)  
  2. {  
  3.     DLinkListNode* ret = NULL;  
  4.     int i = 0;  
  5.     list_head* lhead = (list_head* )head;  
  6.     if(( NULL != lhead) && (pos > 0) && (pos <= lhead->length))  
  7.     {  
  8.         DLinkListNode* node = (DLinkListNode* )head;  
  9.         for(i=1; i<pos; i++)//执行 pos次   得到的是第pos位置的node  这个方法行不通   
  10.         {                   //因为要想删除第pos位置的node 应该先找到它上一个链表元素   
  11.             node = node->next; //所以这里面i=1 比get函数少执行了一次  得到第pos-1位置的node   
  12.         }  
  13.         /*值得注意的是 此处的node是要删除元素的前一个值  ret是要删除的值*/  
  14.         ret = node->next;  
  15.         node->next = ret->next;     
  16.   
  17.         if(NULL != ret->next) //判断删除的值是否为最后一个元素   
  18.         {  
  19.             ret->next->pre = ret->pre;  
  20.             if(node == (DLinkListNode* )head)//判断删除的值是否为第一个元素   
  21.             {  
  22.                 ret->next->pre =  NULL;  
  23.             }   
  24.             if(lhead->slider == ret) //判断删除的节点是否为游标的位置   
  25.             {  
  26.                   
  27.                 lhead->slider = ret->next;   
  28.             }   
  29.         }   
  30.         else  
  31.         {  
  32.             if(lhead->slider == ret) //判断删除的节点是否为游标的位置   
  33.             {  
  34.                   
  35.                 lhead->slider = ret->pre;   
  36.             }  
  37.         }  
  38.   
  39.         lhead->length--;  
  40.     }  
  41.     return (DLinkListNode*)ret;  
  42. }  
DLinkListNode* Del_DLinkListNode(DLinkList* head, int pos)
{
	DLinkListNode* ret = NULL;
	int i = 0;
	list_head* lhead = (list_head* )head;
	if(( NULL != lhead) && (pos > 0) && (pos <= lhead->length))
	{
		DLinkListNode* node = (DLinkListNode* )head;
		for(i=1; i<pos; i++)//执行 pos次   得到的是第pos位置的node  这个方法行不通 
		{                   //因为要想删除第pos位置的node 应该先找到它上一个链表元素 
			node = node->next; //所以这里面i=1 比get函数少执行了一次  得到第pos-1位置的node 
		}
		/*值得注意的是 此处的node是要删除元素的前一个值  ret是要删除的值*/
		ret = node->next;
		node->next = ret->next;	

		if(NULL != ret->next) //判断删除的值是否为最后一个元素 
		{
			ret->next->pre = ret->pre;
			if(node == (DLinkListNode* )head)//判断删除的值是否为第一个元素 
			{
				ret->next->pre =  NULL;
			} 
			if(lhead->slider == ret) //判断删除的节点是否为游标的位置 
			{
				
				lhead->slider = ret->next; 
			} 
		} 
		else
		{
			if(lhead->slider == ret) //判断删除的节点是否为游标的位置 
			{
				
				lhead->slider = ret->pre; 
			}
		}

		lhead->length--;
	}
	return (DLinkListNode*)ret;
}

4.双向链表的快速排序
对于双向链表进行快速排序的效率还不错,比用冒泡排序好很多~~~~~~~此时对快速排序还不是很理解~~~~~等到有了一定理解再回来想想吧!!!
想要提示的一点是,快排是依赖递归实现的,对于递归是有递归层次限制的(其实也是栈溢出的问题),所以快排的最坏情况是已经排序好了的情况,所以对一个链表重复进行快排很容易出现栈溢出的问题!!!


本节代码:

DLinkList.c:

  1. /******************************************************************************************************* 
  2. 文件名:DLinkList.c 
  3. 头文件:DLinkList.h  
  4. 时间: 2013/08/17 
  5. 作者: Hao 
  6. 功能:  可以复用 带有增 删 改 查 功能的循环链表 
  7. 难道: 1.typedef struct Str_DLinkList DLinkListNode;  //这个结构体是链表的真身  
  8.         struct Str_DLinkList   //每一个链表元素的结构都会包含这个结构  因为当给链表元素强制类型  
  9.         {                     //转换成(DLinkListNode* )的时候  其实就是要开始对每个元素中的 DLinkListNode进行赋值了  
  10.             DLinkListNode* next; 
  11.         };  
  12.         这个链表结构在链表元素中起到的作用 是本节的难点  
  13.         2.切记一个问题  就是已经是链表中元素的 千万不要再往链表中添加了 否则链表一定出现无穷的错误  
  14.         3.对于pos值的问题  add、get、del三个函数中 的链表都是 从1开始的到length  0是链表头  
  15.                           在add函数中pos为0的时候是和pos为1的情况是一样的  都是头插法  0~~~~~无穷大  
  16.                           在get函数中pos为0的时候是获得链表头 地址      0~~~~~length  
  17.                           在del函数中pos为0的时候是无效的 del失败       1~~~~~length  
  18. *******************************************************************************************************/  
  19. #include <stdio.h>  
  20. #include <stdlib.h>  
  21. #include <malloc.h>  
  22. #include "DLinkList.h"  
  23.   
  24. typedef struct str_list_head  //这个是链表头 其实也可以当作一个没有前驱的 链表元素 元素的内容是链表长度   
  25. {  
  26.     //DLinkListNode* next;  
  27.     DLinkListNode head; //这个参数要特别重视 每一个链表元素结构的第一个参数一定是 DLinkListNode  
  28.                        //因为在寻找链表元素后继的时候 其实就是将链表元素强制类型转换成 DLinkListNode*  然后给next进行赋值 其实就是给 DLinkListNode变量赋值   
  29.     DLinkListNode* slider;  
  30.     int length; //链表长度   
  31. }list_head;  
  32.   
  33. /******************************************************************************************************* 
  34. 函数名: Creat_DLinkListHead 
  35. 函数功能:创建一个链表的链表头 并给链表头分配空间 
  36. 参数: void 
  37. 返回值:ret 成功返回链表头地址  失败返回NULL  
  38. *******************************************************************************************************/  
  39. DLinkList* Creat_DLinkListHead(void)  
  40. {  
  41.     list_head* ret = NULL;  
  42.     ret = (list_head* )malloc( sizeof(list_head)*1 );  
  43.     if(NULL != ret) //malloc分配成功   
  44.     {  
  45.         ret->length = 0;  
  46.         //ret -> next = NULL;  
  47.         ret->head.next = NULL;  
  48.         ret->head.pre = NULL;  
  49.         ret->slider = NULL;  
  50.     }  
  51.     return (DLinkList* )ret;   
  52. }  
  53.   
  54. /******************************************************************************************************* 
  55. 函数名:Destroy_DLinkListHead 
  56. 函数功能:释放一个链表头指针  
  57. 参数:DLinkList* head 链表头指针  
  58. 返回值: ret 释放成功返回1  释放失败返回0  
  59. *******************************************************************************************************/  
  60. int Destroy_DLinkListHead(DLinkList* head)  
  61. {  
  62.     int ret = 0;   
  63.     list_head* lhead = (list_head* )head;  
  64.     if( NULL != lhead )  
  65.     {  
  66.         free(lhead);  
  67.         ret = 1;  
  68.     }  
  69.     return ret;  
  70. }  
  71.   
  72. /******************************************************************************************************* 
  73. 函数名:Get_Length 
  74. 函数功能:获得链表的长度  
  75. 参数: DLinkList* head 链表头指针  
  76. 返回值: ret 成功返回链表长度  失败返回0  
  77. *******************************************************************************************************/  
  78. int Get_Length(DLinkList* head)   
  79. {  
  80.     int ret = 0;  
  81.     list_head* lhead = (list_head* )head;  
  82.     if( NULL != lhead )  
  83.     {  
  84.         ret = lhead -> length;  
  85.     }     
  86.     return ret;  
  87. }  
  88.   
  89. /******************************************************************************************************* 
  90. 函数名:Clean_DLinkListHead 
  91. 函数功能:   清空链表  
  92. 参数: DLinkList* head 链表头指针  
  93. 返回值:ret 成功返回1 失败返回0  
  94. *******************************************************************************************************/  
  95. int Clean_DLinkListHead(DLinkList* head)   
  96. {  
  97.     int ret = 0;  
  98.     list_head* lhead = (list_head* )head;  
  99.     if( NULL != lhead )  
  100.     {  
  101.         lhead->length = 0;  
  102.         //lhead -> next = NULL;  
  103.         lhead->head.next = NULL;  
  104.         lhead->head.pre = NULL;  
  105.         lhead->slider = NULL;  
  106.         ret = 1;  
  107.     }     
  108.     return ret;  
  109. }  
  110.   
  111. /******************************************************************************************************* 
  112. 函数名:Add_DLinkList 
  113. 函数功能:往链表里面添加一个链表元素 如果pos的值是0(就是链表头)和1(链表的第一元素 链表元素个数是从1开始算的)都是头插法 
  114.           pos的值大于链表长度是尾插法  这里面pos值得注意的是 i=1 pos为a的时候 是把链表元素插入第a个元素的位置  
  115.           当i=0 pos为a的时候 是把链表元素插入 第a个元素位置的后面    切忌:这里面0位置是链表头指针 从1开始是链表元素  
  116. 参数:   DLinkList* head链表头指针    DLinkListNode* Node插入元素的指针(被强制类型转化成DLinkListNode*)  int pos 插入位置  
  117.          pos的有效值范围是 从0到无穷大   
  118. 返回值: ret 插入成功返回1  插入失败返回0  
  119. *******************************************************************************************************/  
  120. int Add_DLinkList(DLinkList* head, DLinkListNode* Node, int pos)  
  121. {  
  122.     int ret = 0;  
  123.     int i = 0;  
  124.     list_head* lhead = (list_head* )head;  
  125.     DLinkListNode* node = (DLinkListNode* )head;  
  126.     ret=( NULL != node) && ( NULL != Node) && (pos >= 0);  
  127.     if(1 == ret)  
  128.     {  
  129.         for(i=1; ( (i<pos) && (node->next != NULL) ); i++)  
  130.         {  
  131.             node = node->next;  
  132.         }  
  133.         /*此处的node是要插入元素的前一个值  Node是要删除的值*/   
  134.         Node -> next = node -> next;  
  135.         node -> next = Node;  
  136.         if(NULL != Node->next) //判断是否为尾插法 如果不是进入如下操作   如果是尾插法  最后一个链表元素不当作NULL的前驱   
  137.         {  
  138.             Node->next->pre = Node;   
  139.         }  
  140.         Node->pre = node;  
  141.           
  142.         if( 0==lhead->length ) //在第一次插入元素的时候  把游标指向第一次个元素   
  143.         {  
  144.             lhead->slider = Node;  
  145.         }  
  146.         if( node == (DLinkListNode* )head)  //如果是头插法 就要将第一个链表元素的前驱写成NULL  不然前驱就变成了头节点了   
  147.         {  
  148.             Node->pre = NULL;  
  149.         }  
  150.           
  151.         lhead -> length++;   
  152.     }  
  153.     return ret;  
  154. }  
  155.   
  156. /******************************************************************************************************* 
  157. 函数名:Get_DLinkListNode 
  158. 函数功能:获得链表中第pos个元素位置的链表元素 链表是从1开始的  0是链表头   pos为0的时候表示get链表头  
  159. 参数: DLinkList* head链表头指针    int pos获得链表元素的位置  pos的有效取值范围是 1 到  length  0是链表头  
  160. 返回值: DLinkListNode*类型 第pos个链表元素的地址  
  161. *******************************************************************************************************/  
  162. DLinkListNode* Get_DLinkListNode(DLinkList* head, int pos)  
  163. {  
  164.     int ret = 0;  
  165.     int i = 0;  
  166.     list_head* lhead = (list_head* )head;  
  167.     ret=( NULL != lhead) && (pos >= 0) && (pos <= lhead->length);  
  168.     if(1 == ret)  
  169.     {  
  170.         DLinkListNode* node = (DLinkListNode* )head;  
  171.         for(i=0; i<pos; i++) //执行 pos次   得到的是第pos位置的node   
  172.         {  
  173.             node = node->next;  
  174.         }     
  175.         return (DLinkListNode*)node;  
  176.     }  
  177.     return NULL;  
  178. }  
  179.   
  180. /******************************************************************************************************* 
  181. 函数名:Del_DLinkListNode 
  182. 函数功能:删除链表中第pos位置的链表元素  
  183. 参数: DLinkList* head链表头指针    int pos删除链表元素的位置  pos是删除的链表元素的位置 跟get和add中的 
  184.        pos是配套的  有效取值范围依然是 1到 length  在这个函数里面由于不能删除链表头 所以pos为0的时候无效  
  185. 返回值: DLinkListNode* ret这个返回值很重要 因为这个删除仅仅是把链表元素踢出了链表 并没有free开辟的内存 
  186.          应该通过这个返回的地址free  释放内存 
  187.          删除成功返回 删除链表元素的地址   删除失败返回 NULL  
  188. *******************************************************************************************************/  
  189. DLinkListNode* Del_DLinkListNode(DLinkList* head, int pos)  
  190. {  
  191.     DLinkListNode* ret = NULL;  
  192.     int i = 0;  
  193.     list_head* lhead = (list_head* )head;  
  194.     if(( NULL != lhead) && (pos > 0) && (pos <= lhead->length))  
  195.     {  
  196.         DLinkListNode* node = (DLinkListNode* )head;  
  197.         for(i=1; i<pos; i++)//执行 pos次   得到的是第pos位置的node  这个方法行不通   
  198.         {                   //因为要想删除第pos位置的node 应该先找到它上一个链表元素   
  199.             node = node->next; //所以这里面i=1 比get函数少执行了一次  得到第pos-1位置的node   
  200.         }  
  201.         /*值得注意的是 此处的node是要删除元素的前一个值  ret是要删除的值*/  
  202.         ret = node->next;  
  203.         node->next = ret->next;     
  204.   
  205.         if(NULL != ret->next) //判断删除的值是否为最后一个元素   
  206.         {  
  207.             ret->next->pre = ret->pre;  
  208.             if(node == (DLinkListNode* )head)//判断删除的值是否为第一个元素   
  209.             {  
  210.                 ret->next->pre =  NULL;  
  211.             }   
  212.             if(lhead->slider == ret) //判断删除的节点是否为游标的位置   
  213.             {  
  214.                   
  215.                 lhead->slider = ret->next;   
  216.             }   
  217.         }   
  218.         else  
  219.         {  
  220.             if(lhead->slider == ret) //判断删除的节点是否为游标的位置   
  221.             {  
  222.                   
  223.                 lhead->slider = ret->pre;   
  224.             }  
  225.         }  
  226.   
  227.         lhead->length--;  
  228.     }  
  229.     return (DLinkListNode*)ret;  
  230. }  
  231.   
  232. /******************************************************************************************************* 
  233. 函数名: DLinkList_Slider 
  234. 函数功能:获得当前游标指向的数据 
  235. 参数: DLinkList* head 
  236. 返回值:成功返回 DLinkListNode* ret  失败返回NULL  
  237. *******************************************************************************************************/  
  238. DLinkListNode* DLinkList_Slider(DLinkList* head)  
  239. {  
  240.     DLinkListNode* ret = NULL;  
  241.     list_head* lhead = (list_head* )head;  
  242.     if( (NULL != lhead)&&(NULL != lhead->slider) )//保证slider是有效的   
  243.     {  
  244.         ret = lhead->slider;  
  245.     }  
  246.     return ret;  
  247. }  
  248.   
  249. /******************************************************************************************************* 
  250. 函数名: DLinkList_Reset 
  251. 函数功能:重置游标 让游标指向head头节点后面的第一个元素  
  252. 参数: DLinkList* head 
  253. 返回值:成功返回 当前游标的指向DLinkListNode* ret  失败返回NULL  
  254. *******************************************************************************************************/  
  255. DLinkListNode* DLinkList_Reset(DLinkList* head)  
  256. {  
  257.     DLinkListNode* ret = NULL;  
  258.     list_head* lhead = (list_head* )head;  
  259.     if(NULL != lhead)  
  260.     {  
  261.         lhead->slider = lhead->head.next;  
  262.         ret = lhead->slider;  
  263.     }  
  264.     return ret;  
  265. }  
  266.   
  267. /******************************************************************************************************* 
  268. 函数名: DLinkList_Next 
  269. 函数功能:使游标指向下一个元素  
  270. 参数: DLinkList* head 
  271. 返回值:成功返回 前游标的指向DLinkListNode* ret  失败返回NULL  
  272. *******************************************************************************************************/  
  273. DLinkListNode* DLinkList_Next(DLinkList* head)  
  274. {  
  275.     DLinkListNode* ret = NULL;  
  276.     list_head* lhead = (list_head* )head;  
  277.     if((NULL != lhead)&&(NULL != lhead->slider)) //保证游标是有效的   
  278.     {  
  279.         ret = lhead->slider;  
  280.         lhead->slider = ret->next;   
  281.     }  
  282.     return ret;  
  283. }  
  284.   
  285. /******************************************************************************************************* 
  286. 函数名: DLinkList_Pre 
  287. 函数功能:使游标指向上一个元素  
  288. 参数: DLinkList* head 
  289. 返回值:成功返回 前游标的指向DLinkListNode* ret  失败返回NULL  
  290. *******************************************************************************************************/  
  291. DLinkListNode* DLinkList_Pre(DLinkList* head)  
  292. {  
  293.     DLinkListNode* ret = NULL;  
  294.     list_head* lhead = (list_head* )head;  
  295.     if((NULL != lhead)&&(NULL != lhead->slider)) //保证游标是有效的   
  296.     {  
  297.         ret = lhead->slider;  
  298.         lhead->slider = ret->pre;   
  299.     }  
  300.     return ret;  
  301. }  
  302.   
  303. /******************************************************************************************************* 
  304. 函数名: DLinkList_Del 
  305. 函数功能:删除链表中的某个指定元素  
  306. 参数: DLinkList* head   DLinkListNode* node为指定的元素  
  307. 返回值:成功返回 删除的链表元素  失败返回NULL  
  308. *******************************************************************************************************/  
  309. DLinkListNode* DLinkList_Del(DLinkList* head,DLinkListNode* node)  
  310. {   //这个函数主要是用来删除游标的返回值的   
  311.    
  312.     DLinkListNode* ret = NULL;  
  313.     list_head* lhead = (list_head* )head;  
  314.     int i=0;   
  315.     if((NULL != head)&&(NULL != node))  
  316.     {  
  317.         DLinkListNode* current = (DLinkListNode*)lhead;  
  318.         for(i=1; i<=lhead->length; i++)  
  319.         {  
  320.             if(node == current->next)  
  321.             {  
  322.                 ret = current->next;  
  323.                 break;   
  324.             }   
  325.             current = current->next;  
  326.         }  
  327.           
  328.         if(NULL == ret)  //说明没有找到node   
  329.         {  
  330.             printf("put error!!!\n");   
  331.         }  
  332.         else //找到了node   
  333.         {  
  334.             Del_DLinkListNode(lhead,i);   
  335.             printf("ii%d\n",i);  
  336.         }   
  337.     }     
  338.     return ret;//返回删除的链表元素   
  339. }  
  340.   
  341. /***************************************************************************************************************** 
  342. 函数名: partion 
  343. 函数功能:快速排序的子函数 
  344. 参数: LinkList* pstHead 链表头  LinkListNode* pstLow 开始排序的头指针  LinkListNode* pstHigh  结束排序的尾指针  
  345. 返回值: LinkListNode* partion  返回中值的指针 
  346. 注意:way_id是比较的数据     data是交换的数据  
  347. *****************************************************************************************************************/   
  348. DLinkListNode* partion(DLinkList* pstHead, DLinkListNode* pstLow, DLinkListNode* pstHigh)    
  349. {    
  350.          list* list_pstLow= (list*) pstLow;  
  351.          list* list_pstHigh= (list*) pstHigh;  
  352.          DATA iTmp;    
  353.          unsigned int pivot = 0;    
  354.          pivot = list_pstLow->data.way_id;    
  355.          while ( pstLow != pstHigh )    
  356.          {    
  357.               //从后面往前换    
  358.               while ( (pstLow != pstHigh) && (list_pstHigh->data.way_id >= pivot))    
  359.               {    
  360.                     pstHigh = pstHigh->pre;   
  361.                     list_pstHigh = (list*) pstHigh;  
  362.               }    
  363.               //交换high low    
  364.               iTmp = list_pstLow->data;    
  365.               list_pstLow->data = list_pstHigh->data;    
  366.               list_pstHigh->data = iTmp;    
  367.                
  368.               //从前往后换    
  369.               while ( pstLow != pstHigh && list_pstLow->data.way_id <= pivot )    
  370.               {    
  371.                     pstLow = pstLow->next;   
  372.                     list_pstLow = (list*)pstLow;  
  373.               }    
  374.               //交换high low    
  375.               iTmp = list_pstLow->data;    
  376.               list_pstLow->data = list_pstHigh->data;    
  377.               list_pstHigh->data = iTmp;    
  378.          }    
  379.          return pstLow;    
  380. }    
  381. /***************************************************************************************************************** 
  382. 函数名: quick_sort 
  383. 函数功能:快速排序 
  384. 参数: LinkList* pstHead 链表头指针 LinkListNode* pstLow 开始排序的头指针 LinkListNode* pstHigh  结束排序的尾指针  
  385. 返回值:void  无返回值  
  386. *****************************************************************************************************************/    
  387. void quick_sort(DLinkList* pstHead, DLinkListNode* pstLow, DLinkListNode* pstHigh)    
  388. {    
  389.     DLinkListNode* pstTmp = NULL;    
  390.     pstTmp = partion(pstHead, pstLow, pstHigh);    
  391.     if ( pstLow != pstTmp )    
  392.     {    
  393.          quick_sort(pstHead, pstLow, pstTmp->pre);    
  394.     }    
  395.      if ( pstHigh != pstTmp )    
  396.      {    
  397.         quick_sort(pstHead, pstTmp->next, pstHigh);    
  398.      }    
  399.      
  400. }    
/*******************************************************************************************************
文件名:DLinkList.c
头文件:DLinkList.h 
时间: 2013/08/17
作者: Hao
功能:  可以复用 带有增 删 改 查 功能的循环链表
难道: 1.typedef struct Str_DLinkList DLinkListNode;  //这个结构体是链表的真身 
		struct Str_DLinkList   //每一个链表元素的结构都会包含这个结构  因为当给链表元素强制类型 
		{                     //转换成(DLinkListNode* )的时候  其实就是要开始对每个元素中的 DLinkListNode进行赋值了 
			DLinkListNode* next;
		}; 
		这个链表结构在链表元素中起到的作用 是本节的难点 
		2.切记一个问题  就是已经是链表中元素的 千万不要再往链表中添加了 否则链表一定出现无穷的错误 
		3.对于pos值的问题  add、get、del三个函数中 的链表都是 从1开始的到length  0是链表头 
						  在add函数中pos为0的时候是和pos为1的情况是一样的  都是头插法  0~~~~~无穷大 
		                  在get函数中pos为0的时候是获得链表头 地址      0~~~~~length 
						  在del函数中pos为0的时候是无效的 del失败       1~~~~~length 
*******************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "DLinkList.h"

typedef struct str_list_head  //这个是链表头 其实也可以当作一个没有前驱的 链表元素 元素的内容是链表长度 
{
	//DLinkListNode* next;
	DLinkListNode head; //这个参数要特别重视 每一个链表元素结构的第一个参数一定是 DLinkListNode
	                   //因为在寻找链表元素后继的时候 其实就是将链表元素强制类型转换成 DLinkListNode*  然后给next进行赋值 其实就是给 DLinkListNode变量赋值 
	DLinkListNode* slider;
	int length; //链表长度 
}list_head;

/*******************************************************************************************************
函数名: Creat_DLinkListHead
函数功能:创建一个链表的链表头 并给链表头分配空间
参数: void
返回值:ret 成功返回链表头地址  失败返回NULL 
*******************************************************************************************************/
DLinkList* Creat_DLinkListHead(void)
{
	list_head* ret = NULL;
	ret = (list_head* )malloc( sizeof(list_head)*1 );
	if(NULL != ret) //malloc分配成功 
	{
		ret->length = 0;
		//ret -> next = NULL;
		ret->head.next = NULL;
		ret->head.pre = NULL;
		ret->slider = NULL;
	}
	return (DLinkList* )ret; 
}

/*******************************************************************************************************
函数名:Destroy_DLinkListHead
函数功能:释放一个链表头指针 
参数:DLinkList* head 链表头指针 
返回值: ret 释放成功返回1  释放失败返回0 
*******************************************************************************************************/
int Destroy_DLinkListHead(DLinkList* head)
{
	int ret = 0; 
	list_head* lhead = (list_head* )head;
	if( NULL != lhead )
	{
		free(lhead);
		ret = 1;
	}
	return ret;
}

/*******************************************************************************************************
函数名:Get_Length
函数功能:获得链表的长度 
参数: DLinkList* head 链表头指针 
返回值: ret 成功返回链表长度  失败返回0 
*******************************************************************************************************/
int Get_Length(DLinkList* head) 
{
	int ret = 0;
	list_head* lhead = (list_head* )head;
	if( NULL != lhead )
	{
		ret = lhead -> length;
	}	
	return ret;
}

/*******************************************************************************************************
函数名:Clean_DLinkListHead
函数功能:	清空链表 
参数: DLinkList* head 链表头指针 
返回值:ret 成功返回1 失败返回0 
*******************************************************************************************************/
int Clean_DLinkListHead(DLinkList* head) 
{
	int ret = 0;
	list_head* lhead = (list_head* )head;
	if( NULL != lhead )
	{
		lhead->length = 0;
		//lhead -> next = NULL;
		lhead->head.next = NULL;
		lhead->head.pre = NULL;
		lhead->slider = NULL;
		ret = 1;
	}	
	return ret;
}

/*******************************************************************************************************
函数名:Add_DLinkList
函数功能:往链表里面添加一个链表元素 如果pos的值是0(就是链表头)和1(链表的第一元素 链表元素个数是从1开始算的)都是头插法
          pos的值大于链表长度是尾插法  这里面pos值得注意的是 i=1 pos为a的时候 是把链表元素插入第a个元素的位置 
          当i=0 pos为a的时候 是把链表元素插入 第a个元素位置的后面    切忌:这里面0位置是链表头指针 从1开始是链表元素 
参数:   DLinkList* head链表头指针    DLinkListNode* Node插入元素的指针(被强制类型转化成DLinkListNode*)  int pos 插入位置 
         pos的有效值范围是 从0到无穷大  
返回值: ret 插入成功返回1  插入失败返回0 
*******************************************************************************************************/
int Add_DLinkList(DLinkList* head, DLinkListNode* Node, int pos)
{
	int ret = 0;
	int i = 0;
	list_head* lhead = (list_head* )head;
	DLinkListNode* node = (DLinkListNode* )head;
	ret=( NULL != node) && ( NULL != Node) && (pos >= 0);
	if(1 == ret)
	{
		for(i=1; ( (i<pos) && (node->next != NULL) ); i++)
		{
			node = node->next;
		}
		/*此处的node是要插入元素的前一个值  Node是要删除的值*/ 
		Node -> next = node -> next;
		node -> next = Node;
		if(NULL != Node->next) //判断是否为尾插法 如果不是进入如下操作   如果是尾插法  最后一个链表元素不当作NULL的前驱 
		{
			Node->next->pre = Node; 
		}
		Node->pre = node;
		
		if( 0==lhead->length ) //在第一次插入元素的时候  把游标指向第一次个元素 
		{
			lhead->slider = Node;
		}
		if( node == (DLinkListNode* )head)  //如果是头插法 就要将第一个链表元素的前驱写成NULL  不然前驱就变成了头节点了 
		{
			Node->pre = NULL;
		}
		
		lhead -> length++; 
	}
	return ret;
}

/*******************************************************************************************************
函数名:Get_DLinkListNode
函数功能:获得链表中第pos个元素位置的链表元素 链表是从1开始的  0是链表头   pos为0的时候表示get链表头 
参数: DLinkList* head链表头指针    int pos获得链表元素的位置  pos的有效取值范围是 1 到  length  0是链表头 
返回值: DLinkListNode*类型 第pos个链表元素的地址 
*******************************************************************************************************/
DLinkListNode* Get_DLinkListNode(DLinkList* head, int pos)
{
	int ret = 0;
	int i = 0;
	list_head* lhead = (list_head* )head;
	ret=( NULL != lhead) && (pos >= 0) && (pos <= lhead->length);
	if(1 == ret)
	{
		DLinkListNode* node = (DLinkListNode* )head;
		for(i=0; i<pos; i++) //执行 pos次   得到的是第pos位置的node 
		{
			node = node->next;
		}	
		return (DLinkListNode*)node;
	}
	return NULL;
}

/*******************************************************************************************************
函数名:Del_DLinkListNode
函数功能:删除链表中第pos位置的链表元素 
参数: DLinkList* head链表头指针    int pos删除链表元素的位置  pos是删除的链表元素的位置 跟get和add中的
       pos是配套的  有效取值范围依然是 1到 length  在这个函数里面由于不能删除链表头 所以pos为0的时候无效 
返回值: DLinkListNode* ret这个返回值很重要 因为这个删除仅仅是把链表元素踢出了链表 并没有free开辟的内存
         应该通过这个返回的地址free  释放内存
		 删除成功返回 删除链表元素的地址   删除失败返回 NULL 
*******************************************************************************************************/
DLinkListNode* Del_DLinkListNode(DLinkList* head, int pos)
{
	DLinkListNode* ret = NULL;
	int i = 0;
	list_head* lhead = (list_head* )head;
	if(( NULL != lhead) && (pos > 0) && (pos <= lhead->length))
	{
		DLinkListNode* node = (DLinkListNode* )head;
		for(i=1; i<pos; i++)//执行 pos次   得到的是第pos位置的node  这个方法行不通 
		{                   //因为要想删除第pos位置的node 应该先找到它上一个链表元素 
			node = node->next; //所以这里面i=1 比get函数少执行了一次  得到第pos-1位置的node 
		}
		/*值得注意的是 此处的node是要删除元素的前一个值  ret是要删除的值*/
		ret = node->next;
		node->next = ret->next;	

		if(NULL != ret->next) //判断删除的值是否为最后一个元素 
		{
			ret->next->pre = ret->pre;
			if(node == (DLinkListNode* )head)//判断删除的值是否为第一个元素 
			{
				ret->next->pre =  NULL;
			} 
			if(lhead->slider == ret) //判断删除的节点是否为游标的位置 
			{
				
				lhead->slider = ret->next; 
			} 
		} 
		else
		{
			if(lhead->slider == ret) //判断删除的节点是否为游标的位置 
			{
				
				lhead->slider = ret->pre; 
			}
		}

		lhead->length--;
	}
	return (DLinkListNode*)ret;
}

/*******************************************************************************************************
函数名: DLinkList_Slider
函数功能:获得当前游标指向的数据
参数: DLinkList* head
返回值:成功返回 DLinkListNode* ret  失败返回NULL 
*******************************************************************************************************/
DLinkListNode* DLinkList_Slider(DLinkList* head)
{
	DLinkListNode* ret = NULL;
	list_head* lhead = (list_head* )head;
	if( (NULL != lhead)&&(NULL != lhead->slider) )//保证slider是有效的 
	{
		ret = lhead->slider;
	}
	return ret;
}

/*******************************************************************************************************
函数名: DLinkList_Reset
函数功能:重置游标 让游标指向head头节点后面的第一个元素 
参数: DLinkList* head
返回值:成功返回 当前游标的指向DLinkListNode* ret  失败返回NULL 
*******************************************************************************************************/
DLinkListNode* DLinkList_Reset(DLinkList* head)
{
	DLinkListNode* ret = NULL;
	list_head* lhead = (list_head* )head;
	if(NULL != lhead)
	{
		lhead->slider = lhead->head.next;
		ret = lhead->slider;
	}
	return ret;
}

/*******************************************************************************************************
函数名: DLinkList_Next
函数功能:使游标指向下一个元素 
参数: DLinkList* head
返回值:成功返回 前游标的指向DLinkListNode* ret  失败返回NULL 
*******************************************************************************************************/
DLinkListNode* DLinkList_Next(DLinkList* head)
{
	DLinkListNode* ret = NULL;
	list_head* lhead = (list_head* )head;
	if((NULL != lhead)&&(NULL != lhead->slider)) //保证游标是有效的 
	{
		ret = lhead->slider;
		lhead->slider = ret->next; 
	}
	return ret;
}

/*******************************************************************************************************
函数名: DLinkList_Pre
函数功能:使游标指向上一个元素 
参数: DLinkList* head
返回值:成功返回 前游标的指向DLinkListNode* ret  失败返回NULL 
*******************************************************************************************************/
DLinkListNode* DLinkList_Pre(DLinkList* head)
{
	DLinkListNode* ret = NULL;
	list_head* lhead = (list_head* )head;
	if((NULL != lhead)&&(NULL != lhead->slider)) //保证游标是有效的 
	{
		ret = lhead->slider;
		lhead->slider = ret->pre; 
	}
	return ret;
}

/*******************************************************************************************************
函数名: DLinkList_Del
函数功能:删除链表中的某个指定元素 
参数: DLinkList* head   DLinkListNode* node为指定的元素 
返回值:成功返回 删除的链表元素  失败返回NULL 
*******************************************************************************************************/
DLinkListNode* DLinkList_Del(DLinkList* head,DLinkListNode* node)
{	//这个函数主要是用来删除游标的返回值的 
 
	DLinkListNode* ret = NULL;
	list_head* lhead = (list_head* )head;
	int i=0; 
	if((NULL != head)&&(NULL != node))
	{
		DLinkListNode* current = (DLinkListNode*)lhead;
		for(i=1; i<=lhead->length; i++)
		{
			if(node == current->next)
			{
				ret = current->next;
				break; 
			} 
			current = current->next;
		}
		
		if(NULL == ret)  //说明没有找到node 
		{
			printf("put error!!!\n"); 
		}
		else //找到了node 
		{
			Del_DLinkListNode(lhead,i); 
			printf("ii%d\n",i);
		} 
	}	
	return ret;//返回删除的链表元素 
}

/*****************************************************************************************************************
函数名: partion
函数功能:快速排序的子函数
参数: LinkList* pstHead 链表头  LinkListNode* pstLow 开始排序的头指针  LinkListNode* pstHigh  结束排序的尾指针 
返回值: LinkListNode* partion  返回中值的指针
注意:way_id是比较的数据     data是交换的数据 
*****************************************************************************************************************/ 
DLinkListNode* partion(DLinkList* pstHead, DLinkListNode* pstLow, DLinkListNode* pstHigh)  
{  
		 list* list_pstLow= (list*) pstLow;
		 list* list_pstHigh= (list*) pstHigh;
		 DATA iTmp;  
		 unsigned int pivot = 0;  
		 pivot = list_pstLow->data.way_id;  
		 while ( pstLow != pstHigh )  
		 {  
			  //从后面往前换  
			  while ( (pstLow != pstHigh) && (list_pstHigh->data.way_id >= pivot))  
			  {  
			   		pstHigh = pstHigh->pre; 
			   		list_pstHigh = (list*) pstHigh;
			  }  
			  //交换high low  
			  iTmp = list_pstLow->data;  
			  list_pstLow->data = list_pstHigh->data;  
			  list_pstHigh->data = iTmp;  
			 
			  //从前往后换  
			  while ( pstLow != pstHigh && list_pstLow->data.way_id <= pivot )  
			  {  
			   		pstLow = pstLow->next; 
			   		list_pstLow = (list*)pstLow;
			  }  
			  //交换high low  
			  iTmp = list_pstLow->data;  
			  list_pstLow->data = list_pstHigh->data;  
			  list_pstHigh->data = iTmp;  
		 }  
		 return pstLow;  
}  
/*****************************************************************************************************************
函数名: quick_sort
函数功能:快速排序
参数: LinkList* pstHead 链表头指针 LinkListNode* pstLow 开始排序的头指针 LinkListNode* pstHigh  结束排序的尾指针 
返回值:void  无返回值 
*****************************************************************************************************************/  
void quick_sort(DLinkList* pstHead, DLinkListNode* pstLow, DLinkListNode* pstHigh)  
{  
 	DLinkListNode* pstTmp = NULL;  
 	pstTmp = partion(pstHead, pstLow, pstHigh);  
 	if ( pstLow != pstTmp )  
 	{  
 		 quick_sort(pstHead, pstLow, pstTmp->pre);  
 	}  
	 if ( pstHigh != pstTmp )  
	 {  
	  	quick_sort(pstHead, pstTmp->next, pstHigh);  
	 }  
   
}  


DLinkList.h:

  1. #ifndef __DLinkList_H__  
  2. #define __DLinkList_H__  
  3.   
  4. typedef void DLinkList;  //这个是为了 封装方便   
  5. typedef struct Str_DLinkList DLinkListNode;  //这个结构体是链表的真身   
  6. struct Str_DLinkList   //每一个链表元素的结构都会包含这个结构  因为当给链表元素强制类型   
  7. {                     //转换成(DLinkListNode* )的时候  其实就是要开始对每个元素中的 DLinkListNode进行赋值了   
  8.     DLinkListNode* next;  
  9.     DLinkListNode* pre;  
  10. };  
  11. /**************************************如下参数是为了快速排序罗列的****************************************/  
  12. typedef struct _tag_DATA  
  13. {  
  14.     unsigned int data_length;    //dat中前2个字节  表示一条信息的长度  在用多少个字节   
  15.     unsigned int way_id;         //4个字节  表示道路唯一id   
  16.     unsigned int way_name_length;//2个字节  表示道路名称所占字节数 注意:这个不准   
  17.     unsigned int way_data;       //4个字节  表示道路信息  0~3位表示Class番号   4~6位表示岔路数   7位表示有无flag  
  18.     unsigned char Class;         //way_data & 0000 0000 0000 0000 0000 0000 0000 1111   0x0f  
  19.     unsigned char byroad_num;    //way_data & 0000 0000 0000 0000 0000 0000 0111 0000   0x70  
  20.     unsigned char flag;          //way_data & 0000 0000 0000 0000 0000 0000 1000 0000   0x80  
  21.     char way_name[256];          //data_length-12个字节   表示道路名称   
  22. }DATA;  
  23.   
  24.   
  25. typedef struct _tag_list  
  26. {  
  27.     DLinkListNode head;   
  28.     DATA data;   
  29. }list;  
  30. /****************************************************************************************/  
  31.   
  32. DLinkList* Creat_DLinkListHead(void);  
  33.   
  34. int Destroy_DLinkListHead(DLinkList* head);  
  35.   
  36. int Get_Length(DLinkList* head);  
  37.   
  38. int Clean_DLinkListHead(DLinkList* head);  
  39.   
  40. int Add_DLinkList(DLinkList* head, DLinkListNode* Node, int pos);  
  41.   
  42. DLinkListNode* Get_DLinkListNode(DLinkList* head, int pos);  
  43.   
  44. DLinkListNode* Del_DLinkListNode(DLinkList* head, int pos);   
  45.   
  46. DLinkListNode* DLinkList_Slider(DLinkList* head);  
  47.   
  48. DLinkListNode* DLinkList_Reset(DLinkList* head);  
  49.   
  50. DLinkListNode* DLinkList_Next(DLinkList* head);  
  51.   
  52. DLinkListNode* DLinkList_Pre(DLinkList* head);  
  53.   
  54. DLinkListNode* DLinkList_Del(DLinkList* head,DLinkListNode* node);  
  55.   
  56.    
  57.    
  58. #endif  
#ifndef __DLinkList_H__
#define __DLinkList_H__

typedef void DLinkList;  //这个是为了 封装方便 
typedef struct Str_DLinkList DLinkListNode;  //这个结构体是链表的真身 
struct Str_DLinkList   //每一个链表元素的结构都会包含这个结构  因为当给链表元素强制类型 
{                     //转换成(DLinkListNode* )的时候  其实就是要开始对每个元素中的 DLinkListNode进行赋值了 
	DLinkListNode* next;
	DLinkListNode* pre;
};
/**************************************如下参数是为了快速排序罗列的****************************************/
typedef struct _tag_DATA
{
	unsigned int data_length;    //dat中前2个字节  表示一条信息的长度  在用多少个字节 
	unsigned int way_id;         //4个字节  表示道路唯一id 
	unsigned int way_name_length;//2个字节  表示道路名称所占字节数 注意:这个不准 
	unsigned int way_data;       //4个字节  表示道路信息  0~3位表示Class番号   4~6位表示岔路数   7位表示有无flag
	unsigned char Class;         //way_data & 0000 0000 0000 0000 0000 0000 0000 1111   0x0f
	unsigned char byroad_num;    //way_data & 0000 0000 0000 0000 0000 0000 0111 0000   0x70
	unsigned char flag;          //way_data & 0000 0000 0000 0000 0000 0000 1000 0000   0x80
	char way_name[256];          //data_length-12个字节   表示道路名称 
}DATA;


typedef struct _tag_list
{
	DLinkListNode head; 
	DATA data; 
}list;
/****************************************************************************************/

DLinkList* Creat_DLinkListHead(void);

int Destroy_DLinkListHead(DLinkList* head);

int Get_Length(DLinkList* head);

int Clean_DLinkListHead(DLinkList* head);

int Add_DLinkList(DLinkList* head, DLinkListNode* Node, int pos);

DLinkListNode* Get_DLinkListNode(DLinkList* head, int pos);

DLinkListNode* Del_DLinkListNode(DLinkList* head, int pos); 

DLinkListNode* DLinkList_Slider(DLinkList* head);

DLinkListNode* DLinkList_Reset(DLinkList* head);

DLinkListNode* DLinkList_Next(DLinkList* head);

DLinkListNode* DLinkList_Pre(DLinkList* head);

DLinkListNode* DLinkList_Del(DLinkList* head,DLinkListNode* node);

 
 
#endif


main.c:

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include "DLinkList.h"  
  4.   
  5. typedef struct _tag_str  
  6. {  
  7.     DLinkListNode head;  
  8.     int i;  
  9. }str;  
  10. int main(int argc, char *argv[])  
  11. {  
  12.     int j = 0;  
  13.     DLinkList* list_head;  
  14.     list_head = Creat_DLinkListHead();  
  15.     str str1,str2,str3,str4,str5,str6,*strp;  
  16.     str1.i=1;  
  17.     str2.i=2;  
  18.     str3.i=3;  
  19.     str4.i=4;  
  20.     str5.i=5;  
  21.     str6.i=6;  
  22.   
  23.     Add_DLinkList(list_head, (DLinkListNode*)&str1,12);  
  24.     Add_DLinkList(list_head, (DLinkListNode*)&str2,12);  
  25.     Add_DLinkList(list_head, (DLinkListNode*)&str3,12);  
  26.     Add_DLinkList(list_head, (DLinkListNode*)&str4,12);  
  27.     Add_DLinkList(list_head, (DLinkListNode*)&str5,12);  
  28.       
  29.       
  30. //  Add_DLinkList(list_head, (DLinkListNode*)&str6,0);  
  31.     for(j=1;j<=Get_Length(list_head);j++)  
  32.     {  
  33.         strp = (str* )Get_DLinkListNode(list_head, j);  
  34.         printf("%d\n",strp->i);  
  35.     }  
  36.   
  37.   
  38.     printf("\n");  
  39.     //DLinkList_Reset(list_head);  
  40.     strp = (str* )DLinkList_Slider(list_head);  
  41.     printf("%d\n",strp->i);  
  42.     printf("\n");  
  43.     for(j=1;j<=Get_Length(list_head)-1;j++)  
  44.     {  
  45.         DLinkList_Next(list_head);  
  46.         strp = (str* )DLinkList_Slider(list_head);  
  47.         printf("%d\n",strp->i);  
  48.     }  
  49.       
  50.     DLinkList_Del(list_head,(DLinkListNode*)&str5);  
  51.     printf("\n");  
  52.       
  53.     for(j=1;j<=Get_Length(list_head)-1;j++)  
  54.     {  
  55.         DLinkList_Pre(list_head);  
  56.         strp = (str* )DLinkList_Slider(list_head);  
  57.         printf("%d\n",strp->i);  
  58.     }     
  59.   
  60.       
  61.     Destroy_DLinkListHead(list_head);  
  62.     return 0;  
  63. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值