链表之单向有头不循环链表

链表是一种链式存储线性表,用一组地址任意的存储单元存放数据表的数据元素,称为存储单元的一个节点
节点的结构体定义为:

typedef struct ListNode
{
     struct ListNode* pNext;
     TypeDate data;
}ListNode;

下面就是一些构造链表的一些 函数,包括删除,插入,销毁等:

创建一个节点

ListNode* BuyNode(TypeDate x)
{
     ListNode* Node = (ListNode*)malloc(sizeof(ListNode));
     Node->pNext = NULL;
     Node->data = x;
     assert(Node);
     return Node;
}

头插:就是从头节点处 插入一个节点:

void SListPushfront(ListNode** ppHead, TypeDate x)//头插
{
     ListNode* NewNode=NULL;
     NewNode = BuyNode(x);
     if (*ppHead == NULL)
     {
          *ppHead = NewNode;
          NewNode->pNext = NULL;
     }
     else
     {
          NewNode->pNext=*ppHead;
          *ppHead=NewNode;
     }
}

尾插 :
对于单向有头不循环链表而言:需要找到链表中的最后一个节点,再将需要插入的节点插入:

void SListPushback(ListNode** ppHead, TypeDate x)//尾插
{
     ListNode* NewNode = NULL;
     ListNode* cur = NULL;
     NewNode = BuyNode(x);
     if (*ppHead == NULL)
     {
          *ppHead = NewNode;
          NewNode->pNext = NULL;
     }
     else
     {
          cur = *ppHead;
          while (cur)
          {
              if (cur->pNext == NULL)
              {
                   cur->pNext = NewNode;
                   NewNode->pNext = NULL;
              }
              cur = cur->pNext;
          }
     }
}

头删:
将第一个节点删除,定义一个节点保存头节点,再将头节点的下一个节点赋为头节点,最后释放头节点。

void SListPopfront(ListNode** ppHead)//头删
{
     ListNode* Node=NULL;
     if (*ppHead == NULL)
     {
          return;
     }
     else
     {
          Node = *ppHead;
          *ppHead=(*ppHead)->pNext;
          free(Node);
     }
}

尾删:
找到倒数第二个节点,将倒数第二个节点的下一个指向NULL

void SListPopback(ListNode** ppHead)//尾删
{
     ListNode* cur = NULL;
     if (*ppHead == NULL)
     {
          return;
     }
     else
     {
          cur = *ppHead;
          while (cur)
          {
              if ((cur->pNext)->pNext == NULL)
              {
                   cur->pNext = NULL;
                   free(cur->pNext);
              }
              cur = cur->pNext;
          }
     }
}

删除任意一个节点:

void SListErase(ListNode** ppHead, ListNode* PposNode)//在任意位置删除
{
     ListNode* PNode = NULL;
     PNode = *ppHead;
     if (*ppHead == NULL)
     {
          return 0;
     }
     else
     {
          while (PNode->pNext != PposNode)//找到需要删除的位置的前一个
          {
              PNode = PNode->pNext;
          }
          PNode->pNext = PposNode->pNext;
          free(PposNode);
     }
}

在任意位置插入一个节点:

void SListInsert(ListNode** ppHead, ListNode* PposNode, TypeDate x)//在任意位置插入
{
     ListNode* PNode = NULL;
     ListNode* NewNode = NULL;
     PNode = *ppHead;
     NewNode = BuyNode(x);
     if (*ppHead == NULL)
     {
          *ppHead = NewNode;
     }
     if (*ppHead == PposNode)
     {
          SListPushfront(ppHead, x);
     }
     else
     {
          while (PNode->pNext != PposNode)
          {
              PNode = PNode->pNext;
          }
          NewNode->pNext = PposNode;
          PNode->pNext = NewNode;
     }
}

按值删除(删除遇到的第一个 ):
如果链表为空,则返回空,若不是空链表,则遍历整个链表 ,比较节点的值是否与所需要删除的节点的值是一样的,如果是一样的就删除这个节点,然后退出。如果没有与其匹配的,就返回空。

void SListRemove(ListNode** ppHead, TypeDate x)//按值删除,删除遇到的第一个
{
     ListNode* PNode = NULL;
     ListNode* cur = NULL;
     PNode = *ppHead;
     if (*ppHead == NULL)
     {
          return;
     }
     else
     {
          while ((PNode->pNext)->data != x)
          {
              PNode = PNode->pNext;
          }
          cur = PNode->pNext;
          PNode->pNext = cur->pNext;
          free(cur);
     }
}

按值删除(删除链表中为这个值得所有节点):
思想:遍历整个链表,当找到数据相同的节点,删除这个节点后,并不退出,要将当前节点赋给下一个节点,仔计算查找。
核心:要将当前节点用一个临时节点代替,否则,找到了需要删除了的节点后,会将这个节点释放那么再使用这个节点将会产生错误。

void SListRemoveAll(ListNode** ppHead, TypeDate x)//按值删除,删除所有的
{
     ListNode* PNode = NULL;
     ListNode* cur = NULL;
     PNode = *ppHead;
     if (*ppHead == NULL)
     {
          return;
     }
     else
     {
          while (PNode->pNext)
          {
              if ((PNode->pNext)->data == x)
              {
                   cur = PNode->pNext;
                   PNode->pNext = cur->pNext;
                   free(cur);
              }
              else
              {
                   PNode = PNode->pNext;
              }
          }
     }
}

销毁链表:
思想:遍历整个链表,将链表的,从头节点开始释放,直至链表为空。

void SListDestory(ListNode** ppHead)
{
     ListNode* PNode = NULL;
     ListNode* Pnext = NULL;
     for (PNode = *ppHead; PNode != NULL; PNode = Pnext)
     {
          Pnext = PNode->pNext;
          free(PNode);
     }
      ppHead=NULL;
}

测试代码:

void test()
{
     ListNode* S=NULL;//初始化链表
     printf("前插后:\n");
     SListPushfront(&S, 2);
     SListPushfront(&S, 4);
     SListPushfront(&S, 6);
     SListPushfront(&S, 6);
     SListPushfront(&S, 6);
     SListPushfront(&S, 8);
     SListPushfront(&S, 2);
     SListPushback(&S, 12);
     SListPrint(S);
     printf("后插后:\n");
     SListPushback(&S, 10);
     SListPushback(&S, 11);
     SListPushback(&S, 12);
     SListPushback(&S, 14);
     SListPushback(&S, 14);
     SListPushback(&S, 16);
     SListPrint(S);
     printf("前删和后删:\n");
     SListPopfront(&S);
     SListPopfront(&S);
     SListPopback(&S);
     SListPopback(&S);
     SListPrint(S);
     printf("插入到指定位置:\n");
     SListInsert(&S, &S->pNext->pNext, 17);
     SListInsert(&S, &S->pNext, 0);
     SListPrint(S);
     printf("删除指定位置:\n");
     SListErase(&S, &S->pNext->pNext);
     SListPrint(S);
     printf("按值删除,只删遇到的第一个:\n");
     SListRemove(&S, 12);
     SListPrint(S);
     printf("按值删除,只删所有:\n");
     SListRemoveAll(&S, 6);
     SListPrint(S);
     /*printf("销毁链表!");
     SListDestory(&S);
     SListPrint(S);*/
}

程序的结果是:

猜你喜欢

转载自blog.csdn.net/ffsiwei/article/details/80568468
今日推荐