链表的各种操作

//基本上都是照着视频打的。。。

//链表的各种操作方法
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

struct Node 
{
  int nid;
  char msg[20];
  struct Node *next;
};

/*
 * 操作1:初始化链表
 *  参数pHead为链表的头文件,该方法用于将头指针指向NULL, 代表该链表为一个空的链表,
 *  从而实现链表的初始化操作
*/
void initLinkList(struct Node **pHead)
{
  *pHead = NULL;
  printf("操作:>链表初始化成功!\n");
}

/*
 *操作2:创建链表结构
 *参数pHead为链表的头指针,将该参数进行输入操作后返回即实现了链表的操作
 *
  */
 struct Node * createLinkList(struct Node *pHead)
 {
 
  struct  Node *p1, *p2;
  int size = 0;
  char c;  //操作符号  
  printf("提示:>开始创建链表结构...");
  do{
 size = size + 1; //将size的值+1
 p1 = (struct Node *)malloc(sizeof(struct Node));//p1申请内存空间
 printf("编号:>");
 scanf("%d", &p1->nid);
 printf("内容 :>");
 scanf("%s", p1->msg);
 //判断该节点是否为链表中的第一个节点
 if(size == 1)  pHead = p1;
 else p2->next = p1;
 p2 = p1; //重要:让p2指针指向p1新创建的节点上
 printf("继续(y/n)? :> ");
 getchar();
 scanf("%c", &c);
     }while(c == 'y' || c == 'Y');
  p2->next = NULL; //将最后一个节点的*next指向NULL
  printf("操作:>链表创建完毕!\n");
  return pHead; //将头指针返回  
}
/*
 *操作3:判断链表是否为空
 * 参数pHead判断是否指向NULL
 */
 
 int isEmptyLinkList(struct Node *pHead)
 {
   return pHead == NULL ? 1:0; 
 }
 /*
  *操作4:输出链表结构 
  *参数pHead,使用while循环格式化输出链表结构
  */
void printLinkList(struct Node *pHead)
{
    struct Node *p;
    if(!isEmptyLinkList(pHead)){
       p = pHead; //将p指针指向pHead,避免直接操作原始pHead
       printf("## 链表输出:");
       do {
          printf("[%s]", p->msg);
          if (p->next != NULL){
           printf(" ->");
          }
          p = p->next;  
       }while(p != NULL);
       printf("\n"); 
     }else{
      printf("提示:>该链表为空!\n");
     }
}
/*
 *操作5:统计节点的个数
 * 参数pHead,通过循环便利节点累加统计节点的个数
 */
 int getLinkListNodeCount(struct Node *pHead)
 {
  struct Node *pTmp;
  pTmp = pHead;
  int count = 1;
  while (pTmp->next != NULL){
      count += 1;
      pTmp = pTmp->next;
  }
  return count;
}

/*
 *操作6:链表的检索
 *参数 pHead, position
 *pHead为链表指针, position为检索的链表节点编号
 */
 struct Node *  seekLinkList(struct Node *pHead, int position)
 {
   struct Node *pTmp;
   int i, nodeCount = getLinkListNodeCount(pHead);
   if(position > nodeCount || position <= 0){
     printf("错误:>您所指定的节点编号不存在! \n");
  } else {
     pTmp = pHead;
     for (i=0; i<position-1;i++){
      pTmp = pTmp->next;
     }
     return pTmp;
  }
 }
/*
 *操作7:输出指定的链表中的节点数据
 *参数结构体指针,输出指针所指向的数据
 */
 void printNodeData(struct Node *p)
 {
  printf("节点信息: ");
  printf("[%d, %s]\n", p->nid, p->msg);
 }
 /*
  * 操作8:删除链表指定位置的节点
  * 参数position, 获取删除节点的位置,通过seekLinkList方法获取该位置的指针,通过position-1/
  *   position+1 获取删除节点前置和后置节点指针,便于后续操作
  */
