(原创)C语言单链表插入

原创 2012年03月31日 14:35:09


                                                                      (原创)C语言单链表插入


更多内容,请浏览 : http://www.360doc.com/showWeb/0/0/199614715.aspx

关于C语言单链表插入的程序,想必大家再熟悉不过了,所涉及的逻辑非常简单,

但是要将这个程序完整无误的写好,可不是那么容易。

因为涉及到:
1. 循环结束的判断:
    A。 找到了比插入结点数值大的结点,说明要插入的位置找到了,就在这个数值更大的结点之前
    B。 当前链表中没有比这个结点数值更大的,那么我们要将待插入结点放到链表结尾。
          之时,我们循环结束的条件就是当前遍历链表的指针是否为NULL。
    C。如果待插入结点数值比所有结点数值都小(我们判断时只需要判断比第一个结点小),
          我们需要将此结点插入到链表头,并且修改链表头指针。
 
对于A,是大多数情况,也就是我们程序的基本流程,而对于B,C,我们可以视为特殊情况,在
处理时单独处理。事实上,如果我们使用“头结点”的方式,可以不必特殊处理C。此时,头结点
只是一个空结点,里面的link指针,指向我们真正要使用的结点所在链表的第一个结点。那么,
即使出现情况C,我们只需要将新插入结点的next指针指向第一个结点,即头结点所指向的结点,
而将head->next指向新插入的结点,如果开始扫描前,用prev指向头结点,pcur指向当前扫描结点,
pnew_node ->link = pcur;
prev->link = pnew_node ;
就可以对A,C统一处理了。

当然,我这里想要介绍的可不是这样的方法。在《pointer on C》这本书里面,讲述了另外一个巧妙
的理解。此理解基于"当移动到下一个结点时,我们保存一个指向下一个结点的next指针“,而不是保存
指向前一个结点的指针,也就是不再需要prev指针。除了第一个结点,其他位置的插入,实际修改的是
前一个结点的link 字段。

我们”聚焦“ link字段,而非结点指针。

示例程序如下:
#if 1

#include <stdio.h>
#include <stdlib.h>

#define  INSERT_OK   0
#define  INSERT_ERR  -1

typedef  struct Node
{
struct Node *link;
int value;
}Node;


int list_insert( Node **linkp, int node_val)
{
Node *pcur;
Node *pnew_node;
/*
寻找正确的插入位置,方法是按序访问链表,直到
找到一个其值大于或等于新值的节点 
*/ 
while((pcur = *linkp) != NULL && 
      pcur->value < node_val)
{
    linkp = &pcur->link;
}
pnew_node = (Node *)malloc(sizeof(Node));
if(pnew_node == NULL)
{
    return INSERT_ERR;
}
pnew_node->value = node_val;
pnew_node->link = pcur;
*linkp = pnew_node;
return INSERT_OK;
}

void print_link_list(Node *proot)
{
    Node *p = proot;
    printf(" data in link list are : \n");
    while(p != NULL)
    {
        printf(" Node_val = %d \n", p->value);
        p = p->link;
    } 

}

int main()
{
    Node *phead = NULL;
    int  i4_ret  = 0;
    
    i4_ret = list_insert(&phead,5);
    if(i4_ret < 0)
    {
        printf("list insert fail : node_val = 5 \n");
    }
    i4_ret = list_insert(&phead,10);
    if(i4_ret < 0)
    {
        printf("list insert fail : node_val = 10 \n");
    }
    i4_ret = list_insert(&phead,15);
    if(i4_ret < 0)
    {
        printf("list insert fail : node_val = 15 \n");
    }
    print_link_list(phead);
    printf(" Test Insert_list function with  3,12,20 \n");
    printf(" Now try to insert  3  : \n");
    i4_ret = list_insert(&phead,3);
    if(i4_ret < 0)
    {
        printf("list insert fail : node_val = 3 \n");
    }
    printf(" Now try to insert 12  : \n");
    i4_ret = list_insert(&phead,12);
    if(i4_ret < 0)
    {
        printf("list insert fail : node_val = 12 \n");
    }
    printf(" Now try to insert 20  : \n");
    i4_ret = list_insert(&phead,20);
    if(i4_ret < 0)
    {
        printf("list insert fail : node_val = 20 \n");
    }
    print_link_list(phead);
    system("PAUSE");
    
    return 0;
}

