针对插入到一个有序的单链表的小程序所做的调试
《C和指针》第12章-使用结构和指针
针对插入到一个有序的单链表的小程序所做的调试:
原理都是保存一个指向链表当前节点之前的那个节点的指针。
第一次:函数的参数是指向节点的指针
问题:当插入到链表的起始位置时,需要修改根指针,但此时函数中的根指针只是原指针的一份拷贝,无法修改。可以通过将根指针声明为全局变量来修改它,但这样一来,这个函数只对这个链表起作用。
第二次:函数的参数是指向节点的指针的指针
优点:将指向链表当前节点之前的节点指针初始化为NULL, 通过判断该指针是否为NULL来完善插入到链表起始位置的代码,这次程序可以修改指向起始节点的指针。
问题:必须将插入到链表起始位置作为一种特殊情况。
第三次:把关注点放在需要修改的节点的next字段
分析如下:
typedef struct Node
{
struct Node *next; //注意这里next部分放在前面
int data;
}Node;
需要修改的是某个节点的next段,因此要先保存它,然后指针指向下一个节点。
Node **linkp;
Node *current;
linkp=¤t->next;
current=*linkp;
这段代码中,*linkp是前一个节点的next字段内容,即下个节点的地址。当需要插入新节点时,只需将新节点的next指向current,然后将*linkp修改为这个新节点的地址。与之前的用一个previous指针保存之前节点的指针相比,优点就在于,不需要将起始位置作为特殊情况判断,因为*linkp本身就是指向第一个节点的指针,可以直接修改,而previous初始为NULL,无法取得previous->next.
以下为函数代码:
int sll_insert(Node **rootp,int value)
{
Node *front=*rootp;
Node *current;
Node *newNode;
while((current=*rootp)!=NULL&¤t->data<value) //循环体简单,局部性好
rootp=¤t->next;
newNode=(Node*)malloc(sizeof(Node));
if(newNode==NULL)
return false;
newNode->data=value;
newNode->next=current;
*rootp=newNode;
return true;
}
总结:写出一个正确的程序不难,写出一个好的程序才需要实力。反复调试,精益求精。