手把手写数据结构之“单向链表操作”

/******************************************************************************头文件数据封装及函数声明部分*******************************************************************************/

#ifndef  _S_LIST_H
#define  _S_LIST_H

#include <stdio.h>
#include <stdlib.h>

#define PRINT  printf("LINE: %d\n", __LINE__);

/*单链表的实现可以各有不同,只要该实现,符合链表的定义即可。
 *单链表最重要的数据结构是元素结点,
 *最重要的操作是插入结点,删除结点和遍历。
 *其它的操作基本上是这3个操作的组合,依据具体的要求而定。
*/

/*******************************************
*单向链表结点信息
*
*数据域: 可以是普通类型,也可以是封装类型
*指针域: next指针
*
*********************************************/
typedef struct node
{
 int num;   //数据域
 struct node *next; //指针域
}NODE;

/*******************************************
*单向链表信息
*
*链表的属性信息: 链表的作用描述,链表当前节点个数等等
*指针信息:  一般必须有表头指针,也可以有为结点指针
*
*********************************************/
typedef struct list_info
{
 int max;   //结点个数
 NODE *head;   //头结点指针
}LIST_INFO;

/********************************************
*Des:  创建链表
*Ret:  成功返回0, 失败返回-1; 
*********************************************/
int Create_List(LIST_INFO **plist);

/********************************************
*Des:  判断链表是否为空
*Ret:  真: 1,  假: 0 
*********************************************/
int Is_Empty_List(const LIST_INFO *plist);

/********************************************
*Des:  添加新的数据节点到表头
*Ret:  成功返回0, 失败返回-1; 
*********************************************/
int AddtoList_Head(LIST_INFO *plist, const int num);

/********************************************
*Des:  添加新的数据结点到表尾
*Ret:  成功返回0, 失败返回-1; 
*********************************************/
int AddtoList_Tail(LIST_INFO *plist, const int num);


/********************************************
*Des: 查找某个结点是否存在,存在返回前一个结点
*Ret: NULL:不存在或出错,(NODE *)1:该节点为头结点 
*********************************************/
NODE * Find_Node(const LIST_INFO *plist, const int num);


/********************************************
*Des:   获取第m结点的数据
*Ret: 成功返回0,失败返回-1
*********************************************/
int Get_Node_Info(const LIST_INFO *plist, int *num, const int M);
 


/********************************************
*Des: 将新的数据num插入到数据域为dest_num结点前面
*Ret: 成功返回0,返回-1; 
*********************************************/
int Insert_num_to_Node(LIST_INFO *plist, const int num, const int dest_num);


/********************************************
*将新的数据结点添加到第m个结点后
*成功返回0,返回-1; 
*********************************************/
int Add_num_to_M(LIST_INFO *plist, const int m, const int num);


/********************************************
*Des: 删除第一个数据与为num的结点
*Ret: 成功返回0,返回-1; 
*********************************************/
int Delete_num_from(LIST_INFO *plist, const int num);


/********************************************
*Des: 遍历链表
*Ret: 成功返回0,返回-1; 
*********************************************/
int Traverse_List(const LIST_INFO *plist);

/********************************************
*Des: 将链表所有节点排序(按数据从小到大)
*Ret: 成功返回0,返回-1; 
*********************************************/
int Order_List(LIST_INFO *plist);

/********************************************
*Des: 清空链表
*Ret: 成功返回0,返回-1; 
*********************************************/
int Empty_List(LIST_INFO *plist);


/********************************************
*Des: 将链表逆序
*Ret: 成功返回0,返回-1; 
*********************************************/
int Reverse_List(LIST_INFO *plist);


/********************************************
*Des: 获取链表结点个数
*Ret: 成功返回结点个数,失败返回-1; 
*********************************************/
int Get_count_Node(const LIST_INFO *plist);

/********************************************
*Des: 销毁链表
*Ret: 成功返回0,失败返回-1; 
*********************************************/
int Destory_List(LIST_INFO **plist);


/********************************************
*Des: 顺序表结点插入 (已经按从小到大排好序的链表)
*Ret: 成功返回0,失败返回-1; 
*********************************************/
int Order_Insert__Node(LIST_INFO * plist, const int num);


#endif

 

 

 

/********************************************************************************函数接口定义实现部分******************************************************************************************/ 

 

 

#include "s_list.h"

/********************************************
*Des:  创建结点并填充结点信息
*Ret:  成功返回结点, 失败返回NULL; 
*********************************************/
static NODE *__Create_Node__(int num)
{
 NODE *new_node = (NODE *)malloc(sizeof(NODE));
 if(NULL == new_node)
 {
  perror("Malloc new node");
  return NULL;
 }

 new_node->num = num;
 new_node->next = NULL;

 return new_node;
}

/********************************************
*Des:  创建链表
*Ret:  成功返回0, 失败返回-1; 
*********************************************/
int Create_List(LIST_INFO **plist)
{
 if(NULL == plist)
  return -1;
 *plist = (LIST_INFO *)malloc(sizeof(LIST_INFO));
 if(NULL == *plist)
 {
  perror("List malloc");
  return -1;
 }

 (*plist)->head = NULL;
 (*plist)->max = 0;

 return 0;
}

