• C和指针 第十二章 使用结构和指针 双链表和语句提炼


    双链表中每个节点包含指向当前和之后节点的指针,插入节点到双链表中需要考虑四种情况:

    1、插入到链表头部

    2、插入到链表尾部

    3、插入到空链表中

    4、插入到链表内部

    #include <stdio.h>
    #include <stdlib.h>
    #define TRUE 1
    #define FALSE 0
    
    //指针fwd指向前一个节点,bwd指向后一个节点
    typedef struct NODE {
    	struct NODE *fwd;
    	struct NODE *bwd;
    	int value;
    } Node;
    
    //插入value到双链表中,rootPtr为指向节点的指针
    int doubleLinklistInsert(Node *rootPtr, int value)
    {
    	Node *this;
    	Node *next;
    	Node *newNode;
    
    	for(this = rootPtr; (next = this -> fwd) != NULL; this = next){
    		//如果节点值已经存在
    		if(next	-> value == value){
    			return FALSE;
    		}
    		//找到插入位置
    		if(next -> value > value){
    			break;
    		}
    	}
    
    	//分配内存
    	newNode = (Node *)malloc(sizeof(Node));
    	if(newNode == NULL){
    		return FALSE;
    	}
    
    	newNode -> value = value;
    
    	/*插入节点一共四种情况
    	1.插入到头部
    	2.插入到尾部
    	3.插入到中间
    	4.插入到空链表中
    	*/
    	//如果插入到头部部或者内部
    	if(next != NULL){
    		//插入到内部
    		if(this != rootPtr){
    			newNode -> fwd = next;
    			newNode -> bwd = this;
    			this -> fwd = newNode;
    			next -> bwd = newNode;
    		}else{
    			//插入到头部,newNode的bwd为NULL
    			newNode -> fwd = next;
    			newNode -> bwd = NULL;
    			rootPtr -> fwd = newNode;
    			next -> bwd = newNode;
    		}
    	}else{
    		//插入到尾部或者空表中
    		if(this != rootPtr){
    			//插入到尾部,修改根指针的bwd和fwd
    			newNode -> fwd = NULL;
    			newNode -> bwd = this;
    			this -> fwd = newNode;
    			rootPtr -> bwd = newNode;
    		}else{
    			//插入到空链表中
    			newNode -> fwd = NULL;
    			newNode -> bwd = NULL;
    			this -> fwd = newNode;
    			this -> bwd = newNode;
    		}
    	}
    
    	return TRUE;
    }
    
    int main()
    {
    	Node third;
    	Node second;
    	Node first;
    
    	third = (Node){NULL, &second, 4};
    	second = (Node){&third, &first, 2};
    	first = (Node){&second, NULL, 1};
    
    	Node root = {&first, &third, -1};
    	Node *rootPtr = &root;
    
    	doubleLinklistInsert(rootPtr, 35);
    	doubleLinklistInsert(rootPtr, -10);
    	doubleLinklistInsert(rootPtr, 3);
    
    	rootPtr = &root;
    	while((rootPtr = rootPtr -> fwd) != NULL){
    		printf("%d	", rootPtr -> value);
    	}
    	return 0;
    }
    

      运行:

    优化:

    1.语句提炼

    对于下面的代码可以从if语句中,提取出共同的部分。

    if(x = 3){
        i = 1;
        something;
    }else{
        i = 1;
        something different;        
    }
    

    将共同的i=1,提取出if语句

     i = 1;
    if(x = 3){
        something;
    }else{
        something different;        
    }
    

    代码提炼:提取共同项

        if(next != NULL){
            newNode -> fwd = next;
            next -> bwd = newNode;
            //插入到内部
            if(this != rootPtr){
                newNode -> bwd = this;
                this -> fwd = newNode;
            }else{
                //插入到头部,newNode的bwd为NULL
                newNode -> bwd = NULL;
                rootPtr -> fwd = newNode;
            }
        }else{
            //插入到尾部或者空表中
            newNode -> fwd = NULL;
            this -> fwd = newNode;
            if(this != rootPtr){
                //插入到尾部,修改根指针的bwd和fwd
                newNode -> bwd = this;
                rootPtr -> bwd = newNode;
            }else{
                //插入到空链表中
                newNode -> bwd = NULL;
                this -> bwd = newNode;
            }
        }

    对于下面的情况

    if(field!= NULL){
        pointer = field;
    }else{
        pointer=NULL;
    }
    //第二种情况field等于NULL,所以上面条件语句可以写成
    pointer =field;
    

    要找出看起来虽然不一样,但逻辑上是相同的代码,进行简化,这里第二个else中this此时是等于rootPtr的,所以相同, this转换成rootPtr,然后提取出。提取之后两个条件语句中都有:

            if(this != rootPtr){
                //插入到尾部,修改根指针的bwd和fwd
                newNode -> bwd = this;
                this -> fwd = newNode;
            }else{
                //插入到空链表中
                newNode -> bwd = NULL;
                rootPtr -> fwd = newNode;
            }    
    

    提取出来:

        if(this != rootPtr){
            //插入到尾部,修改根指针的bwd和fwd
            newNode -> bwd = this;
            this -> fwd = newNode;
        }else{
            //插入到空链表中
            newNode -> bwd = NULL;
            rootPtr -> fwd = newNode;
        }
        
        if(next != NULL){
            newNode -> fwd = next;
            next -> bwd = newNode;
            //插入到内部
        }else{
            //插入到尾部或者空表中
            newNode -> fwd = NULL;
            rootPtr -> bwd = newNode;
        }
    

      下面的第二个else中的next是NULL,所以NULL可以转换一下,继续提取出来:

        newNode -> fwd = next;
        if(next != NULL){
            next -> bwd = newNode;
        }else{
            rootPtr -> bwd = newNode;
        }
    
        if(this != rootPtr){
            newNode -> bwd = this;
            this -> fwd = newNode;
        }else{
            newNode -> bwd = NULL;
            rootPtr -> fwd = newNode;
        }

    提取出来,最终简化版:

    #include <stdio.h>
    #include <stdlib.h>
    #define TRUE 1
    #define FALSE 0
    
    //指针fwd指向前一个节点,bwd指向后一个节点
    typedef struct NODE {
        struct NODE *fwd;
        struct NODE *bwd;
        int value;
    } Node;
    
    //插入value到双链表中,rootPtr为指向节点的指针
    int doubleLinklistInsert(Node *rootPtr, int value)
    {
        Node *this;
        Node *next;
        Node *newNode;
    
        for(this = rootPtr; (next = this -> fwd) != NULL; this = next){
            //如果节点值已经存在
            if(next	-> value == value){
                return FALSE;
            }
            //找到插入位置
            if(next -> value > value){
                break;
            }
        }
    
        //分配内存
        newNode = (Node *)malloc(sizeof(Node));
        if(newNode == NULL){
            return FALSE;
        }
    
        newNode -> value = value;
    
        /*插入节点一共四种情况
        1.插入到头部
        2.插入到尾部
        3.插入到中间
        4.插入到空链表中
        */
        //如果插入到头部部或者内部
    
        newNode -> fwd = next;
        if(next != NULL){
            next -> bwd = newNode;
        }else{
            rootPtr -> bwd = newNode;
        }
    
        if(this != rootPtr){
            newNode -> bwd = this;
            this -> fwd = newNode;
        }else{
            newNode -> bwd = NULL;
            rootPtr -> fwd = newNode;
        }
    
        return TRUE;
    }
    
    int main()
    {
        Node third;
        Node second;
        Node first;
    
        third = (Node){NULL, &second, 4};
        second = (Node){&third, &first, 2};
        first = (Node){&second, NULL, 1};
    
        Node root = {&first, &third, -1};
        Node *rootPtr = &root;
    
        doubleLinklistInsert(rootPtr, 35);
        doubleLinklistInsert(rootPtr, -10);
        doubleLinklistInsert(rootPtr, 3);
    
        rootPtr = &root;
        while((rootPtr = rootPtr -> fwd) != NULL){
            printf("%d	", rootPtr -> value);
        }
        return 0;
    }
    

      运行:

    通过提炼语句,消除if语句中的重复语句。

  • 相关阅读:
    GPS时间服务器在广电系统的应用
    时钟系统报价分析
    北斗校时服务器装置介绍
    时钟服务器的安装与调试
    频率计使用说明
    通用计数器使用方法
    WOL持久化配置
    RGB屏驱动流程
    iOS-苹果登陆授权(AppleID SignIn)
    VSCODE自用快捷键备忘
  • 原文地址:https://www.cnblogs.com/yangxunwu1992/p/5847743.html
Copyright © 2020-2023  润新知