数据结构与算法之线性表

372 阅读5分钟

循环链表和单项链表的差异

单向链表的最后一个结点指针域是空的,而循环链表 最后一个指针域不为空,重新再一次指向头结点的位置

单向链表为何要增加头节点

  • 便于首元结点处理
  • 便于空表和非空表的统一处理

循环链表的创建

  • 第一次创建
  • 已经创建,新增数据

          判断第一个创建:YES : ->新结点next->自身,NO->链表结尾的位置,尾结点next->新结点,新的结点next=头结点(首元结点)

  方法1:

/* 循环链表的创建方式有两种情况 1.判断是否第一次创建链表:
  YES->创建一个新结点,并使得新结点的next 指向自身; (*lt)->next = (*lt);   
  NO-> 找链表尾结点,将尾结点的next = 新结点. 新结点的next = (*lt); */
FunctionType CreateList (CharlesLinkList *lt){   
    int item;   
    CharlesLinkList temp = NULL; 
    CharlesLinkList target = NULL;   
    printf("请输入结点的值,输入0结束\n");    
    while (1) {     
   scanf("%d",&item);     
   if (item == 0) break;      
   if (*lt == NULL) {       
       *lt = (CharlesLinkList)malloc(sizeof(Node));//创建结点       
       if (*lt == NULL) return ERROR;//如果为空,则不往下执行         
       (*lt)->data = item;//赋值操作(输入的数字赋值给新创建的结点item)    
       (*lt)->next = *lt;//新结点==本身 
       }else{        
        //1:遍历,找最后一个结点            
        /*如果target->next != *lt,target = target->next*/            
        for (target = *lt; target->next != *lt; target = target->next);       
        //2.创建一个新结点           
        temp = (CharlesLinkList)malloc(sizeof(Node));    
        if (temp) return ERROR;      
       //3.往data里面存储刚刚输入的数据     
       temp->data = item;           
       temp->next = *lt;//让temp->next指向首元节点        
       target->next = temp;        }    }

    return SUCCESS;
}

方法2:

//后插法创建
FunctionType CreateList2 (CharlesLinkList *lt){  
  int item;    
  CharlesLinkList temp = NULL;   
  CharlesLinkList target = NULL;  
  CharlesLinkList r = NULL;   
  printf("请输入结点的值,输入0结束\n");   
  while (1) {        
      scanf("%d",&item);    
      if (item == 0) break;    
 
      if (*lt == NULL) {           
      *lt = (CharlesLinkList)malloc(sizeof(Node));//创建结点       
      if (*lt == NULL) return ERROR;//如果为空,则不往下执行          
      (*lt)->data = item;//赋值操作(输入的数字赋值给新创建的结点item)       
      (*lt)->next = *lt;//新结点==本身         
       r = *lt;      
      }else{   
     
    //2.创建一个新结点   
        temp = (CharlesLinkList)malloc(sizeof(Node));          
       if (temp) return ERROR;         
    //3.往data里面存储刚刚输入的数据    
        temp->data = item;         
        temp->next = *lt;//让temp->next指向首元节点       
        r->next = temp;      
        r = temp;      
      }   
    }   
 return SUCCESS;
}

打印方法:

void show(CharlesLinkList p){
    //如果链表是空  
      if(p == NULL){  
      printf("打印的链表为空!\n");    
      return;  
   }else{       
      CharlesLinkList temp;     
      temp = p;       
      do{        
          printf("%5d",temp->data);     
          temp = temp->next;      
     }while (temp != p);       
      printf("\n");   
   }
}

循环链表插入数据

实现逻辑顺序

如果插入的位置为place==1时,则属于插入首元结点,所以需要特殊处理

  •  创建新结点temp,并判断是否创建成功,成功则赋值,否则返回ERROR;
  •  找到链表最后的结点_尾结点,
  • 让新结点的next 执行头结点.
  •  尾结点的next 指向新的头结点;
  • 让头指针指向temp(临时的新结点)

