单链表基本操作
头文件
ifndef __LINK_LIST_H__
#define __LINK_LIST_H__
typedef int DataType;
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
//定义结构体将结点的数据域和指针域封装起来
typedef struct Node
{
DataType _data;//单链表的数据域
struct Node* _next;//单链表的指针域
}Node,*pNode, *pList;
void InitLinkList(pList *pplist);//初始化单链表
void PushBack(pList *pplist, DataType x);//c从尾部向单链表中插入元素
void Display(pList plist);//输出函数
void Destory(pList* pplist);//销毁单链表,释放内存
void PopBack(pList* pplist);//从尾部删除数据
void PushFront(pList *pplist, DataType x);//前面插入数据
void PopFront(pList *pplist);//从前面删除数据
//指定位置的插入和删除
pNode Find(pList plist, DataType x);//找元素
void Insert(pList *pplist, pNode ret, DataType x);//找到这个元素的位置并插入
void Erase(pList *pplist,pNode ret);//删除所在位置的元素
//删除指定元素
void Remove(pList *pplist,DataType x);
//删除指定的所有元素
void RemoveAll(pList *pplist, DataType x);
//对所有元素进行排序(冒泡)
void Bubblesort(pList *pplist);
#endif __LINK_LIST_H__
函数的功能实现
#include "LinkList.h"
void InitLinkList(pList *pplist)//用二级指针接收一级指针的地址
{
assert(pplist);
*pplist = NULL;//让元素为空
}
pNode BuyNode(x)//为x开辟空间
{
pNode pnode = malloc(sizeof(Node));
if (pnode == NULL)
{
perror("error");//没有开辟成功
exit(0);
}
pnode->_data = x;
pnode->_next = NULL;
}
void PushBack(pList *pplist, DataType x)//后插元素
{
assert(pplist);
pNode p = *pplist;
//为x开辟空间
pNode pnode = BuyNode(x);
//如果是个空链表
if (p == NULL)//没有节点
{
*pplist = pnode;
}
else
{
while (p->_next != NULL)//遍历到最后一个节点
{
p = p->_next;
}
p->_next = pnode;//放入元素
}
}
void Display(pList plist)//输出元素
{
pNode p = plist;
while (p)//遍历整个单链表
{
printf("%d->",p->_data);
p = p->_next;
}
printf("over\n");
}
void Destory(pList* pplist)//释放这个链表
{
pNode p = *pplist;
assert(pplist);
while (p)
{
pNode del = p;//先把节点保存起来,如果先移动,之后这个结点找不到
p = p->_next;//移动节点
free(del);//要删除节点的指针
}
*pplist = NULL;//让指针等于空,避免称为野指针
}
void PopBack(pList* pplist)
{
pNode cur = *pplist;
assert(pplist);
if (*pplist == NULL)//没有节点
{
return ;
}
//只有一个节点
if (cur->_next == NULL)
{
free(*pplist);
*pplist = NULL;//删除头结点必须改首指针的值。所以必须用*pplist,不能用cur,改变不了首地址的值
return;
}
//大于一个节点
else
{
while (cur->_next->_next)
{
cur = cur->_next;
}
free(cur->_next);
cur->_next = NULL;
}
}
void PushFront(pList *pplist, DataType x)//头插
{
assert(pplist);
//为这个数开辟空间
pNode newnode = BuyNode(x);
//如果没有节点
if (*pplist == NULL)
{
*pplist = newnode;//直接赋值
}
else
{
newnode->_next = *pplist;
*pplist = newnode;
}
}
void PopFront(pList *pplist)//头删
{
pNode cur=NULL;
assert(pplist);
cur = *pplist;
if (cur == NULL)//没有节点
{
return;
}
else
{
pNode del = cur;//将第一个节点先保存起来
*pplist = (*pplist)->_next;
free(del);
del = NULL;
}
}
pNode Find(pList plist, DataType x)//在链表中查找元素
{
pNode cur = plist;
if(*pplist==NULL)//如果是空链表返回
{
return;
}
while (cur)
{
if (cur->_data == x)//遍历整个单链表
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
//向单链表中插入元素
void Insert(pList *pplist, pNode ret, DataType x)
{
pNode newnode = BuyNode(x);
assert(pplist);
assert(ret);
//如果是空,直接插入
if (*pplist == NULL)
{
PushFront(pplist,x);
}
else
{
newnode->_next = ret->_next;//注意先后顺序不能变
ret->_next = newnode;
}
}
void Erase(pList *pplist, pNode pos)//删除某一位置的元素
{
pNode cur = NULL;
assert(pplist);
assert(pos);
cur = *pplist;//用一个指针保存首结点
if (*pplist == NULL)
{
return;
}
while ((cur->_next !=pos)&&cur)
{
cur = cur->_next;
}
if (cur!= NULL)
{
cur->_next = pos->_next;
free(pos);
pos = NULL;
}
}
void Remove(pList *pplist, DataType x)
{
assert(pplist);
pNode cur = *pplist;
pNode prev = NULL;
if (*pplist == NULL)
{
return;
}
while (cur)
{
if (cur->_data == x)
{
pNode del = cur;
if (cur == *pplist)//看是否为第一个结点
{
*pplist = cur->_next;
free(del);
break;//如果是第一个结点,跳出去,不用遍历
}
else
{
cur = cur->_next;
prev->_next = del->_next;
free(del);
break;//删除元素后跳出
}
}//当if条件不成立的时候,才会执行else
else{
prev = cur;
cur = cur->_next;
}
}
}
void RemoveAll(pList *pplist, DataType x)
{
assert(pplist);
pNode cur = *pplist;
pNode prev = NULL;
if (*pplist == NULL)
{
return;
}
while (cur)
{
if (cur->_data == x)
{
pNode del = cur;
if (cur == *pplist)//看是否为第一个结点
{
*pplist = cur->_next;
free(del);
break;
}
else
{
cur = cur->_next;
prev->_next = del->_next;
free(del);
}
}
//将所有的元素都删除掉,链表一直向后遍历,直到删除所有的元素
else{
prev = cur;
cur = cur->_next;
}
}
}
void BubbleSort(pList *pplist)
{
pNode tail = NULL;
pNode pre = NULL;//定义两个指针-->后指针
pNode cur = NULL;//前指针
DataType tmp;
//外层循环的条件是tail指针向前移动时是否等于头指针
while (tail != (*pplist)->_next)
{
pre = *pplist;
cur = pre->_next;
//内层循环看前后指针的值是否和tail的值相等
while ((cur != tail) && (pre->_next != tail))
{
if ((cur->_data )>(pre->_data))//交换前后两个结点的值
{
tmp = cur->_data;
cur->_data = pre->_data;
pre->_data = tmp;
}
pre = pre->_next;
//这个条件必须注意,当cur的下一个值等于tail的时候,就不让cur向后移动。
if (cur->_next != tail)
{
cur = cur->_next;
}
}
tail = cur;//让tail向前移动一次
}
}
主函数测试
#include "LinkList.h"
void test()
{
pList plist;//指针类型的变量
pNode ret;
InitLinkList(&plist);//初始化单链表
PushBack(&plist,2);//c从尾部向单链表中插入元素
PushBack(&plist, 4);
PushBack(&plist, 8);
PushBack(&plist, 6);
PushBack(&plist,5);
Display(plist);
PopBack(&plist);//尾部删除元素
Display(plist);
PushFront(&plist, 7);//头部插入元素
Display(plist);
PopFront(&plist);//头部删除元素
Display(plist);
ret=Find(plist, 4);
if (ret != NULL)
{
printf("%d\n", ret->_data);
Insert(&plist, ret, 5);
Display(plist);
Erase(&plist, ret);
Display(plist);
}
PushBack(&plist, 5);
PushBack(&plist, 5);
PushBack(&plist, 9);
PushBack(&plist, 1);
PushBack(&plist, 5);
Display(plist);
Remove(&plist,5);//删除元素
Display(plist);
RemoveAll(&plist, 5);//删除重复元素
Display(plist);
BubbleSort(&plist);//冒泡排序
Display(plist);
Destory(&plist);//释放单链表
}
int main()
{
test();
return 0;
}