通过组合结构和指针可以创建强大的数据结构。该博客只是针对了单链表来看的。
链表的每一个结点都是一个结构体,其中有两个元素分别是:1、指向下一个结点的指针(link)和该结点数据(value)。其中需要一个根指针指向第一个结点(root)。
插入的思想是通过比较当前结构的数据和要插入的数据(new_value)大小,从而判断插入位置。首先需要定义两个指针变量,一个指向当前结构(current),一个指向当前结构的前一个结构(previous)。当判断好位置之后需要做的就是分配一个新结点(new),同时将结点插入。
代码如下:
#include <stdlib.h> #include <stdio.h> #include "sll_node.h" #define FALSE 0 #define TRUE 1 int sll_insert( Node *current, int new_value ) { Node *previous; Node *new; /* **寻找正确的插入位置,方法是按顺序访问链表,直到到达其值大于或等于 **新插入的节点值。 */ while( current->value < new_value ) { previous = current; current = current->link; } /* **为新节点分配内存,并把新值存储到新结点中,如果内存分配失败, **函数返回FALSE。 */ new = (Node *)malloc( sizeof( Node )); if( new == NULL ) return FALSE; new->value = new_value; /* **把新节点插入到链表中,并返回TRUE。 */ new->link = current; previous->link = new; return TRUE; }
但是其中存在如下问题:1、在判断插入位置的过程中,要判断是否已经访问到最后一个结点,如果不做此判断在循环指针赋值的过程中由于current为空指针会造成间接访问失败。2、如果在链表第一个位置插入结点就需要改变根指针,因此就需要定义个指向根指针的指针(rootp),通过对根指针的指针来对对根节点进行操作。对比上一个代码有如下代码:
#include <stdlib.h> #include <stdio.h> #include "sll_node.h" #define FALSE 0 #define TRUE 1 int sll_insert( Node **rootp, int new_value ) { Node *current; Node *previous; Node *new; /* **得到指向第一个结点的指针。 */ current = *rootp; previous = NULL; /* **寻找正确的插入位置,方法是按顺序访问链表,直到到达其值大于或等于 **新插入的节点值。 */ while( current != NULL && current->value < new_value ) { previous = current; current = current->link; } /* **为新节点分配内存,并把新值存储到新结点中,如果内存分配失败, **函数返回FALSE。 */ new = (Node *)malloc( sizeof( Node )); if( new == NULL ) return FALSE; new->value = new_value; /* **把新节点插入到链表中,并返回TRUE。 */ new->link = current; if( previous == NULL ) *rootp = new; else previous->link = new; return TRUE; }
好像调试升级以后就已经很好了,但是其实还可以再进行优化升级,优化升级的思想就是排除起始位置的特殊情况,抓住其中的共性来进行操作。链表的共性就是每一个结点都有一个指向它的指针。第一个结点的指针是根指针(root),其他结点的指针是上一个结点的指针元素(link)。因此在这里定义一个指针(linkp),这个指针可以指向一个字段,该字段是指向下一个结点的指针;最初该指针指向根指针,即指向第一个结点的指针。还需要一个指向当前结点的指针(current)。如此一来我们便将关注中心从结点到了指向下一个结点的指针。对比上边代码如下:
#include <stdlib.h> #include <stdio.h> #include "sll_node.h" #define FALSE 0 #define TRUE 1 int sll_insert( register Node **linkp, int new_value ) { register Node *current; register Node *new; /* **寻找正确的插入位置,方法是按顺序访问链表,直到到达其值大于或等于 **新插入的节点值。 */ while((current = *linkp) != NULL && current->value < new_value ) { linkp = ¤t->link; } /* **为新节点分配内存,并把新值存储到新结点中,如果内存分配失败, **函数返回FALSE。 */ new = (Node *)malloc( sizeof( Node )); if( new == NULL ) return FALSE; new->value = new_value; /* **把新节点插入到链表中,并返回TRUE。 */ new->link = current; *linkp = new; return TRUE; }
从这三步的优化中第二步是对第一步的错误进行处理的过程,第三步是对第二步的操作优化,优化的思想是从看上去不同的操作中去总结共性,即抽象,找到共性后就可以用一项操作完成多个看似不同的任务,其实我们一直在做这些东西,不仅从知识中找共性,从生活中也可以找共性,从生活的现象中抽象出来的就是规律,其实规律还可以再做进一步的抽象,一步步向上抽象就可以发现一些最根本的规律和真理,然后我们就可以依据这些规律和真理去注重我们日常的一些具体的行为和举动,从而帮助我们处理好一些问题。
原文地址:http://blog.csdn.net/rcj183419/article/details/45790381