有头单链表

/*链式结构其实是结构体变量与结构体变量通过指针建立联系进而连接在一起。
而结构体分为:数据域(用来存储数据,而且这个数据可以是任何类型,甚至是结构体类型),指针域(用来做连接的)
链表就是内存不连续的,且数据存在不同类型的数组。只是它不能通过下标的方式访问,只能通过指针去访问
有头链表:表头不存放数据去操作
例:*/

```c
#include  <stdio.h>
#include  <stdlib.h>   //标准头文件
struct    Node
{
     int   data;
     struct   Node* next;   //我通常用next指针表示下一个结构体变量的地址是多少
}
struct   Node* createList()  
/*createList要用指针,是因为它返回的是头的这个指针,且链表都是以指针的方式返回的,因为我们是从堆内存中申请一块内存的,我们要返回的是一个指针*/
{
      struct   Node* headNode = (struct  Node*)malloc(sizeof(stuct  Node));
      /*有人会问为什么是头指针headNode分配这块内存。这是因为:【malloc其作用是在内存的动态存储区分配一个长度为sizeof()的连续空间,且此函数的返回值是分配区域的首地址,也可以说,此函数是一个指针类型的函数,返回的指针指向该分配域的开头位置。如果分配成功,则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将此内存释放(malloc的含义来源于百度。在这里引用只为大家能更好理解单链表)】这里malloc分配了一块节点类型的内存,分配了这块内存之后返回这块内存的首地址存储到headNode里面*/

       /*表头是一个结构体变量,我们要对其进行初始化,且表头不存放数据,所以数据data我们不做处理,指针要对其进行处理*/
      headNode->next = NULL;
      return  headNode;      /*这里返回headNode是为了主函数接收headNode这个值,否者写其他的话,headNode不被接收*/
}

//以上就是创建表头的过程,也叫创建链表的过程。


//创建结点,为插入做准备
struct  Node*createNode(int  data)          /*节点也是个结构体变量,只是比表头多了个数据域,所以我们要传入一个数据域*/
{
      struct   Node* newNode = (struct   Node*)malloc(sizeof(struct   Node));
      newNode->data = data;
      newNode ->next = NULL;
      return  newNode;      /*其实节点和表头一样的,只是有头单链表表头不存放数据*/
}


/*第一种插入方式:表头法插入*/
void   insertByHead(struct  Node* headNode, int   data) 
 /*告诉别人插入的是以headNode这个表头为头节点,插入的数据为data的链表*/
{
       //插入之前首先创建插入的结点
     struct  Node*   newNode = createNode(data); /*用指针调用这个结点*/
     newNode ->next  = headNode->next;
     headNode->next = newNode;    //这里已完成插入
}
 /*因为我们要做的是一个有表头的链表,所以我们不可能把结点插到headNodew前面去的,只能插到headNode头结点的下一个*/


/*表尾插入,我们只需知道当这个下一个结点是空NULL的时候,即为表尾*/
/*从第一个结点插入,然后往后面找*/
void  insertByTail(struct   Node*   headNode, int   data)
/*要插入的结点,要插入的数据*/
{
        struct    Node* newNode = createNode(data);   
        /*创建插入的结点,调用一下createNode函数*/
        struct   Node* tailNode = headNode;
        while (tailNode->next !=NULL)
        {
                   tailNode = tailNode ->next;
         }
         tailNode ->next = newNode;
}      

//指定位置插入
//struct   Node*  headNode   插入这个结点
//int    data     插入这个数据
//int   posData      指定位置
void   insertByAppoin(struct   headNode, int  data ,  int   posData)
{
       struct   Node* pMove = headNode;
       struct  Node*posNode = headNode->next;
       //移动节点不为NULL,且当前节点元素不等于查找元素
       while(posNode != NULL&&posNode ->data ! =posData)
       {
                  posFrontNode = posNode;
                  posNode = posFrontNode->next;
          }
          //分析posNode的状态
          if(posNode == NULL)
          {
                   printf("未找到指定位置,无法插入!\n");
                   return;
           }
           else
           {
                           struct  Node* newNode = createNode(data);
                           posFrontNode ->next = newNode;
                           newNode -> next = posNode;
               }
}

//表头删除,删除第二个结点
void   deleteNodeByHead(struct  Node*  headNode)
{
         struct  Node*nextNode = headNode ->next;
         if(nextNode == NULL)
         {
                      printf("链表为NULL,无法删除!");
                      return ;
          }
         headNode ->next = nextNode ->next;
         free(nextNode);
         nextNode = NULL;
}

//表尾删除
void   deleteNodeByTail(struct  Node* headNode)
{
            struct  Node* tailNode= headNode ->next;  //尾结点
            struct   Node* tailFrontNode = headNode;  //尾结点上一个结点
            if(tailNode ==NULL)
            {
                      printf("链表为NULL,无法删除!")
                      return;
             }
            while(tailNode->next != NULL)
            {
                            tailFrontNode = tailNode;
                            tailNode = tailFrontNode ->next;
              }
              tailFrontNode ->next = NULL;
              free(tailNode);
              tailNode = NULL;
}


//指定位置删除
void   deleteByAppoin(struct   Node* headNode, int  posData)
{
           struct  Node*posFrontNode = headNode;
           struct  Node*posNode = headNode->next;
           //移动结点不为NULL,并且当前结点中元素不等于查找的元素
           while(posNode != NULL&&posNode ->data != posData)
           {
                             posFrontNode = posNode;
                             posNode = posFrontNode - next;
              }
              //分析posNode状态
              if(posNode == NULL)
              {
                          printf("未找到指定位置,无法删除!\n");
               }
               else
               {
                             posFrontNode ->next = posNode ->next;
                             free(posNode);
                             posNode  =NULL;
                   }
}


**删除数据一定要判断是否为空**

//进行打印 
void   printList(struct   Node* headNode)
{
      //有头链表,从第二个开始打印
      struct   Node* pMove  =  headNode->next;
      while(pMove)
      {
                printf("%d-->",pMove ->data);
                pMove = pMove -> next;
       }
       printf("\n");
}


//需要用的时候,用主函数接收
int   main()
{
      struct   Node*list = createList();   //链表创建
      insertByHead(list, 1);
      insertByHead(list, 2);
      insertByHead(list, 3);
      printList(list);
      /*这里的结果是321,因为这里是表头法插入,按顺序先把  1 插到表头的下一个结点,然后再把  2  插进去,最后再把  3   插进去,也就是说,1  2  3按顺序地插进第二个结点,所以输出的结果是反的,为3 2 1*/
         /* 在这里也可以写为:
       for(int   i = 1; i<=3 ; i++)
       {
                  insertByHead(list, i);
        }
        printList(list);                    */

         insertByTail(list, -1);
        printList(list);
        //输出结果为3->2->1-> -1
    
         inserByAppoin(list , -100, -1);
         printList(list);

         deleteNodeByHead(list);
         printList(list);

        deleteNodeByTail(list);
        printList(list);

      deleteByAppoin(list, 1)
      printLiist(list)

     system("pause");    //防止闪屏
     return  0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值