zoukankan      html  css  js  c++  java
  • 数据结构学习笔记(4.线性表之双向链表)

    本节知识点:

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

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

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



         (1).正常的链表插入操作,代码如下:
    for(i=1; ( (i<pos) && (node->next != NULL) ); i++)
    {
    	node = node->next;
    }
    /*此处的node是要插入元素的前一个值  Node是要删除的值*/ 
    Node -> next = node -> next;
    node -> next = Node;
         (2).把附近的两个链表的前驱pre都赋值为正确的值,代码如下:
    if(NULL != Node->next) //判断是否为尾插法 如果不是进入如下操作   如果是尾插法  最后一个链表元素不当作NULL的前驱 
    {
    	Node->next->pre = Node; 
    }
    Node->pre = node;
         (3).如果是头插法,要记得把插入的元素结点的前驱pre赋值为NULL,代码如下:
    if( node == (DLinkListNode* )head)  //如果是头插法 就要将第一个链表元素的前驱写成NULL  不然前驱就变成了头节点了 
    {
    	Node->pre = NULL;
    }
        (4).第一次插入链表元素,要把游标指向插入的链表元素,代码如下:
    if( 0==lhead->length ) //在第一次插入元素的时候  把游标指向第一次个元素 
    {
    	lhead->slider = Node;
    }
         第三步 (改写删除函数):
         有三种情况分别是:删除的是第一个结点元素,删除的是最后一个结点元素,删除的是中间结点元素。
         (1).删除第一个结点元素:要注意给下一个结点元素的前驱pre赋值为NULL,不是指向head
         (2).删除最后一个结点元素:要注意不要给next的前驱再赋值了,因为next已经为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;
    }

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


    本节代码:

    DLinkList.c:

    /*******************************************************************************************************
    文件名: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!!!
    "); 
    		}
    		else //找到了node 
    		{
    			Del_DLinkListNode(lhead,i); 
    			printf("ii%d
    ",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:

    #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:

    #include <stdio.h>
    #include <stdlib.h>
    #include "DLinkList.h"
    
    typedef struct _tag_str
    {
    	DLinkListNode head;
    	int i;
    }str;
    int main(int argc, char *argv[])
    {
    	int j = 0;
    	DLinkList* list_head;
    	list_head = Creat_DLinkListHead();
    	str str1,str2,str3,str4,str5,str6,*strp;
    	str1.i=1;
    	str2.i=2;
    	str3.i=3;
    	str4.i=4;
    	str5.i=5;
    	str6.i=6;
    
    	Add_DLinkList(list_head, (DLinkListNode*)&str1,12);
    	Add_DLinkList(list_head, (DLinkListNode*)&str2,12);
    	Add_DLinkList(list_head, (DLinkListNode*)&str3,12);
    	Add_DLinkList(list_head, (DLinkListNode*)&str4,12);
    	Add_DLinkList(list_head, (DLinkListNode*)&str5,12);
    	
    	
    //	Add_DLinkList(list_head, (DLinkListNode*)&str6,0);
    	for(j=1;j<=Get_Length(list_head);j++)
    	{
    		strp = (str* )Get_DLinkListNode(list_head, j);
    		printf("%d
    ",strp->i);
    	}
    
    
    	printf("
    ");
    	//DLinkList_Reset(list_head);
    	strp = (str* )DLinkList_Slider(list_head);
    	printf("%d
    ",strp->i);
    	printf("
    ");
    	for(j=1;j<=Get_Length(list_head)-1;j++)
    	{
    		DLinkList_Next(list_head);
    		strp = (str* )DLinkList_Slider(list_head);
    		printf("%d
    ",strp->i);
    	}
    	
    	DLinkList_Del(list_head,(DLinkListNode*)&str5);
    	printf("
    ");
    	
    	for(j=1;j<=Get_Length(list_head)-1;j++)
    	{
    		DLinkList_Pre(list_head);
    		strp = (str* )DLinkList_Slider(list_head);
    		printf("%d
    ",strp->i);
    	}	
    
    	
    	Destroy_DLinkListHead(list_head);
    	return 0;
    }
    
    
    
    
    


     

     
  • 相关阅读:
    RabbitMQ
    连接池,为什么要使用连接池?
    mac 安装arcanist
    感触
    UDP socket
    Servlet过滤器
    PL、SQL
    springmvc 文件上传实现(不是服务器的)
    注解spring
    excel工具类
  • 原文地址:https://www.cnblogs.com/pangblog/p/3271524.html
Copyright © 2011-2022 走看看