#endif 


传参时,linkp被赋值为&phead,也就是说我们可以在函数里面修改phead (传递的是地址),
如果插入位置为第一个结点之前,那么寻找插入位置的循环将直接退出,此时pcur == *linkp,
于是pnew_node应该指向pcur,并且*linkp应该指向待插入结点;
如果插入位置为其他位置,那么通过循环查找,linkp将指向一个指向pcur所指向结点的下一个
结点的指针。找到插入位置时,pcur将指向待插入结点的下一个结点,而前一个结点里面的
link成员将由linkp所指向。

于是,pnew_node->link = pcur; 而前面一个结点的link指针有linkp所指向,于是,
表达式pnew_node->link = pcur; 和 *linkp = pnew_node; 能兼顾情况 A和 C 了。

p->link实际所指向的是下一个结点,那么pcur = pcur->link这个语句,就可以通过使用
pcur = *linkp 来消除,因为后者已经是pcur->link所指向的结点了。

不得不提出的是,*linkp与linkp的使用,不得有误。因为如果linkp还指向第一个结点,而
对*linkp进行赋值的话,就会修改这个结点了,请确保你的赋值是正确的。

本例中linkp是指向待插入结点的link指针,或者第一个结点的指针。


如果不能很好理解这种思路,还是按照自己最熟练,最不容易出错的方式实现吧!!

C语言之数据结构的顺序单链表创建,插入和删除操作

数据结构上机课时敲的。。之前用C++实现过简单的三元组,,但没有用C语言实现。所以试了试,课本上的参数传递都是用的引用的形式,而如果要用C语言实现的话就都需要改为指针传递的形式。 下面有一个重点就是删...
  • sxtopc
  • sxtopc
  • 2016年09月18日 22:47
  • 282

C语言单链表插入基础

1实现目标:输入数据如0 2 4 8,插入数据n,如果比第一个大,插入到第一个前面,否则继续找下一个,直到找到比n小的,查到他的前面 2此程序,把大于大于第一个数作为特殊处理 #inclu...

C语言单链表创建,插入,删除

#include #include typedef struct Node { int data; //数据域 Node *next; //指针域,指向下一个Node节点 }Node; N...

c语言实现单链表的操作:创建,删除,插入,反转, 排序等

最近学了数据结构的单链表基本操作:创建,删除,插入,反转,排序等.         如有不当或错误之处,欢迎指正,不胜感激!   #include #include #include i...
  • wahack
  • wahack
  • 2011年10月29日 14:45
  • 736

单链表的插入(完整版程序c语言实现,以字符串为数据)

这里的插入主要是针对有序表中插入一个数据,插入后仍然为一个有序表。接下来会给出在链表尾插入,和在链表投插入怎么做#include #include #include #include #define ...

c语言:单链表的实现(一) 创建,插入,删除,查找

#include #include #include #define NULL 0 #define LEN sizeof(struct Student) using namespace std; ty...

单链表的初始化、插入、删除——C语言

单链表的初始化、插入、删除 #include #include typedef int ElemType; //定义结点类型 typedef struct Node { Elem...

单链表插入和删除结点c语言的实现

个人学习的一些笔记,如果有误,希望指正

C语言之单链表操作之插入

2、插入(后插) 假设在一个单链表中存在2个连续结点p、q(其中p为q的直接前驱),若我们需要在p、q之间插入一个新结点s,那么我们必须先为s分配空间并赋值,然后使p的链域存储s的地址,s的链域存储q...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:(原创)C语言单链表插入
举报原因:
原因补充:

(最多只允许输入30个字)