zoukankan      html  css  js  c++  java
  • 单链表带头结点&不带头结点

    Node *head;  //声明头结点

    带头结点初始化

    void InitList(Node **head){

         *head=(Node *)malloc( sizeof(Node));
         (*head)->next=NULL;
    }

    带头结点尾插入,统一操作
    方式一:
    void CreatList(Node **head){
         Node *r=*head,*s;
         int a;
         while(scanf("%d",&a)){
              if(a!=0){
                   s=(Node *)malloc(sizeof(Node));
                   s->value=a;
                   r->next=s;
                   r=s;    
              }
              else{    
                   r->next=NULL;
                   break;    
              }
         }
    }
    调用CreatList(&head);

    方式二:
    void CreatList(Node *head){
         Node *r=head,*s;
         ... //下面的都一样
    }
    调用CreatList(head);

    ------------------------------------------------------------------------------------------------------

    不带头结点初始化
    方式一:
    void InitList(Node **head){
         *head=NULL;
    }
    调用InitList(&head);
     
    方式二:
    void InitList(Node *head){
         head=NULL;
    }
    调用InitList(head);
     
    不带头结点尾插入,第一个节点与其他节点分开操作
    void CreatList(Node  **head){
         Node *p,*t;         /*p工作指针,t临时指针*/
         int a,i=1;
         while(scanf("%d",&a)){
              if(a!=0){
                   t=(Node *)malloc(sizeof(Node));
                   t->value=a;
                   if(i==1){
                        *head=t;    
                   }
                   else{
                        p->next=t;
                   }
                   p=t;
              }
              else{    
                   p->next=NULL;
                   break;    
              }
              i++;
         }
    }
    调用CreatList(&head);

     
    一、两者区别:
         1、不带头结点的单链表对于第一个节点的操作与其他节点不一样,需要特殊处理,这增加了程序的复杂性和出现bug的机会,因此,通常
              在单链表的开始结点之前附设一个头结点。
         2、带头结点的单链表,初始时一定返回的是指向头结点的地址,所以一定要用二维指针,否则将导致内存访问失败或异常。
         3、带头结点与不带头结点初始化、插入、删除、输出操作都不样,在遍历输出链表数据时,带头结点的判断条件是while(head->next!=NULL),
              而不带头结点是while(head!=NULL),虽然头指针可以在初始时设定,但是如1所述,对于特殊情况如只有一个节点会出现问题。
             
     
    二、为什么不带头结点初始化有2种方式,而带头结点只有1种方式呢?
     
         因为不带头结点声明Node *head 时;C编译器将其自动初始化为NULL,于是根本不需要调用InitList(head);也即不带头结点的初始化
    是个伪操作。而带头结点的初始化在堆开辟了一段内存,需要修改head指针变量指向的地址(即head的值),所以要修改head的值,必须传保
    存head变量的地址(即二维指针)。而直接调用CreatList(head);相当于传head变量的值,函数修改的是head的副本,无法真正改变head的值。 
     
         :这里可以将head指针看成一个变量(不管它保存的是地址),就比较好理解了。
          
     
    三(key)、其实本质上还是传值,传址的问题,只不过指针本身保存的地址,让这个过程变得有点纠结。在函数调用需要修改指针变量的指向(value)时,
     应该传递指针变量的地址(address)。
          另外,对于函数的形参是指针时,只要该参数不在左边(即都是右值操作),二维指针(形参)就可以简化为一维指针。如上面带头结点的尾插
    简化版本。
  • 相关阅读:
    Linux_vi编辑器
    Linux_几个符号命令
    Linux_权限
    Linux_用户/用户组
    Linux_文件及文件夹[创建][复制][移动][删除][重命名]
    Linux_文件查看
    Linux_初识
    码农网站
    学习网站
    软件设计师考试范围
  • 原文地址:https://www.cnblogs.com/Seiyagoo/p/2426107.html
Copyright © 2011-2022 走看看