链表的实现有两种方式:有头和无头。(我只知道两种欢迎大佬指出新的方式)
两者的区别在于,主要体现在链表结点的增减上,没有头结点,链表的第一个结点的增减操作要和其他结点分开独立出来,有头结点,链表的第一个结点的增删操作可以和后续的节点合并的一起。
链表的创建方式有两种:头插法和尾插法。
两者区别在于对于输出入数据的存储顺序,头插法是逆序,尾插是顺序,看图
有头节点 尾插法
算法描述:将新插入的节点首地址存放到节点
有头节点 头插法
算法描述:将新插入的节点首地址存储到头节点中 在将上一个节点的首地址存放到新插入的节点中
无头节点尾插
无头节点头插法
先定义个结构体 为了便于观察此处就不用typedef
struct Student{
int num;
struct Student *next;
};
头插法
// 动态头节点链表 头插法
// 不断的把新链表 插入 头 -> 第一个节点之间
static struct Student *DSLists(){ //返回值是 头节点指针
struct Student *current, *head;// current 指向新节点 head 指向头节点 tail 尾节点
int m;
head = (struct Student *)malloc(sizeof(struct Student));// 建立头节点 头指针->head
current = head;
current->next = NULL;//
scanf_s("%d",&m);
while (m!=-1){
current = (struct Student *)malloc(sizeof(struct Student));// 分配新节点空间
current->next = head->next;// 连接 新节点的指针域-> 头节点节点指针域-> 的原节点
head->next = current;// 头节点指针域指向新的节点 新节点变成第一个节点
current->num = m;
scanf_s("%d",&m);
}
//输出
struct Student *s;
s = head->next; //如果是 将head直接赋值给 s的话 在输出的时候 会输出一个随机数(因为head->num没有存放数据)
if (head != NULL){
while (s){ // 地址为空 结束
printf("%d ", s->num);
s = s->next;// 将下个节点的地址给 q
}
}
return head;
}
尾插法
// 动态头节点链表 尾插法 输出顺序和输入顺序相同
static struct Student *DSLists2(){ //返回值是 头节点指针
struct Student *current, *head, *tail;
int m;
current = (struct Student *)malloc(sizeof(struct Student));
tail = current;
head = current;
head->next = NULL;
scanf_s("%d",&m);
while (m!=-1){
current = (struct Student *)malloc(sizeof(struct Student));
tail->next = current;// 原链表尾指针域指向新的节点首地址
tail = current;// 新节点 首地址->尾节点
current->num = m;
scanf_s("%d",&m);
}
tail->next = NULL;//设置为节点为空
struct Student *s;
s = head->next;
printf("%d", head->num);
if (head != NULL){
while (s!=NULL){ // 地址为空 结束
printf("%d ", s->num);
s = s->next;// 将下个节点的地址给 q
}
}
return head;*/
}
反序列
有头节点反序列
没写完等下接着写