带头结点的单链表的初始化,建立,插入,查找,删除

//带头结点的单链表的初始化,建立,插入,查找,删除
    #include <stdio.h>
    #include <stdlib.h>

    typedef int ElemType;//定义数据域类型////////////////////////  
typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。


结构体中的 typedef struct Node 的意思就是,为自定义的数据类型定义一个新名字 Node。
//定义结点类型(由数据域,指针域组成)和链表LinkList/////////////////////
    typedef struct Node
    {
      ElemType data;     //单链表的数据域
      struct Node *next;  //单链表的指针域
     }Node,*LinkedList;           
关于结构体 struct Node *next; 这么一句代码,为什么要这么写?我写成 int *next 行不行?
不行的。next是指向下一个Node,所以其类型必须是Node。int *next 只能指向int,而不能指向Node。所以必须定义为 Node 类型,但是 Node 是结构体,所以前面还得加上个 struct。

//单链表的初始化/////////////////////////////////////////////////////
    LinkedList LinkedListInit()
    {
      Node *L;
      L=(Node *)malloc(sizeof(Node));  //申请结点空间
      if(L==NULL)                 //判断是否有足够的内存空间
       printf("申请内存空间失败");
       L->next=NULL;              //将next设置为NULL,初始长度为0的单链表.com
      }

//单链表的建立1,头插法建立单链表/////////////////////////////////////
     LinkedList LinkedListCreateH()
    {
     Node *L;
     L=(Node *)malloc(sizeof(Node));   //申请头结点空间
     L->next=NULL;       //初始化一个空链表
     ElemType x;    //x为链表数据域中的数据
     while(scanf("%d",&x)!=EOF)
     {
       Node *p;
       p=(Node *)malloc(sizeof(Node));  //申请新的结点
       p->data=x;      //结点数据域赋值
       p->next=L->next;    //将结点插入到表头
       L->next=p;
      }
     return L;
    }

//单链表的建立2,尾插法建立单链表/////////////////////////////////////
LinkedList LinkedListCreateT()
{
 Node *L;
 L=(Node *)malloc(sizeof(Node));    //申请头结点空间
 L->next=NULL;    //初始化一个空链表
 Node *r;
 r=L;                  //r始终指向终端结点,开始时候指向头结点
ElemType x;                       //x为链表数据域中的数据
 while(scanf("%d",&x)!=EOF)
 {
   Node *p;
   p=(Node *)malloc(sizeof(Node));       //申请新的结点
   p->data=x;
   r->next=p ;
   r=p;
 }
 return L;
}

//单链表的插入,在链表的第i个位置插入x的元素
     LinkedList LinkedListInsert(LinkedList L,int i,ElemType x)
     {
       Node *pre;      //pre为前驱结点
       pre=L;
       int temi=0;
       for(temi=1;temi<i;temi++)
        pre=pre->next ;     //查找第i个位置的前驱结点
      Node *p;
      p=(Node *)malloc(sizeof(Node));
      p->data=x;
      p->next=pre->next;   
      pre->next=p;
      }
      return L;
    }

//单链表的删除,在链表中删除值为x的元素
    LinkedList LinkedListDelete(LinkedList L,ElemType x)
    {
      Node *p ,*pre;         //pre为前驱结点,p为查找的结点;
      p=L->next;
      whiel(p-<data!=NULL)
     {
       pre=p;
      p=p->next;
    }
     pre->next=p->next;            //删除操作,将其前驱的next指向其后继
    free(p);
    return L;
    }

////////////////////////////////////////////////////////////
int main()  
{  
    LinkedList list,start;  
   printf("请输入单链表的数据:");   
    list = LinkedListCreatT();  
    for(start = list->next; start != NULL; start = start->next)  
        printf("%d ",start->data);  
    printf("/n");  
    int i;  
    ElemType x;  
    printf("请输入插入数据的位置:");  
    scanf("%d",&i);  
    printf("请输入插入数据的值:");  
    scanf("%d",&x);  
    LinkedListInsert(list,i,x);  
    for(start = list->next; start != NULL; start = start->next)  
        printf("%d ",start->data);  
    printf("/n");  
    printf("请输入要删除的元素的值:");  
    scanf("%d",&x);  
    LinkedListDelete(list,x);   
    for(start = list->next; start != NULL; start = start->next)  
        printf("%d ",start->data);  
    printf("/n");  
      
    return 0;  
}   
 

//题外话:
    //带头结点初始化


            Node *head;  //声明头结点
         void InitList(Node **head)
                {
               *head=(Node *)malloc( sizeof(Node));
               (*head)->next=NULL;
            }
    //不带头结点初始化

    方式一:
        void InitList(Node **head){
            *head=NULL;
        }

      调用InitList(&head);

    方式二:
        void InitList(Node *head){
            head=NULL;
        }

 //带头结点的单链表,初始时一定返回的是指向头结点的地址,所以一定要用二维指针,否则将导致内存访问失败或异常。

相关知识拓展:
 malloc()到底从哪里得到了内存空间?答案是从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。就是这样!
什么是堆:堆是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程 初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
堆一般由程序员分配释放,若不释放,程序结束时可能由OS回收。注意这里说是可能,并非一定。所以我想再强调一次,记得要释放。

posted on 2014-03-12 16:00  黑主优姬  阅读(4976)  评论(0编辑  收藏  举报

导航