• 双向链表


    引言:


            单链表存在一个问题,当我们想要訪问某个结点的前一个结点时。要从头结点開始訪问。显然这种操作是令人烦躁的。为此,双向链表出现,它比单链表多出了一个指针域。指向前一个结点。

    这样,对于双向链表。就能够方便的从后向前遍历链表了。但多出的问题是对于插入和删除结点的开销要添加一倍。


    分析描写叙述:


            双向链表存储结构图为:,用结构体表演示样例如以下:

    typedef	int	ElemType;
    typedef struct LNode{
    	ElemType	data;
    	struct LNode *prior;
    	struct LNode *next;
    }LNode, *PLNode;
    

            双向链表的初始化。

    双向链表的初始化,即分配一个LNode结构体大小的内存。使它的prior指针和next指针都指向结点本身。

    PLNode InitDList(void)
    {
    	PLNode HeadLNode = (PLNode)malloc(sizeof(LNode));
    	if(HeadLNode == NULL){
    		printf("malloc memory fail.
    ");	
    		return NULL;
    	}
    
    	HeadLNode->prior = HeadLNode->next = HeadLNode;
    
    	return HeadLNode;
    }
    

            双向链表创建链表。

    向已经初始化的双向链表的头部插入结点元素。

    PLNode CreateDList(PLNode PHeadNode)
    {
    	PLNode TmpLNode = (PLNode)malloc(sizeof(LNode));
    	if(TmpLNode == NULL){
    		printf("malloc memory fail.
    ");	
    		return PHeadNode;
    	}
    	TmpLNode->next = NULL;
    
    	while(scanf("%d", &TmpLNode->data) != 0){
    		TmpLNode->next        = PHeadNode->next;
    		TmpLNode->prior       = PHeadNode;
    		PHeadNode->next       = TmpLNode;
    		if(TmpLNode->next != NULL)//此处的推断是针对空链表的操作,假设是空链表,以下的语句就不做。
    			TmpLNode->next->prior = TmpLNode;	
    
    		TmpLNode = (PLNode)malloc(sizeof(LNode));
    		if(TmpLNode == NULL){
    			return PHeadNode;
    		}
    	}
    	free(TmpLNode);
    
    	return PHeadNode;
    }
    

              双向链表的遍历。

    此处的链表的遍历与前面提到的单链表的遍历没有什么不同。须要注意的地方还是对參数的保护。

    void TraverseDList(PLNode PHeadNode)
    {
    	PLNode TmpLNode = PHeadNode;
    
    	if(PHeadNode == NULL) {
    		printf("input element faulse.
    ");
    		return ;
    	}
    
    	while(TmpLNode->next != NULL){
    		printf("%d ", TmpLNode->next->data);	
    		TmpLNode = TmpLNode->next;
    	}
    	putchar('
    ');
    }
    

             双向链表的长度。

    跟求单链表长度一样。          

    int ListLength(PLNode PHeadNode)
    {
    	int count = 0;
    	while(PHeadNode->next != NULL){
    		count++;
    		PHeadNode = PHeadNode->next;	
    	}
    
    	return count;
    }
    

             双向链表中插入节点元素。给定一个双向链表和插入位置,给定一个结点元素,向给定的链表中插入该结点。

    PLNode InsertDList(PLNode PHeadNode, ElemType data, int Index)
    {
    	int index = 0;
    	PLNode TmpLNode = PHeadNode;
    
    	if(PHeadNode == NULL || Index < 0 || Index > ListLength(PHeadNode) + 1){
    		printf("input element faulse.
    ");	
    		return NULL;
    	}
    
    	for(index = 1; index < Index; index++){
    		TmpLNode = TmpLNode->next;	
    	}
    
    	PLNode Tmp = (PLNode)malloc(sizeof(LNode));
    	if(Tmp == NULL){
    		printf("malloc memory faluse.
    ");	
    		return PHeadNode;
    	}
    	Tmp->data = data;
    
    	Tmp->next = TmpLNode->next;
    	Tmp->prior = TmpLNode->prior;
    	TmpLNode->next = Tmp;
    	TmpLNode->prior = Tmp;
    
    	return PHeadNode;
    }
    

              双向链表中删除结点

    PLNode DeleteList(PLNode PHeadNode,  int Index)
    {
    	int index;
    	PLNode TmpNode = PHeadNode;
    
    	if(PHeadNode == NULL || Index < 0 || Index > ListLength(PHeadNode)){
    		printf("input element faulse.
    ");	
    		return NULL;
    	}
    	
    
    	for(index = 0; index < Index; index++){
    		TmpNode = TmpNode->next;	
    	}
    	TmpNode->prior->next = TmpNode->next;
    	if(TmpNode->next != NULL)
    		TmpNode->next->prior = TmpNode->prior;
    	free(TmpNode);
    
    	return PHeadNode;
    }
    

            双向链表中删除结点。

    PLNode DeleteList(PLNode PHeadNode,  int Index)
    {
    	int index;
    	PLNode TmpNode = PHeadNode;
    
    	if(PHeadNode == NULL || Index <= 0 || Index > ListLength(PHeadNode)){
    		printf("input element faulse.
    ");	
    		return NULL;
    	}
    	
    	for(index = 0; index < Index; index++){
    		TmpNode = TmpNode->next;	
    	}
    
    	TmpNode->prior->next = TmpNode->next;
    	TmpNode->next->prior = TmpNode->prior;
    
    	free(TmpNode);
    
    	return PHeadNode;
    }
    


  • 相关阅读:
    夺命雷公狗---微信开发22----微信客户端下载多媒体文件
    夺命雷公狗---微信开发21----通过程序进行下载多媒体文件
    夺命雷公狗---微信开发20----编写程序进行上传多媒体文件
    夺命雷公狗---微信开发19----使用网页调试工具调试该接口进行文件的上传与下载
    夺命雷公狗---微信开发18----删除自定义菜单
    夺命雷公狗---微信开发17----自定义菜单的事件推送,响应菜单的CLICK
    夺命雷公狗---微信开发16----自定义菜单的查询
    夺命雷公狗---微信开发15----编写进行创建自定义菜单
    夺命雷公狗---微信开发14----用网页调试工具调试自定义菜单接口
    夺命雷公狗---微信开发13----获取access_token
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5350758.html
Copyright © 2020-2023  润新知