关于有头结点和无头结点的单链表
来源:互联网 发布:网络教育学士学位证 编辑:程序博客网 时间:2024/04/27 20:12
今天说一下单链表的有头结点和无头结点的操作,其中有一些细节还是需要注意的.废话不多说直接用代码说吧。(先把代码放这)
//这是一个无头结点的单链表
typedef int ElemType;//这里用typedef的作用是在后期便于更改数据类型
typedef struct Node
{
ElemType data;
struct Node*next;
}Node;//定义了个结构体,里面就个数据域和next域
void Init(Node**p)
{
(*p)=NULL;//因为没有头结点,所以只需将(*p)置为NULL即可。
}
void Insert(Node**p,ElemType val)//这里的插入方法使用的最常用的尾插法
{
Node*newnode=(Node*)malloc(sizeof(Node));//首先是创建一个新节点
newnode->data=val;
newnode->next=NULL;//新节点里存放我们要插入的数据,并且将它的next域制成NULL
if((*p)==NULL)
{
(*p)=newnode;//这里判断的含义是指如果这个单链表里一个数都没有,那么就让newnode节点成为它第一个节点。
return ;
}
Node*q=*p;
while(q->next!=NULL)
{
q=q->next;
}
q->next=newnode;//如果它里面有数,那么就这里创建了一个q来遍历整个单链表,最后遍历到这个链表的结尾,然后将这个数插入到最后面
}
bool Delete(Node**p,ElemType val)
{
if( (*p)==NULL)
{
return false;//这里判断的是如果单链表里没有数,那么当然也就没法删除了
}
Node*q=(*p);
if((*p)->data==val)
{
Node*q=(*p);
(*p)=(*p)->next;
free(q);
return true//这个if语句的含义是如果第一个数就是我要删除的那个数,那么就让p指向p->next,然后释放掉q
}
for(Node*q=(*p);q->next !=NULL;q=q->next)//如果走到这一步则说明不是第一个数,然后就是往后遍历直到找到这个数
{
if(q->next->data==val)
{
Node*pCur=q->next;
q->next=pCur->next;
free(pCur);
return true;//这里是删除节点的步骤,思想就是指向下一个的下一个节点
}
}
return false;//如果没找到这个数,就返回false
}
bool Clear(Node**ps)
{
if( (*ps)==NULL)
{
return false;
}//当然,还是要判断,如果单链表是空的,那就返回false;
Node*pCur=*ps;
Node*q=*ps;
while(q->next!=NULL)//只要q->next!=NULL,那么就说明还是节点
{
pCur=q->next;
free(q);
q=pCur;
}//这里的步骤就是从头开始一个一个删,直到最后只有一个节点后就返回
free(pCur);//这就是把最后一个节点删了
(*ps)=NULL;
return true;
}
void Show(Node**ps)//这就是打印函数
{
for(Node*q=*ps;q!=NULL;q=q->next)
{
printf(“%d “,q->data);
}
printf(“\n”);
}
void main()
{
Node*ps;
Init(&ps);
for(int i=0;i<3;i++)
{
Insert(&ps,i);
}
Show(&ps);
Delete(&ps,0);
Show(&ps);
Clear(&ps);
Show(&ps);
}
运行的截图放这:
接下来我们再来说一说有头结点的单链表
void InitList(List plist)
{
assert(plist!=NULL);
//plist->data;//不用初始化它的data域
plist->next = NULL;
}
//头插
bool Insert_head(List plist,int val)
{
Node p = (Node )malloc(sizeof(Node));
p->data = val;//还是创建一个节点还存放我们要用的数据
p->next = plist->next;
plist->next = p; //插入的时候先连接p和plist->next,然后再连接plist和p
return true;
}
//尾插
bool Insert_tail(List plist,int val)
{
Node p = (Node )malloc(sizeof(Node));
p->data = val;
Node *q;for(q=plist;q->next!=NULL;q=q->next) ;//找尾节点//将p插入在q的后面p->next = q->next;//p->next = NULL;q->next = p;return true;
}
Node *Search(List plist,int key)//这是查找函数,若找到目标数据,则返回该节点
{
for(Node *p=plist->next;p!=NULL;p=p->next)
{
if(p->data == key)
{
return p;
}
}
return NULL;
}
bool Delete(List plist,int key)
{
Node *p;
for(p=plist;p->next!=NULL;p=p->next)
{
if(p->next->data == key)
{
break;
}
}
if(p->next == NULL)//没有key
{
return false;
}
//将节点从链表中删除Node *q = p->next;p->next = q->next;//p->next = p->next->next;free(q);//释放内存return true;
}
bool IsEmpty(List plist)
{
return plist->next == NULL;
}
//得到数据节点个数
int GetLength(List plist)
{
int count = 0;
for(Node *p=plist->next;p!=NULL;p=p->next){ count++;}return count;
}
void Show(List plist)
{
for(Node *p=plist->next;p!=NULL;p=p->next)//p->next!=NULL
{
printf(“%d “,p->data);
}
printf(“\n”);
}
void Destroy(List plist)
{
//总是删除第一个数据节点
Node *p;
while(plist->next != NULL)
{
p = plist->next;
plist->next = p->next;
free(p);
}
}
void Clear(List plist)
{
Destroy(plist);
}
void main()
{
Node ps;
InitList(&ps);
for(int i=0;i<5;i++)
{
Insert_head(&ps,i);
}
Show(&ps);
for(int j=5;j<10;j++)
{
Insert_tail(&ps,j);
}
Show(&ps);
}//这后面的和之前说到的无头结点的单链表内容都是一样的,所以不再啰嗦。
来张截图瞅瞅
最后,做一点总结吧,说说这两种方法的优缺点吧,有头结点的单链表肯定是比较好理解的,但它也会浪费一点资源,然而对于无头结点的就是代码稍微微的能难一点,但其中的好处则是不言而喻的,节省资源这一点其实并不是亮点,我个人认为它更好的一点是没有头结点的阻碍,比如说连接两个链表,你无头结点的就可以直接连接,但像有头结点的,它就要处理头结点这个问题。其实吧,都差不多,就是看个人习惯。
- 关于有头结点和无头结点的单链表
- 分别用头插法和尾插法建立有头结点和无头结点的单链表
- 单链表的创建(有头结点和无头结点)
- 单链表(无头结点)
- 无头结点单链表
- 单链表的头结点和结点
- 单链表的头结点和头指针
- 无头结点的链表逆置
- 头指针和头结点的区别
- c实现无头结点单链表
- 头指针和头结点
- 单链表的建立(头部延长、尾部延长)、插入操作、删除操作(无头结点的删除、有头结点的删除)
- 无头结点的单链表(java实现)
- 实现无头结点单链表的基本操作函数
- 有头结点的单向链表
- 实现有头结点的单链表的简单操作
- 关于链表中头指针和头结点的理解
- 关于链表中头指针和头结点的理解
- PHP 生成二维码
- 单点登录
- 数据挖掘之遗传算法
- Core Java Volume I 读书笔记--第4章 对象与类
- 总有那么一段时间,茫茫然而不知所以。
- 关于有头结点和无头结点的单链表
- struts知识点梳理
- Hadoop小文件的优化
- Android Simulator 修改hosts
- 数组与矩阵问题---子数组的最大累加和问题
- MFC计算机图形学(2)
- htop的源码编译方法
- 网易前端面试
- Swift 4.0 中的 open,public,internal,fileprivate,private