/********************************************
*Des:  判断链表是否为空
*Ret:  真: 1,  假: 0 
*********************************************/
int Is_Empty_List(const LIST_INFO *plist)
{
 return (NULL == plist->head) ? 1: 0;
}

/********************************************
*Des:  添加新的数据节点到表头
*Ret:  成功返回0, 失败返回-1; 
*********************************************/
int AddtoList_Head(LIST_INFO *plist, const int num)
{
 NODE *new_node = __Create_Node__(num);
 if(NULL == new_node)
  return -1;

 new_node->next = plist->head;
 plist->head = new_node;

 plist->max++;

 return 0;
}

/********************************************
*Des:  添加新的数据结点到表尾
*Ret:  成功返回0, 失败返回-1; 
*********************************************/
int AddtoList_Tail(LIST_INFO *plist, const int num)
{
 NODE *pnode = plist->head, *tmpnode = NULL;
 NODE *new_node = __Create_Node__(num);
 if(NULL == new_node)
  return -1;

 //链表为空
 if(Is_Empty_List(plist))
 {
  plist->head = new_node;
 }
 else
 {
  while(NULL != pnode->next)
  {
   pnode = pnode->next;
  }
  pnode->next = new_node;
 }

 plist->max++;

 return 0;
}


/********************************************
*Des: 查找某个结点是否存在,存在返回前一个结点
*Ret: NULL:不存在或出错,(NODE *)1:该节点为头结点 
*********************************************/
NODE * Find_Node(const LIST_INFO *plist, const int num)
{
 NODE *pre_node = (NODE *)1;
 NODE *tmpnode = NULL, *pnode = plist->head;
 while(NULL != pnode)
 {
  if(pnode->num == num)
   return pre_node;
  
  pre_node = pnode;
  pnode = pnode->next;
 }

 return NULL;
}


/********************************************
*Des:   获取第m结点的数据
*Ret: 成功返回0,失败返回-1
*********************************************/
int Get_Node_Info(const LIST_INFO *plist, int *num, const int M)
{
 int idx = 0;
 if(M > Get_count_Node(plist) || M <= 0)
 {
  printf("Invalid arg!\n");
  return -1;
 }

 NODE *pnode = plist->head;
 while(NULL != pnode)
 {
  idx++;
  if(idx == M)
   break;
  
  pnode = pnode->next;
 }
 *num = pnode->num;
 
 return 0;
}
 
/********************************************
*将新的数据结点添加到第m个结点后
*成功返回0,返回-1; 
*********************************************/
int Add_num_to_M(LIST_INFO *plist, const int m, const int num)
{
 int idx = 0;
 if(m > Get_count_Node(plist) || m <= 0)
 {
  printf("Invalid arg!\n");
  return -1;
 }
 
 NODE *new_node = __Create_Node__(num);
 if(NULL == new_node)
 {
  return -1;
 }
 NODE *pnode = plist->head;
 
 while(NULL != pnode)
 {
  idx++;
  if(idx == m)
   break; 
  pnode = pnode->next;
 }

 new_node->next = pnode->next;
 pnode->next = new_node;
 plist->max++;
 
 return 0;
}

/********************************************
*Des: 将新的数据num插入到数据域为dest_num结点前面
*Ret: 成功返回0,返回-1; 
*********************************************/
int Insert_num_to_Node(LIST_INFO *plist, const int num, const int dest_num)
{
 //查找dest_num结点
 NODE *pre_node = Find_Node(plist, dest_num);
 if(NULL == pre_node)
 {
  printf("No such node!\n");
  return -1;
 }

 //创建结点
 NODE *new_node = __Create_Node__(num);
 if(NULL == new_node)
 {
  return -1;
 }
 //若插入到表头
 if(pre_node == (NODE *)1)
 {
  new_node->next = plist->head;
  plist->head = new_node;
 }
 else//插入到其他位置
 {
  new_node->next = pre_node->next;
  pre_node->next = new_node;
 }

 plist->max++;
 return 0;
  
}


/********************************************
*Des: 删除第一个数据与为num的结点
*Ret: 成功返回0,返回-1; 
*********************************************/
int Delete_num_from(LIST_INFO *plist, const int num)
{
 NODE *fnode = NULL;
 NODE *prev_node = Find_Node(plist, num);
 if(NULL == prev_node)
 {
  printf("Have no such Node!\n");
  return -1;
 }

 if((NODE *)1 == prev_node)
 {
  fnode = plist->head;
  plist->head = fnode->next;
 }
 else
 {
  fnode = prev_node->next;
  prev_node->next = fnode->next;
 }

 free(fnode);
 plist->max--;

 return 0;
}