int deleteNodeByPosition(struct Node **p, struct Node *pHead, int position)
{
   struct Node *pDelete, *pPrev, *pNext;
   int nodeCount = getLinkListNodeCount(pHead);
   if (position > nodeCount || position <= 0){
      printf("错误:>您输入的节点位置不存在 !\n");
      return 0;   
   }else{
      pDelete = seekLinkList(pHead, position); //获取待删除的节点指针
      if(pDelete == pHead){ //判断该节点是否为第一个节点
         printf("操作:>正在删除第一个节点...\n");
         pNext = seekLinkList(pHead, (position+1));
         *p = pNext;
       }else if(pDelete->next == NULL){ //判断该节点是否为最后一个节点
         printf("操作:>正在删除最后一个节点.....\n");
         pPrev = seekLinkList(pHead, (position-1)); 
         pPrev->next = NULL;    
       }else{
         printf("操作:> 正在删除链表中的节点.....\n");
         pPrev = seekLinkList(pHead, (position-1));
         pNext = seekLinkList(pHead, (position+1));
         pPrev->next = pNext;  //前置节点的*next指针指向后置节点   
      }
      pDelete = NULL;  //当前删除的指针置空
      return 1;
       }
}  
/*
 *操作9:实现对链表节点的添加操作
 *参数:**p, *pHead, position, flag
 * 首先判断插入位置是否正确,其次获取插入位置的节点指针, 获取*pPrev, *pNext
 */
 int insertLinkListNode(struct Node **p, struct Node *pHead, int position, int flag)
 {
    struct Node *pThis, *pPrev, *pNext, *pInsert;
    int nodeCount = getLinkListNodeCount(pHead);
    if(position > nodeCount ||position <= 0){
      printf("错误:插入节点的位置数据不存在");
      return 0;
    }else{
       //首先开辟一个节点的内存空间
       pInsert = (struct Node *)malloc(sizeof (struct Node));
       //为该节点赋值
       printf("请输入新的节点信息:\n");
       printf("编号:>");
       scanf("%d", &pInsert->nid);
       printf("内容:>");
       scanf("%s", pInsert->msg);
       pThis = seekLinkList(pHead, position);
       if(pThis == pHead){
          if(!flag){
            printf("操作:>向第一个节点[前]插入新的节点数据.....\n");
            *p = pInsert;  //将头指针指向新添加的节点
            pInsert->next = pThis;  // 将新添加的节点*next1指向原先的第一个节点         
          }else{
             printf("操作:>向第一个节点[后]插入新的节点数据.....\n");
             pNext = seekLinkList(pHead, (position + 1));
             pThis -> next = pInsert;//
             pInsert->next = pNext;         
               }
          }else if(pThis->next == NULL){//链表中的最后一个节点后追加一个节点
             if(!flag){
              printf("操作:>向最后一个节点[前]插入新的节点数据....\n");
              pPrev = seekLinkList(pHead,(position - 1));
              pPrev->next = pInsert;
              pInsert->next = pThis;
             }else{
             printf("操作:>向第最后一个节点[后]插入新的数据......\n");
             pThis->next = pInsert;
             pInsert->next = NULL;            
             }
          }else{//链表中的中间节点
             if(!flag){
               printf("操作:>向中间节点[前]插入新的节点数据....\n");
               pPrev = seekLinkList(pHead, (position - 1));
      pPrev->next = pInsert;
      pInsert->next = pThis;
             }else{
              printf("操作:>向中间节点[后]插入新的节点数据......\n");
              pNext = seekLinkList(pHead, (position + 1));
              pThis->next = pInsert;
              pInsert->next = pNext;
             }          
          }
       
       return 1;
    } 
 }
 
int main(void)
{
  struct Node *pHead, *pTmp;
  int choise,position,flag,dist;
  char selected;
  do{
  system("clear");
  printf("\n\n===================================\n");
  printf("\t工程实践:链表的操作\n");
  printf("----------------------------------------\n");
  printf("     功能菜单:\n");
  printf("\t(1) 初始化链表\n");
  printf("\t(2) 创建链表结构\n");
  printf("\t(3) 输出链表结构\n");
  printf("\t(4) 通过位置检索链表节点\n");
  printf("\t(5) 删除链表节点\n");
  printf("\t(6) 插入链表节点\n");
  printf("\t(7) 退出 \n");
  printf("\n========================================\n");
  printf("请选择功能:");
  scanf("%d", &choise);
  
  switch (choise){
   case 1:
    initLinkList(&pHead); break;//初始化链表结构   
   case 2:
    pHead = createLinkList(pHead); break;//创建链表结构
   case 3:
    printLinkList(pHead);  break;//输出链表结构
   case 4:
    printf("请输入需要检索的节点位置(1-%d): >", getLinkListNodeCount(pHead));
    scanf("%d", &position);
    pTmp = seekLinkList(pHead, position); //检索链表节点
    if(pTmp != NULL){
      printNodeData(pTmp);//输出节点信息
    }
   break;
   case 5:
   printf("请输入需要删除的节点位置(1-%d):>",getLinkListNodeCount(pHead));
   scanf("%d", &position);
   if(deleteNodeByPosition(&pHead, pHead, position)){
     printf("操作:> 第%dg个节点删除成功!\n",position);
     printLinkList(pHead);  break;//输出链表结构
   }else{
     printf("操作:>第%d个节点删除失败!\n",position);
   }
   break;
   case 6:
     printf("请输入插入节点的位置(1-%d):>", getLinkListNodeCount(pHead));
     scanf("%d", &position);
     printf("确定插入位置[0. 前置插入  1.后置插入]:>");
     scanf("%d", &flag);
      if(insertLinkListNode(&pHead, pHead, position, flag)){
       printf("操作:> 节点插入成功!\n");
       printLinkList(pHead);  break;//输出链表结构
      }else{
        printf("操作:> 节点插入失败!\n");
      }
   break;
   case 7:
   exit(0);break;
   default:break;
  }
  
  printf("\n继续操作?(y/n):> ");
  getchar();
  scanf("%c", &selected);
  }while(selected == 'y' || selected == 'Y');
  return 0;
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值