插入的位置为place != 1时(其他位置)

  • 创建新结点temp,并判断是否创建成功,成功则赋值,否则返回ERROR;
  • 先找到插入的位置,如果超过链表长度,则自动插入队尾;
  • 通过target找到要插入位置的前一个结点, 让target->next = temp;
  •  插入结点的前驱指向新结点,新结点的next 指向target原来的next位置 ;

Status ListInsert(CharlesLinkList *L, int place, int num){  
      CharlesCharlesLinkList temp ,target;   
      int i;   
      if (place == 1) {     
      temp = (CharlesLinkList)malloc(sizeof(Node)); 
       if (temp == NULL) {           
           return ERROR;     
        }       
        temp->data = num;       
        for (target = *L; target->next != *L; target = target->next);       
        temp->next = *L;       
        target->next = temp;  
       *L = temp;    
       }else  {        
           temp = (CharlesCharlesLinkList)malloc(sizeof(Node));     
         if (temp == NULL) {         
             return ERROR;
        }
        temp->data = num;
        
        for ( i = 1,target = *L; target->next != *L && i != place - 1; target = target->next,i++) ;        temp->next = target->next;
        target->next = temp;
    }
    
    return OK;
}


循环链表删除元素

Status  CharlesLinkListDelete(CharlesLinkList *L,int place){ 
      CharlesLinkList temp,target;    
      int i;  
      //temp 指向链表首元结点
      temp = *L;   
      if(temp == NULL) return ERROR;  
      if (place == 1) {      
         //1.如果删除到只剩下首元结点了,则直接将*L置空;        
         if((*L)->next == (*L)){          
            (*L) = NULL;         
            return OK;       
          }       
         //2.链表还有很多数据,但是删除的是首结点;  
         //2.1 找到尾结点, 使得尾结点next 指向头结点的下一个结点 target->next = (*L)->next;       
         //2.2 新结点做为头结点,则释放原来的头结点        
         for (target = *L; target->next != *L; target = target->next);  
         temp = *L;
        *L = (*L)->next;      
        target->next = *L;      
        free(temp);   
      }else{       
           //如果删除其他结点--其他结点        
           //1. 找到删除结点前一个结点target        
           //2. 使得target->next 指向下一个结点        
           //3. 释放需要删除的结点temp     
           for(i=1,target = *L;target->next != *L && i != place -1;target = target->next,i++) ;     
              temp = target->next;     
              target->next = temp->next;         
              free(temp);   
         }    
    return OK;
}

循环链表查询值

int selectValue(CharlesLinkList L,int value){   
    int i = 1;    CharlesLinkList p; 
    p = L;    //寻找链表中的结点 data == value   
    while (p->data != value && p->next != L) {    
        i++;    
        p = p->next;   
     }    

    //当尾结点指向头结点就会直接跳出循环,所以要额外增加一次判断尾结点的data == value;   
     if (p->next == L && p->data != value) {   
     return  -1;   
     }   
    return i;
}

main 函数执行

int main(int argc, const char * argv[]) {  
    CharlesLinkList head;   
    int place,num;    
    int iStatus;     

    //iStatus = CreateList(&head);  
    iStatus = CreateList2(&head);   
    printf("原始的链表:\n");   
    show(head);//    
    printf("输入要插入的位置和数据用空格隔开:");
    //    scanf("%d %d",&place,&num);
    //    iStatus = ListInsert(&head,place,num);
    //    show(head);    
    
    printf("输入要删除的位置:"); 
    scanf("%d",&place);  
    CharlesLinkListDelete(&head,place);  
    show(head);   
    printf("输入你想查找的值:");  
    scanf("%d",&num);    
    place=findValue(head,num);  
    if(place!=-1)     
       printf("找到的值的位置是place = %d\n",place);   
    else       
       printf("没找到值\n");  
    return 0;
}

打印结果: