1. 程式人生 > >Linux C 單向連結串列2

Linux C 單向連結串列2

#include <stdio.h>  
#include <stdlib.h>  
   
/*節點型別結構體*/   
typedef struct node_t {  
    void* data;  //節點的資料域  
    struct node_t *next;  //節點的後繼指標域  
}linknode_t, *linklist_t;  
      
linklist_t CreateEmptyLinklist(); //利用頭結點來建立一個空連結串列(頭結點)      
void DestroyLinklist(linklist_t list); //刪除連結串列函式
void ClearLinklist(linklist_t list); //刪除連結串列裡面節點函式      
int EmptyLinklist(linklist_t list);//判斷連結串列是否為空連結串列函式      
int LengthLinklist(linklist_t list);//獲取連結串列長度函式       
int GetLinklist(linklist_t list, int at, void **data);//連結串列的某個節點獲取函式      
int SetLinklist(linklist_t list, int at, void *data);//連結串列的某個節點設定函式         
int InsertLinklist(linklist_t list, int at,void *data); //連結串列的某個節點插入函式       
int DeleteLinklist(linklist_t list, int at);//刪除連結串列某個節點函式        

linklist_t ReverseLinklist(linklist_t list); //連結串列反轉函式


*
  * 入口引數:
  *                無
  *  返回值:
  *                linknode_t結構體;
  *   函式描述:
  *                利用頭結點來建立一個空連結串列(頭結點);
  *  注意事項:
  *               無;
  */
linklist_t CreateEmptyLinklist()  
{   
   linklist_t list;  
   list = (linklist_t)malloc(sizeof(linknode_t)); //結構指標分配空間;

   if (NULL != list) {  
      list->next = NULL; //下一個Node節點為空;
    }  
   return list;  
}  
/*
  * 入口引數:
  *                linklist_t結構指標;
  *  返回值:
  *                無;
  *   函式描述:
  *                刪除連結串列函式;
  *  注意事項:
  *               無;
  */
void DestroyLinklist(linklist_t list)  
{  
  if (NULL != list) {  
     ClearLinklist(list);  
     free(list);  
  }  
}  
/*
  * 入口引數:
  *                linklist_t結構指標;
  *  返回值:
  *                無;
  *   函式描述:
  *                刪除連結串列裡面節點函式;
  *  注意事項:
  *                無;
  */
void ClearLinklist(linklist_t list)  
{  
  linknode_t *node; //指向Node節點的時候被移除  
  if (NULL == list) return;  

  while (NULL != list->next) {  
    node = list->next;  
    list->next = node->next;  
    free(node);  
   }  
   return;  
}  
/*
  * 入口引數:
  *                linklist_t結構指標;
  *  返回值:
  *                無;
  *   函式描述:
  *                獲取連結串列長度函式;
  *  注意事項:
  *                無;
  */
int LengthLinklist(linklist_t list)  
{  
  int len = 0;  
  linknode_t *node; //迭代節點  

  if (NULL == list) return -1;  

  node = list->next; // 迭代節點指第一個資料節點
  while (NULL != node) {  
    len++;  
    node = node->next;  
  }  
  return len;  
}  
/*
  * 入口引數:
  *                linklist_t結構指標;
  *  返回值:
  *                無;
  *   函式描述:
  *                判斷連結串列是否為空連結串列函式;
  *  注意事項:
  *                無;
  */
int EmptyLinklist(linklist_t list)  
{  
  if (NULL != list) {  
    if (NULL == list->next) { //判斷連結串列是否為空,為空返回1
        return 1;  
    } else {    //判斷連結串列是否為空,不為空返回1
        return 0;  
    }  
  } else {  
    return -1;  
  }  
}  
/*
  * 入口引數:
  *                list 結構指標;
  *                at 節點位置;
  *                data 獲取資料;
  *  返回值:
  *                無;
  *   函式描述:
  *                連結串列的某個節點獲取函式;  
  *  注意事項:
  *                無;
  */
int GetLinklist(linklist_t list, int at, void **data)  
{  
  linknode_t *node;   //迭代節點   
  int pos;        

  if (NULL == list) return -1;  
  if (at < 0) return -1;  

  node = list->next;  //第一個節點賦值迭代節點
  pos = 0;  
  while (NULL != node) {  
    if (at == pos) {  
        if (NULL != data) {  
            *data = node->data;  
        }  
        return 0;             
    }   
    node = node->next;  //指向下一個節點
    pos++;  
   }  
  return -1;  
}  
/*
  * 入口引數:
  *                list 結構指標;
  *                at  節點位置
  *                data 設定資料
  *  返回值:
  *                無;
  *   函式描述:
  *                連結串列的某個節點設定函式;  
  *  注意事項:
  *                無;
  */
