关于单链表,我写了很久,查了很多资料,主要的原因还是以前的知识不是太牢固,所以写的时候错误很多,不过大都能调试出来。
或许是一个寒假没咋敲代码了,最普遍的一个错误:判断两个数是否相等的时候,正确的语句是:
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");
}