一
首先讲第一种无头单头不循环的单链表
是通过指向单链表头结点的结构题指针来维护的
//定义单链表结点
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SListNode;
typedef struct SListNode* SList;
//控制单链表的方法(接口)
void SListInit(SList* head); //SList 就是struct SListNode**,二级指针
void SListDestory(SList* head);
void SListShow(const SList* head);
…………
主函数
int main()
{
SList head; //创建指向单链表结构体的指针
SListInit(&head); //head是SList即struct SListNode*类型, &head则要用二级指针接收
在这里提一下为什么传指向单链表结点的指针的地址并用二级指针接收
如果直接传指向单链表结点的指针
分两种情况
第一种head头指针指向空头指针无法访问到任何结点,指针是按值传参所以也无法改变head头
指针的指向, 这将导致灾难性的后果这个单链表注定永生孤独,永远是一个空链表,无法初始化
且无法添加任何结点
第二种head头指针本身就指向一段大于等于一个结点的单链表则其可以访问到存在的任何结点
只不过head头指针只能访问指向的数据, 但永远无法改变head头指针的指向,调用的方法传入
的只是head指针的一份临时拷贝无论对拷贝变量如何修改都无法改变链表的结构,即无法对链表
进行增删改查的任何操作
return 0;
}
二
再讲第二种无头单向不循环的单链表
也是通过指向单链表头结点的结构题指针来维护的,只不过区别是将head指针再装到一个结构体中,调用单链表的方法时,便可以传这个装了head指针的结构体的地址,并用指向装head指针的结构体的指针去接收,这样就巧妙的避开二级指针使用不熟练的硬伤以及会出现的各种指针危险,也不会纠结改变链表结构的传址,不该变链表结构的传值
(其实不该变实参的形参设置有两种方法:如下)
不该变实参的形参设置有两种方法
(1)传值 形参用与实参相同的类型接收
(2)传址 形参用const 的指针来接收(注意const位于*前的两种情况)
注意:const的使用
const 修饰指针类型可以出现在三个位置分两种情况(前和后)
例:void* b;
const void* b; //在指针指向的类型名前
void const* b; //在*前面
void* const b; //在变量名前
const 在*前(前两种位置),指针指向的内存无法被修改
const 在*后(最后一种位置情况),指针的指向无法被修改
第二种无头单向不循环的单链表如下:
//定义单链表结点
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SListNode;
//定义装了head指针的结构体
typedef struct SList
{
SListNode* _head;
}SList;
typedef struct SList* Head;
//控制单链表的方法(接口)
void SListInit(Head* head); //SList 就是struct SListNode**,二级指针
void SListDestory(Head* head);
void SListShow(const Head* head);
…………
int main()
{
SList head; //实例化装了head指针的结构体
SListInit(&head); //head是SList即struct SList类型, &head则要用一级指针 struct SList*即
Head接收
在维护链表的方法中,head->_head即是访问整个结构体的那个重要的头指针
return 0;
}