int SetLinklist(linklist_t list, int at, void *data)  
{  
  linknode_t *node; //迭代節點     
  int pos;  
  int found = 0;  

  if (!list) return -1;    
  if (at < 0) return -1;

  node = list->next;  //初始化迭代節點
  pos = 0;  
  while (NULL != node) {  
    if (at == pos) {   
        found = 1; //插入節點的標誌
        node->data = data;  //把資料賦值給節點資料域
        break;            
    }   
    node = node->next;  //指向下一個節點
    pos++;  
  }  
  if (1 == found) {  //如果設定資料成功返回為0;
    return 0;  
   } else {  //如果設定資料失敗返回為-1;
    return -1;  
  }  
}  
/*
  * 入口引數:
  *                list 結構指標;
  *                at  節點位置
  *                data 設定資料
  *  返回值:
  *                無;
  *   函式描述:
  *                連結串列的某個節點插入函式;  
  *  注意事項:
  *                無;
  */
int InsertLinklist(linklist_t list, int at, void *data)  
{  
  linknode_t  *node_prev, *node_at, *node_new;  //初始化迭代節點
  int     pos_at;  
  int     found = 0;  

  if (NULL == list) return -1;  

  /* at must >= 0 */  
  if (at < 0) return -1;  

  node_new = malloc(sizeof(linknode_t));   //分配空間
  if (NULL == node_new) {  
     return -1;  
   }  
  node_new->data = data; /* assigned value */  
  node_new->next = NULL; //節點如果插入超過連結串列長度的位置,會接到尾節點後面,這樣,node_new成了尾節點,node_new->next = NULL

  node_prev = list;  //跟隨指標,幫助我們更好的定位  
  node_at = list->next; //遍歷指標   
  pos_at = 0;  
  while (NULL != node_at) {  
    if (pos_at == at) {  
        found = 1;  //找到正確的位置,跳出迴圈  
        break;            
    }    
    node_prev = node_at;  //跟隨指標先跳到遍歷指標的位置  
    node_at = node_at->next; //遍歷指標跳到下一個節點的位置
    pos_at++;  
  }  
 
  if (found) {  
    node_new->next = node_at;  //插入的節點next指向node_at
    node_prev->next = node_new; //插入節點的前一個節點   
   } else {  
    /*若是沒找到正確的位置,即所插入位置超越了連結串列的長度,則接到尾節點的後面,
    同樣,這樣適用於空連結串列,這樣我們可以建立一個空連結串列,利用這個函式,實現連結串列的初始化*/
    node_prev->next = node_new;  
   }  
   return 0;  
 }  
/*
  * 入口引數:
  *                list 結構指標;
  *                at  節點位置
  *  返回值:
  *                無;
  *   函式描述:
  *                刪除連結串列某個節點函式;  
  *  注意事項:
  *                無;
  */
int DeleteLinklist(linklist_t list, int at)  
{  
  linknode_t  *node_prev, *node_at;  
  int     pos_at;  
  int         found = 0;  

  if (!list) return -1;  
  /* at must >= 0 */  
  if (at < 0) return -1;  

  node_prev = list;  
  node_at = list->next;  
  pos_at = 0;   

  while (NULL != node_at) {  
    if (pos_at == at) {  
        found = 1;  //找到對應的位置,跳出迴圈
        break;            
    }    
    node_prev = node_at;   //跟隨指標,幫助我們更好的定位
    node_at = node_at->next;  //遍歷指標跳到下一個節點的位置
    pos_at++;  
  }  
  if (found) {  
    node_prev->next = node_at->next;  //移除對應的節點
    free(node_at);  
    return  0;  
  } else {  
    return -1;  
  }  
}  
/*
  * 入口引數:
  *                list 結構指標;
  *  返回值:
  *                無;
  *   函式描述:
  *                連結串列反轉函式;  
  *  注意事項:
  *                無;
  */
linklist_t ReverseLinklist(linklist_t list)  
{  
  linknode_t *node;   //迭代節點
  linknode_t *node_prev;  //迭代之前節點  
  linknode_t *node_next;  //迭代之後節點
            
  if (NULL == list) return NULL;  
  node_prev = NULL;  
  node = list->next;  
  while (NULL != node) {  
    node_next = node->next;  //迭代節點指向下一個節點
    /*當迭代節點指向最後一個節點,連結串列頭節點指向最後一個節點,
     連結串列最後一個節點成為頭節點*/  
    if (NULL == node_next) {  
        list->next = node;  
    }  
    /*反轉連結串列直接的節點,確保當前節點指向先前的節點不是下一個節點*/      
    node->next = node_prev;        
   
    /*反轉連結串列位置*/
    node_prev = node;  
    node = node_next;  
  }  
  return list;  


/**********************************測試程式******************************************/


typedef struct{
   char a[10];
   char b;
}data_t;
      

int main()  
{  
  int i;

  data_t *data;
 
  linklist_t p;

  data_t *c;
 
  p = CreateEmptyLinklist();

  for(i = 0;i < 5;i++)  
    {  
      c =(data_t *)malloc(sizeof(data_t));
      sprintf(c->a,"a%d",i);
      c->b=i;
      InsertLinklist(p,i,(void*)c);
    }

//ReverseLinklist(p);  
printf("The length of the list is:%d\n",LengthLinklist(p));  
 
 for(i = 0;i < 5;i++)  
    {
     GetLinklist(p,i,&data);
     printf("The NO of this list is:%s\n",data->a);
     printf("The NO of this list is:%d\n",data->b);
    }
 
return 0;
}