头指针和头结点

头指针:指向链表第一个结点的指针,若链表有头结点,则指向投结点;头指针有标识作用,所以常使用头指针冠以链表的名字;无论链表是否为空,头指针肯定存在,这是必要因素。

头结点:放在第一个结点之前,数据域无特殊意义;对第一个结点的前插入和删除就与其他结点统一了;头结点不是必要因素。

结构:

  1. typedef struct Node{ 
  2.     ElemType data; 
  3.     struct Node *next; 
  4. }Node; 
  5. typedef struct Node * LinkList 

单链表的读取:

  1. bool getElem(LinkList L,int i,ElemType *e){ 
  2.      LinkList p;//p指向头结点后第一个节点  
  3.      int j=1;//j负责计数,从1开始  
  4.       
  5.      p = L->next; 
  6.      while(p && j<i){//p不为空,且计数器没到要找的位置,就继续  
  7.          p = p->next; 
  8.      } 
  9.      if(!p || j>i){//如果i的值过小,则会出现j>i的情况;如果i的值过大,会出现p为空的情况  
  10.          return false;//i的取值范围是[1,L.length]  
  11.      } 
  12.      else
  13.          *e = p->data; 
  14.          return true
  15.      } 

单链表的插入:

 

  1. bool listInsert(LinkList *L,int i,ElemType e){//此处L是指向(指向向头结点的指针)的指针  
  2.     LinkList p,s;//p指向要插入的前一个位置的结点处  
  3.     int j=1;//j依然从1开始计数  
  4.      
  5.     p = (*L);//所以p要从头结点处开始  
  6.     while(p && j<i){ 
  7.         p = p->next; 
  8.         ++j; 
  9.     } 
  10.     if(!p || j>i){//i的取值范围是[1,L.length]  
  11.         return false
  12.     } 
  13.     else
  14.         s = (LinkList)malloc(sizeof(Node)); 
  15.         s->data = e; 
  16.         s->next = p->next;//赋值顺序不能出错  
  17.         p->next = s; 
  18.         return true
  19.     } 

单链表的删除:

 

  1. bool listDelete(LinkList *L,int i,ElemType *e){ 
  2.      LinkList p,q;//p标识要删除元素的前一个元素,q标识要删除的元素  
  3.      int j=1; 
  4.       
  5.      p = (*L); 
  6.      while(p->next && j<i){//我们确保的不只是p而是p后面的元素一定要存在!  
  7.          p = p->next; 
  8.      } 
  9.      if(!(p->next) || j>i){ 
  10.          return false
  11.      } 
  12.      else
  13.          q = p->next; 
  14.          *e = q->data; 
  15.          p->next = q->next; 
  16.          free(q);//释放过程  
  17.          return true
  18.      } 
  19. }  

单链表的创建:

 

  1. void createListHead(LinkList *L,int n){//头插法  
  2.     int j; 
  3.     LinkList p;//p指向新建的指针  
  4.      
  5.     srand(time(0)); 
  6.     (*L) = (LinkList)malloc(sizeof(Node));//建立一个头结点  
  7.     (*L)->next = NULL; 
  8.     for(j=0;j<n;j++){ 
  9.         p = (LinkList)malloc(sizeof(data)); 
  10.         p->data = rand()%100+1; 
  11.         p->next = (*L)->next; 
  12.         (*L)->next = p; 
  13.     } 

 

  1. void createListTail(LinkList *L,int n){ 
  2.     int j; 
  3.     LinkList p,r; 
  4.      
  5.     srand(time(0)); 
  6.     (*L) = (LinkList)malloc(sizeof(Node));//建立一个头结点  
  7.     (*L)->next = NULL; 
  8.     r=(*L); 
  9.     for(j=0;j<n;j++){ 
  10.         p = (LinkList)malloc(sizeof(data)); 
  11.         p->data = rand()%100+1; 
  12.         r->next = p; 
  13.         r = p; 
  14.     } 
  15.     r->next = NULL://循环结束之前将尾结点的指针域置空  

单链表的清空:

  1. void clearList(LinkList *L){ 
  2.     LinkList p,q; 
  3.     p = (*L)->next; 
  4.       
  5.     while(p){ 
  6.         
  7.         q = p->next;//q用来标记位置,必不可少  
  8.         free(p); 
  9.         p=q; 
  10.     } 
  11.     (*L)->next = NULL;//最后将头指针置空  

优缺点对比