/********************************************
*Des: 遍历链表
*Ret: 成功返回0,返回-1; 
*********************************************/
int Traverse_List(const LIST_INFO *plist)
{
 //函数入口检测
 if(NULL == plist)
 {
  printf("Invalid arg!\n");
  return -1;
 }
 
 NODE *pnode = plist->head;
 if(Is_Empty_List(plist))
 {
  printf("The List is empty!\n");
  return -1;
 }

 printf("The List node count: %d\n", Get_count_Node(plist));

 while(NULL != pnode)
 {
  printf("%-5d", pnode->num);
  pnode = pnode->next;
 }

 printf("\n\n");
 return 0;
}

/********************************************
*Des: 将链表所有节点排序(按数据从小到大)
*Ret: 成功返回0,返回-1; (没有想出更好方法)
*********************************************/
int Order_List(LIST_INFO *plist)
{
 NODE *pnode = plist->head->next, *head = plist->head;
 head->next = NULL;
 NODE *tmpnode = NULL, *pre_p = NULL, *tmp = NULL;
 
 while(pnode != NULL)
 {
  tmp = pnode->next;
  
  tmpnode = head;
  if(pnode->num <= head->num)
  {
   pnode->next = head;
   head = pnode;
  }
  else
  {
   pre_p = head;
   tmpnode = head->next;
   while(tmpnode != NULL)
   {
    if(pnode->num <= tmpnode->num)
    {
     break;
    }
    pre_p = tmpnode;
    tmpnode = tmpnode->next;
   }
   pre_p->next = pnode;
   pnode->next = tmpnode;
  }

  pnode = tmp; 
 }

 plist->head = head;

 return 0;
}


/********************************************
*Des: 清空链表
*Ret: 成功返回0,返回-1; 
*********************************************/
int Empty_List(LIST_INFO *plist)
{
 if(NULL == plist)
 {
  printf("Invalid arg!\n");
  return -1;
 }

 NODE *fnode = NULL, *pnode = plist->head;
 while(NULL != pnode)
 {
  fnode = pnode;
  pnode = pnode->next;
  free(fnode);
 }

 plist->head = NULL;
 plist->max = 0;

 return 0;
}


/********************************************
*Des: 将链表逆序
*Ret: 成功返回0,返回-1; 
*********************************************/
int Reverse_List(LIST_INFO *plist)
{
 if(NULL == plist)//函数入口检测
 {
  printf("Invalid arg!\n");
  return -1;
 }
 
 NODE *head = NULL, *tmpnode = NULL, *pnode = plist->head;
 while(NULL != pnode)
 {
  tmpnode = pnode;
  pnode = pnode->next;

  tmpnode->next = head;
  head = tmpnode;
 }

 plist->head = head;

 return 0;
}

/********************************************
*Des: 顺序表结点插入 (已经按从小到大排好序的链表)
*Ret: 成功返回0,失败返回-1; 
*********************************************/
int Order_Insert__Node(LIST_INFO * plist, const int num)
{
 if(NULL == plist)//函数入口检测
 {
  printf("Invalid arg!\n");
  return -1;
 }

 NODE *pnode = NULL, *tmpnode = NULL;
 NODE *new_node = __Create_Node__(num);//创建新的结点
 if(NULL == new_node)
  return -1;

 pnode = plist->head;

 //链表为空
 if(plist->head == NULL)
 {
  plist->head = new_node;
 }

 //第一个结点就大于num
 else if(plist->head->num > num)
 {
  new_node->next = plist->head;
  plist->head = new_node;
 }
 else
 {
  tmpnode = plist->head;
  pnode = plist->head->next;
  
  while(NULL != pnode)
  {
   if(pnode->num > num)
    break;
   tmpnode = pnode;
   pnode = pnode->next;
  }
  new_node->next = tmpnode->next;
  tmpnode->next = new_node;
 }

 plist->max++;

 return 0;
}


/********************************************
*Des: 获取链表结点个数
*Ret: 成功返回结点个数,失败返回-1; 
*********************************************/
int Get_count_Node(const LIST_INFO *plist)
{
 return plist->max;
}

/********************************************
*Des: 销毁链表
*Ret: 成功返回0,失败返回-1; 
*********************************************/
int Destory_List(LIST_INFO **plist)
{
 if(Empty_List(*plist) < 0)
  return -1;

 free(*plist);
 *plist = NULL;

 return 0;
}

 

 

/*****************************************************************************测试代码********************************************************************************************************/

 

#include <time.h>
#include "s_list.h"

#define  RANDOM  (rand() % 10 + 1)

int main()
{
 srand(time(NULL));
 int i, num;

 LIST_INFO *plist = NULL;

 Create_List(&plist);

 for(i = 0; i < 5; i++)
 {
  num = RANDOM;
  printf("%5d", num);
  
  Order_Insert__Node(plist, num);
 }
 printf("\n\n");

 Traverse_List(plist);

 for(i = 0; i < 5; i++)
 {
  num = RANDOM;
  printf("%5d", num);
  
  AddtoList_Head(plist, num);
 }
 printf("\n\n");

 Traverse_List(plist);

 return 0;
}

 /************************************************************************************测试结果***************************************************************************************************/

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值