文章标题C语言实现单链表之基础操作

来源:互联网 发布:relex软件 代理 编辑:程序博客网 时间:2024/06/07 03:39

单链表的基础操作:初始化链表、删除链表、头插、尾插、头删、尾删、查找数据、删除特定结点、在特定位置插入结点、打印链表
typedef int DataType;
typedef struct SeqList
{
struct SeqList *pNext;
DataType _data;
}SeqList, *pSeqList;
//构建新结点的函数
SeqList* ByeNewNode(DataType data)
{
SeqList tmp = (SeqList )malloc(sizeof(SeqList));
//malloc 在开辟空间时可能失败,因此要加上判断,保证代码健壮性
if (tmp != NULL)
{
tmp->_data = data;
tmp->pNext = NULL;
}
return tmp;
}
一:初始化链表
如果不初始化我们并不能知道链表的指向,因此需要把头结点制NULL。
void initialize(pSeqList *phead)
{
assert(pHead);
*phead = NULL;
}
注意:如果pHead为NULL,解引用时就会出错,因此需要加assert,如果出错就会报错。assert能帮助定位错误

二、删除链表
删除链表就必须把所有的结点都删除。
void DestroyList(pSeqList* pHead)
{
assert(pHead);
pSeqList tmp = *pHead;;
pSeqList proNode = tmp;
if (*pHead == NULL)
{
return;
}
while (tmp)
{
proNode = tmp;
tmp = tmp->pNext;
free(proNode);
proNode = NULL;
}
*pHead = NULL;
}
采用两个指针保存结点,一个是保存当前结点,一个是保存下一个结点,不然把当前结点一删除,就不能找到下一个结点了。

三、头插
头插是每一次把结点插入头结点的位置,因此每一次需要改变头指针
void PushFront(pSeqList* pHead, DataType data)
{
assert(pHead);
pSeqList proNode = NULL;
pSeqList tmp = ByeNewNode(data);
if (tmp != NULL)
{
tmp->pNext = *pHead;
*pHead = tmp;
}
}
注意:开辟了新结点返回的指针一定要判NULL

四、头删
每一次都删除头结点,当头结点为空时就不用删除了
void PopFront(pSeqList* pHead)
{
assert(pHead);
if (*pHead == NULL)
{
return;
}
pSeqList tmp = *pHead;
*pHead = (*pHead)->pNext;
free(tmp);
}

五、尾插
每一次都必须插入最后一个结点的后面
void PushBack(pSeqList* pHead, DataType data)
{
assert(pHead);
pSeqList tmp = NULL;
if (*pHead == NULL)
{
*pHead = ByeNewNode(data);
return;
}
tmp = *pHead;
while (tmp->pNext)
{
tmp = tmp->pNext;
}
tmp->pNext = ByeNewNode(data);
}
尾插在开辟新结点后不用判NULL,尾结点后面本来就是空,如果后面为空也就没关系了。

六、尾删
1.当头为NULL
2.只有一个结点(改变头结点的指向)
3.有超过一个结点
void PopBack(pSeqList* pHead)
{
assert(pHead);
pSeqList tmp = NULL;
pSeqList proNode = NULL;
if (*pHead == NULL)
{
return;
}
if ((*pHead)->pNext == NULL)
{
free(*pHead);
*pHead = NULL;
}
tmp = *pHead;
while (tmp->pNext)
{
proNode = tmp;
tmp = tmp->pNext;
}
free(tmp);
proNode->pNext = NULL;
}

七、查找数据
只要遍历一遍就可以知道数据是否在链表中
pSeqList Find(pSeqList pHead, DataType data)
{
assert(pHead);
pSeqList tmp = pHead;
while (tmp)
{
if (tmp->_data == data)
{
return tmp;
}
tmp = tmp->pNext;
}
return NULL;
}

八、删除特定位置的结点
void Erase(pSeqList* pHead, pSeqList pos)
{
assert(pHead);
pSeqList tmp = NULL;
if (*pHead == NULL)
{
return;
}
if (*pHead == pos)
{
free(*pHead);
*pHead = NULL;
}
tmp = *pHead;
while ((tmp->pNext != pos) && (tmp != NULL))
{
tmp = tmp->pNext;
}
if (tmp->pNext == pos)
{
tmp->pNext = pos->pNext;
free(pos);
pos = NULL;
}
}
九、特定位置插入结点
采用插入到pos位置的后面,当然可以插入到pos位置上只需要把代码修改一点就可以
void Insert(pSeqList* pHead, pSeqList pos, DataType data)
{
assert(pHead);
pSeqList proNode = NULL;
pSeqList newNode = NULL;
if (*pHead == NULL)
{
return;
}
newNode = ByeNewNode(data);
if (newNode == NULL)
{
return;
}
if (*pHead == pos)
{
newNode->pNext = (*pHead)->pNext;
(*pHead)->pNext = newNode;
}
proNode = *pHead;
while ((proNode != pos) && (proNode != NULL))
{
proNode = proNode->pNext;
}
if (proNode == pos)
{
newNode->pNext = pos->pNext;
pos->pNext = newNode;
}
}

十、打印链表
void PrintList(pSeqList pHead)
{
assert(pHead);
while (pHead != NULL)
{
printf(“%d “, pHead->_data);
pHead = pHead->pNext;
}
printf(“\n”);
}

注意:对于链表的操作最重要的是边界是否考虑周全,思路是否明确

0 0
原创粉丝点击