线性单链表


/*******线性表*********
 * 线性表是最基本、最简单、也是最常用的一种数据结构。
 * 线性表(linear list)是数据结构的一种,
 * 一个线性表是n个具有相同特性的数据元素的有限序列
 * 线性表以下四个特征:
 * 1.集合中必存在唯一的一个“第一元素”。
 * 2.集合中必存在唯一的一个 “最后元素” 。
 * 3.除最后一个元素之外,均有唯一的后继(后件)。
 * 4.除第一个元素之外,均有唯一的前驱(前件)。
 * ************************/

/*******线性链表(单链表)*********

 * 描述:结点 =数据域 + 指针域
        用一组地址任意的存储单元存放线性表中的数据元素,
        逻辑上相邻的元素在物理上不要求也相邻,不能随机存取
 * 优点:动态数据结构、易于插入和删除、内存利用率高       
 * 缺点:遍历困难,不易于查询,反向遍历困难
 * 适用:适用于需要频繁进行增加/删除元素,而查找元素较少的程序。

 * ************************/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "phoneNote.h"


#define MAX_SIZE 20
typedef PhoneNote elemType;
/// @brief 线性链表
typedef struct listNode{
    /// @brief 数据
    elemType data; 
    /// @brief 后继
    struct listNode *next;
    
}listNode,*linkList;

#define m_data "linkList.data"
#define BUFF_SZIE 100
#define CAPTION "linkList"


#define m_print(list) showlinkList(list,phoneNote_printw)
#define m_load(list) loadlinkList(list,m_data,phoneNote_creat)
#define m_save(list) savelinkList(list,m_data)
#define m_search(list,key,value,del) searchlinList(list,key,value,phoneNote_search,del)
#define m_insert(list,item,pos) insertlinkList(list,item,pos)
#define m_delete(list,pos) deletelinkList(list,pos)
#define m_clear(list) clearlinkList(list)
#define m_destroy(list) destroylinkList(list)
#define m_lenght(list) getLenghtlinkList(list)
#define m_modify(list,pos) modifylinkList(list,pos,phoneNote_modify)
#define m_merge(la,lb) mergelinkList(la,lb)
#define m_sort(list,key,desc) sortlinkList(list,key,phoneNote_cmp,desc)
#define m_resver(list) resverlinkList(list)
#define m_inputelem() phoneNote_scanf()



linkList createlinkList() {return (linkList)calloc(1,sizeof(listNode));}
  
int getLenghtlinkList(linkList list){
   int i=0;
   if(list==NULL) return i;
   while(list->next) {i++;list=list->next;}
   return i;
}
int insertlinkList(linkList list, elemType *item, int pos)
{
   int j=0;
   linkList cursor=list;
   linkList newList=NULL;
   if(!cursor || !item)return -1;  
   while(cursor && j<pos)
   {cursor=cursor->next,j++;}
   if(!cursor || j>pos) return -2;
   if(!(newList=createlinkList()))return -3;
   memcpy(&(newList->data),item,sizeof(elemType));   
   newList->next=cursor->next;
   cursor->next=newList;
   return 0;

}
int deletelinkList(linkList list, int pos)
{
   int j=0;
   linkList cursor=list;  
   linkList tmp=NULL;
   while(cursor->next && j<pos){cursor=cursor->next;j++;}
   if(!cursor || j>pos)return -1;
   tmp=cursor->next;
   if(cursor->next->next)
   {cursor->next=cursor->next->next;}
   else{cursor->next=NULL;}   
   free(tmp);
   return 0;
}
int modifylinkList(linkList list, int pos, int (*elemModify)(elemType *p))
{  int j=0;
   linkList cursor=list;
   linkList newList=NULL;
   while(cursor->next && j<pos+1)
   {cursor=cursor->next;j++;}
   if(!cursor || j>pos+1)return -1;
   return elemModify(&(cursor->data));   
}
linkList searchlinList(linkList list, const char *key, const char *value, elemType *(*elemSearch)(elemType *p, const char *key, const char *value), int del)
{  
   int j=0;
   linkList rel=createlinkList();    
   linkList cursor=list;    
   while(cursor && cursor->next)
   {
      cursor=cursor->next; 
      if(elemSearch(&(cursor->data),key,value))
      {
         insertlinkList(rel,&(cursor->data),getLenghtlinkList(rel));
         if(del==1){deletelinkList(list,j);cursor=list;j=0;continue;}
         }
      j++;
   }
    return rel;
}


int showlinkList(linkList list, void (*_print)(elemType *p))
{  linkList cursor=list;
     if(cursor==NULL || _print==NULL) return -1;
    printf("\n--------- Show  list ------------------\n");
    while(cursor) 
    {_print(&(cursor->data));cursor=cursor->next;}
    printf("----------- Total: %d  --------------------\n\n",getLenghtlinkList(list));
    return 0;
}

int clearlinkList(linkList list)
{
   linkList cursor=list;
   linkList tmp=NULL;
   while(cursor && cursor->next)
   {
      tmp=cursor->next;
      cursor=cursor->next->next ;
      free(tmp);}
   list->next=NULL;
   return 0;
}
int destroylinkList(linkList *list)
{
   clearlinkList((*list));
   free(*list);
   *list=NULL;
   return 0;
}
int loadlinkList(linkList list, const char *file, elemType *(*_creatItem)())
{    

     FILE* fp = fopen(file, "r");
     elemType* item=NULL;   
        if(list==NULL) 
    {   printf("sequence list  is null\n");
        return -1;}  
     if(fp==NULL){
        printf("Failed to open file\n");
        return -2;
     }     
     item=_creatItem();
     if(item==NULL){
        printf("Failed to Create empty elemType\n");
        return -3;}
      clearlinkList(list);
     while(fread(item,sizeof(elemType),1,fp))
     {
       if(insertlinkList(list,item,getLenghtlinkList(list)))break;
     }    
     fclose(fp);
}
int savelinkList(linkList list, const char *file)
{
     linkList cursor=list->next;
     FILE* fp = fopen(file, "w");   
     if(cursor==NULL) {printf("sequence list  is null\n");return -1;}  
     if(fp==NULL){ printf("Failed to open file\n"); return -2; }   
     while(cursor)
     {
      fwrite(&(cursor->data),sizeof(elemType),1,fp);
      cursor=cursor->next;
     }    
     fclose(fp);
}
linkList mergelinkList(linkList la,linkList lb)
{    
   linkList cursor=NULL;   
   linkList rel=createlinkList(); 
   linkList array[]={la,lb};
   for (size_t i = 0; i < 2; i++)
   {
     cursor=array[i]; 
     while(cursor && cursor->next)    
   {  cursor=cursor->next;  
      insertlinkList(rel,&(cursor->data),getLenghtlinkList(rel));   
   }
   }
    return rel;
}
int sortlinkList(linkList list, const char* key, int (*elemCmp)(elemType *p1,elemType* p2, const char* key),int desc)
{   
    /*** 插入排序
 * 1.从第一个元素开始,该元素可以认为已经被排序;
 * 2.取出下一个元素,在已经排序的元素序列中从后向前扫描;
 * 3.如果该元素(已排序)大于新元素,将该元素移到下一位置;
 * 4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
 * 5.将新元素插入到该位置后;
 * 6.重复步骤2~5。
 * 算法的时间复杂度为O(n^2)
 * ***/
   if(!list && !list->next &&!list->next->next) return 0;  
     linkList s=list->next;
     linkList q=s->next;
     linkList p=NULL;
     list->next->next=NULL;
     while(q)
     {
      s=q;
      q=q->next;
      p=list;
      switch (desc)
      {
      case 0:
         while(p->next && elemCmp(&(p->next->data),&(s->data),key)<=0){p=p->next;}
         break;
      case 1:
         while(p->next && elemCmp(&(p->next->data),&(s->data),key)>0){p=p->next;}
         break;
      default:
         while(p->next && elemCmp(&(p->next->data),&(s->data),key)<=0){p=p->next;}
         break;
      }     
      // while(p->next && elemCmp(&(p->next->data),&(s->data),key)<=0){p=p->next;}
      // while(p->next && elemCmp(&(p->next->data),&(s->data),key)>0){p=p->next;}
       s->next=p->next;p->next=s;
       }
     
     return 0;
}
int resverlinkList(linkList list)
{
   if(!list && !list->next &&!list->next->next) return 0;  
    linkList s=0,q=0;
    s=list->next;
    q=s->next;    
    list->next->next=NULL;
    while(q)
    {
      s=q;q=q->next;
      s->next=list->next;list->next=s;
      
    }
 return 0;    
}
void printContinue()
{
    char a;
    printf("press any key to continue......   ");
     /*************************
     * scanf()中的%c 不能正常输入的问题
     * 在*%c前面加一个空格,将存于缓冲区中的回车符读入
     * char a;
     * scanf("%c%c",&a,&a); 
     *************************/
    scanf("%c%c",&a,&a);
}
int  printMenu()
{          
        int select = 1;       
        printf("\n******\t%s\t******************\n",CAPTION);
        printf("* [1] insert_pos   [2] delete_pos   *\n");
        printf("* [3] show_list    [4] search       *\n"); 
        printf("* [5] sort         [6] resver       *\n");
        printf("* [7] clear        [8] merge        *\n");
        printf("* [9] reduce       [10] delete_val  *\n");
        printf("* [11] load        [12] save        *\n");
        printf("* [13] modify                       *\n");        
        printf("* [0] quit                          *\n");
        printf("************************************\n");
        printf("\e[1;32mplease Enter :>\e[0m");                  
        scanf("%d", &select);
        return select;
}
int  executeCommand(int _cmd)
   {  
      linkList list=createlinkList(); 
      linkList newlist=NULL;    
      int pos=0,rel=0;    
      elemType *item =NULL;
   
     

     while (1)
    {
      char cmd[100]={0};
      char key[100]={0}; 
      char value[100]={0};
       switch (printMenu())
     { 
      
      case 0:
            printf("\e[1;31m %s goodbye!\n\e[0m",CAPTION);
            m_destroy(&list);return 0 ;/*exit(0)*/;
         break;
      case 1://insert_pos
            pos=m_lenght(list);
            printf("Please enter the insertion position [%d]  ",pos); 
            scanf("%c",cmd); scanf("%[^\n]",cmd); 
            if(cmd[0]>=0x30 && cmd[0]<=0x39 )  {pos=atoi(cmd);}   
            if((item=m_inputelem())==NULL)
            { printf("insert failed,Element is empty\n");break; }        
            if(m_insert(list,item,pos)==0) {m_print(list);}             
         break;
      case 2://del_pos
            pos=m_lenght(list)-1;
            printf("Please enter the insertion position [%d]  ",pos); 
            scanf("%c",cmd); scanf("%[^\n]",cmd); 
            if(cmd[0]>=0x30 && cmd[0]<=0x39 )  {pos=atoi(cmd);}                  
            if(!m_delete(list,pos)) {m_print(list);}             
         break;
      case 3: //show_list             
            m_print(list); 
         break; 
      case 4: //search
            printf("Please enter the search key    ");scanf("%s",key); 
            printf("Please enter the search value    ");scanf("%s",value);
            m_print(m_search(list,key,value,0));           
         break;
      case 5:  //sort
            printf("Please enter the sort key  [name]  ");scanf("%c",key); scanf("%[^\n]",key);
            if(key[0]<0x30)   strncpy(key,"name",strlen("name")); 
            printf("Please enter the sort key  < 0 :abs ,1: desc > [0]  ");scanf("%c",cmd); scanf("%[^\n]",cmd);
            pos=0;if(cmd[0]>0x30)  {pos=atoi(cmd);}   
            m_sort(list,key,pos);
            m_print(list);
         break;
      case 6: //resver
             m_resver(list);
             m_print(list);
         break;
      case 7:  //clear
            m_clear(list);
            m_print(list);                                
         break;
      case 8:  //merge            
            m_print(m_merge(list,list));            
         break;
      case 9: //reduce        
            printf("\033[32m Dynamic space Do not reduce \033[0m\n");                       
         break;
      case 10:  //delete_val
            printf("Please enter the delete key    ");scanf("%s",key); 
            printf("Please enter the delete value    ");scanf("%s",value);            
            m_print(m_search(list,key,value,1));          
            m_print(list); 
         break;
      case 11:    //load 
            m_load(list);
            printf("\e[1;31m load successful \n\e[0m");
            m_print(list);
         break;
      case 12:    //save
            m_save(list);
            printf("\e[1;31m save successful \n\e[0m");
         break;
      case 13:  //modify
            pos=m_lenght(list)-1;            
            printf("Please enter the insertion position [%d]  ",pos);
            scanf("%c",cmd); scanf("%[^\n]",cmd); 
            if(cmd[0]>=0x30 && cmd[0]<=0x39 )  {pos=atoi(cmd);} 
            m_modify(list,pos);
            m_print(list);
         break;
      
      default: //please re-enter
         printf("\033[32m Wrong selection, please re-enter \033[0m\n");
        break;
     }
     printContinue();
    }
    return 0;
}



//int linkListTest(int argc, char const **argv)
int (int argc, char const **argv)
{
     return executeCommand(0);    

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值