不带头结点的单链表:
1.不带头结点的单链表操作中,除了初始化,头插,尾插,删除,操作与带头结点的单链表有差别外,其它的操作基本上一样。
2.链表指针直接指向了首元节点,因此在首元节点前插入数据元素或者删除首元节点元素都会改变头指针的值。所以这里要引入二级指针。
3、存储结构:

4、实现:
(1)list.h:
#pragma once
//链表指针直接指向了首元节点,因此在首元节点前插入数据元素或者删除首元节点元素都会改变头指针的值。所以这里要引入二级指针。
typedef struct Node
{
int data;
struct Node *next;
}Node,*List;
//初始化
void InitList(List *pplist);
//头插
bool Insert_Head(List *pplist,int val);
//尾插
bool Insert_Tail(List *pplist,int val);
//删除
bool Delete(List *pplist,int key);
//查找
Node *Search(List plist,int key);
//求字符串长度
int GetLength(List plist);
//打印
void Show(List plist);
//摧毁
void Destroy(List *pplist);
(2)list.cpp:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "list.h"
//初始化
void InitList(List *pplist)
{
assert(pplist != NULL); //头指针一定存在
*pplist = NULL; //头指针指向的第一个节点不存在
}
static Node *BuyNode(int val)
{
Node *p = (Node *)malloc(sizeof(Node));
assert(p != NULL);
p->data = val;
p->next = NULL;
return p;
}
//头插
bool Insert_Head(List *pplist,int val) //pplist是头指针
{
Node *p = BuyNode(val); //购买一个节点
p->next = *pplist; //新的节点的后继为原来的头结点
*pplist = p; //头指针指向新节点p
return true;
}
//尾插
bool Insert_Tail(List *pplist,int val)
{
Node *p = BuyNode(val);
Node *q = *pplist; //q为第一个节点
if(q == NULL)
{
*pplist = p;
}
else
{
for(;q->next != NULL;q = q->next);//找尾巴
q->next = p; //最后一个节点的后继指向新的节点
}
return false;
}
//删除
bool Delete(List *pplist,int key)
{
if(pplist == NULL || *pplist == NULL) //当头指针不存在或者第一个节点不存在
{
return false;
}
Node *p = *pplist; //p此时为第一个节点
if(p->data == key) //第一个节点就是要删除的值
{
*pplist = p->next; //头指针指向第二个节点
free(p); //销毁第一个节点
return true;
}
for(p = *pplist;p->next != NULL;p = p->next)
{
if(p->next->data == key) //找到要删除节点的前一个节点
{
Node *q = p->next; //q即为要删除的节点
p->next = q->next;
free(q);
return true;
}
}
return false;
}
//查找
Node *Search(List plist,int key)
{
Node *p;
for(p = plist;p != NULL;p = p->next)
{
if(p->data == key)
{
break;
}
}
return p;
}
//求字符串长度
int GetLength(List plist)
{
int count = 0;
for(Node *p = plist;p!= NULL;p = p->next)
{
count++;
}
return count;
}
//打印
void Show(List plist)
{
for(Node *p = plist;p != NULL;p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
}
//摧毁
void Destroy(List *pplist)
{
Node *p;
while(*pplist != NULL)
{
p = *pplist;
*pplist = p->next;
free(p);
}
}
(3) main.cpp:
#include <stdio.h>
#include <vld.h>
#include "list.h"
int main() /* 不带头节点单链表测试 */
{
List plist;
InitList(&plist);
Show(plist);
printf("length = %d\n",GetLength(plist));
int i;
for(i=0;i<10;i++)
{
Insert_Head(&plist,i);
}
Show(plist);
printf("length = %d\n",GetLength(plist));
for(i=20;i<30;i++)
{
Insert_Tail(&plist,i);
}
Show(plist);
printf("length = %d\n",GetLength(plist));
Delete(&plist,5);
Show(plist);
printf("length = %d\n",GetLength(plist));
Delete(&plist,5);
Show(plist);
printf("length = %d\n",GetLength(plist));
Delete(&plist,9);
Show(plist);
printf("length = %d\n",GetLength(plist));
Delete(&plist,29);
Show(plist);
printf("length = %d\n",GetLength(plist));
Destroy(&plist);
return 0;
}
本文探讨不带头结点的单链表,介绍其操作特性,如初始化、头插、尾插和删除等,并强调在处理首元节点时需要使用二级指针以避免头指针变化。此外,还提供了链表的存储结构和实现代码示例。

2508

被折叠的 条评论
为什么被折叠?



