单链表的基本操作

关于单链表,我写了很久,查了很多资料,主要的原因还是以前的知识不是太牢固,所以写的时候错误很多,不过大都能调试出来。

或许是一个寒假没咋敲代码了,最普遍的一个错误:判断两个数是否相等的时候,正确的语句是:

int a=10;
int b=20;
if(a==b)//这里是双等号
{
语句
}

两个等号,我老是写成一个,这个以前纠正过,过了一个寒假,又犯错了。

还有就是涉及传参的问题,这个搞得最久,其中的大部分我都写成注释了:

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

#pragma warning (disable:4996)

#define DataType int

typedef struct ListNode {
    DataType data;
    struct Node *next;
}Node, *PNode;

// 初始化单链表---思考为什么要传递二级指针
void InitList(PNode* pHead);

// 在链表尾部插入值为data的新结点
void PushBack(PNode* pHead, DataType data);

// 删除链表的最后一个节点
void PopBack(PNode* pHead);

// 在链表头部插入置为data的新节点
void PushFront(PNode* pHead, DataType data);

// 删除链表的第一个结点
void PopFront(PNode* pHead);

// 查找链表中值为data的结点,存在返回该结点的地址,否则返回空
PNode Find(PNode pHead, DataType data);

//在链表pos位置后插入值为data的新节点
void Insert(PNode pos, DataType data);

// 删除单链表pos位置上的结点
void Erase(PNode* pHead, PNode pos);

// 移除链表中第一个值为data的结点
void Remove(PNode* pHead, DataType data);

// 移除链表中所有值为data的结点
void RemoveAll(PNode* pHead, DataType data);

// 获取链表中结点的总个数
size_t Size(PNode pHead);

// 获取链表中第一个结点
PNode Front(PNode pHead);

// 获取链表中最后一个节点
PNode Back(PNode pHead);

// 判断链表是否为空
int Empty(PNode pHead);

// 打印单链表
void PrintList(PNode pHead);

// 构建新节点
PNode BueNode(DataType data);

目前关于单链表的基本操作就这些内容,接下来还有各种各样的面试题,都是一些扩展,不过我还没写,那么先看这些函数的实现吧

#include"List.h"

//初始化
//因为在函数内部需要改变头指针的内容,而C语言传参是传值,所以需要用二级指针来修改头指针的值
void InitList(PNode *pHead)
{
    assert(pHead);
    *pHead = NULL;
}

// 构建新节点
PNode BuyNode(DataType data)
{
    PNode node = (PNode)malloc(sizeof(Node));//给新节点开辟空间
    if (node)//判断是否开辟成功
    {
        node->data = data;
        node->next = NULL;
    }
    return node;
}

// 在链表尾部插入值为data的新结点
void PushBack(PNode* pHead, DataType data)
{
    PNode NewNode = BuyNode(data);//创建一个新节点

    if (NULL == (*pHead))//如果链表为空,直接将新节点赋给头结点即可
    {
        (*pHead) = NewNode;
        return;
    }
    else//否则,遍历找到尾节点,再将新节点赋给尾结点后面
    {
        PNode pCur = (*pHead);
        while (pCur->next)
        {
            pCur = pCur->next;
        }
        pCur->next = NewNode;
    }
}

// 删除链表的最后一个节点
void PopBack(PNode* pHead)
{
    assert(pHead);
    if (NULL == *pHead)//如果链表为空,直接返回
    {
        return;
    }
    else if ( NULL==(*pHead)->next)//如果链表只有一个节点,即头结点,那么将头结点赋为NULL
    {
        *pHead = NULL;
    }
    else
    {
        PNode pCur = *pHead;
        PNode prev = pCur;
        while ( NULL!=pCur->next)//遍历找到尾结点
        {
            prev = pCur;
            pCur = pCur->next;
        }
        free(pCur);   //先释放掉最后一个结点的内容,再把倒数第二个赋为空。
        prev->next = NULL;
    }

}

// 在链表头部插入置为data的新节点
void PushFront(PNode* pHead, DataType data)
{
    assert(pHead);
    PNode NewNode = BuyNode(data);//创建一个新节点
    if ( NULL==*pHead)//如果链表为空,直接将新节点赋给头结点
    {
        *pHead = NewNode;
    }
    else
    {
        if (NewNode)
        {
            NewNode->next = *pHead;//先让新节点指向第一个结点
            *pHead = NewNode;//再将新节点赋给头结点
        }
    }
}

// 删除链表的第一个结点
void PopFront(PNode* pHead)
{
    assert(pHead);
    if (NULL == *pHead)
    {
        return;
    }
    else
    {
        PNode pdel = *pHead; //先保存头结点,将头结点指向下一个结点之后在进行释放。
        *pHead = (*pHead)->next;
        free(pdel);
    }
}

// 查找链表中值为data的结点,存在返回该结点的地址,否则返回空
PNode Find(PNode pHead, DataType data)
{
    assert(pHead);
    if (NULL == pHead)
    {
        return NULL;
    }
    PNode pCur = pHead;
    while (pCur)//遍历单链表,查找
    {
        if (pCur->data == data)
        {
            return pCur;//找到返回结点地址
        }
        pCur = pCur->next;
    }
    return NULL;//遍历完还没有找到,返回空
}

//在链表pos位置后插入值为data的新节点
void Insert(PNode pos, DataType data)
{
    if (pos)//pos如何获取?????
    {
        PNode NewNode = BuyNode(data);
        if (NewNode)
        {
            NewNode->next = pos->next;
            pos->next = NewNode;
        }
    }
}

// 删除单链表pos位置上的结点
void Erase(PNode* pHead, PNode pos)
{
    assert(pHead);
    //分三种情况
    if (NULL == pHead&&pos == 0)  //链表和位置都为空
    {
        return;
    }
    else if (pos == 1)  //位置是头部,相当于头删
    {
        PNode pCur =* pHead;
        *pHead = (*pHead)->next;
        free(pCur);
    }
    else //普通位置
    {
        PNode pCur = *pHead;
        while (pCur->next != pos)
        {
            pCur = pCur->next;
        }
        pCur->next = pos->next;
        free(pos);
    }
}

 移除链表中第一个值为data的结点  
//void Remove(PNode* pHead, DataType data)
//{
//  assert(pHead);
//  PNode prev = Find(pHead, data);//find在这里使用不行,参数的类型不一样
//  Erase(&pHead, prev);
//}
//
 移除链表中所有值为data的结点
//void RemoveAll(PNode* pHead, DataType data)
//{
//  assert(pHead);
//  if (NULL == pHead)  
//  {
//      return;
//  }
//  PNode del = *pHead;//先将头结点保存
//
//  //错误一次,将“==”写成“=”,以后注意!
//  if ((*pHead)->data == data)//如果头结点中的值是要删除的
//  {
//      *pHead = (*pHead)->next;//再将头结点指向下一个结点
//      free(del);//最后释放点头结点
//  }
//  PNode pCur = *pHead;
//  PNode prev = pCur;
//  while (pCur)  //遍历
//  {
//      if (pCur->data == data)//找到之后(错误同上)
//      {
//          prev->next = pCur->next;//
//          free(pCur);//
//          pCur = prev->next;//
//      }
//  }
//}

// 获取链表中结点的总个数
size_t Size(PNode pHead)
{
    size_t count = 0;
    while (pHead)
    {
        pHead = pHead->next;
        count++;
    }
    return count;
}

// 获取链表中第一个结点
PNode Front(PNode pHead)
{
    assert(pHead);
    if (NULL == pHead)
    {
        return;
    }
    return pHead;
}

// 获取链表中最后一个节点
PNode Back(PNode pHead)
{
    assert(pHead);
    if (NULL == pHead)
    {
        return;
    }
    PNode pCur = pHead;
    while (pCur->next)
    {
        pCur = pCur->next;
    }
    return pCur;
}

// 判断链表是否为空
int Empty(PNode pHead)
{
    assert(pHead);
    if (NULL == pHead)
    {
        return 0;
    }
    return 1;
}

// 打印单链表
void PrintList(PNode pHead)
{
    PNode pCur = pHead;
    while (pCur)
    {
        printf("%d ", pCur->data);
        pCur = pCur->next;
    }
    printf("\n");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值