前言:线性表-----线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结
构,常见的线性表:顺序表、链表、栈、队列、字符串.顺序表(数组实现具有内存连续特性),链表(内存空间分别通过自身存放前后节点指针内存不用内存连续),栈和队列(一类特殊的线性表),字符串在内存中是特殊的类似常量的存在,它一般在静态变量中存放。
链表按需开辟所需要的内存它每次开辟的时候使用的动态内存(如用malloc)分布在堆上。
补:关于内存的分布如下图
简单的进行了一些内存的分布跟链表大类的归类。接下来我们说说链表的那些事吧!
一.单链表(SingleList)的实现
本文我们主要实现单链表(无头单向无循环)是基本的单链表,具有增删查改功能,用c语言实现,一共有3个板块。 头文件名为:SList.h 源文件有:SLlist.c test.c。
SList.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLNodetype;
// 链表节点的初始化
typedef struct SLNode {
SLNodetype val;//存放的数据内容
struct SLNode* next;
}SLNode;
// 头插 尾插
void SLNodePushBack(SLNode**head,SLNodetype x);
void SLNodePushFront(SLNode**head,SLNodetype x);
// 头删 尾删
void SLNodePopBack(SLNode** head);
void SLNodePopFront(SLNode** head);
SLlist.c
#include"SList.h"
// creat Node 函数实现
SLNode* CreatNode(SLNodetype x)
{
SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
NewNode->val = x;
NewNode->next = NULL;
return NewNode;
}
void SLNodePushFront(SLNode** head, SLNodetype x)
{
assert(head);
SLNode* NewNode = CreatNode(x);
if (*head == NULL)
{
*head = NewNode;
}
else {
NewNode->next = *head;
*head = NewNode;
}
}
void SLNodePushBack(SLNode** head, SLNodetype x)
{
assert(head);
SLNode* NewNode = CreatNode(x);
SLNode* tail = *head;
if (*head == NULL)
{
*head = NewNode;
}
else
{
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = NewNode;
}
}
void SLNodePopBack(SLNode** head)
{
assert(head);
assert(*head);
SLNode* tail = *head;
if (tail->next == NULL)
{
free(tail);
*head = NULL;
}
else {
while (tail->next->next != NULL)
{
tail = tail->next;
}
free(tail->next->next);
tail->next = NULL;
}
}
void SLNodePopFront(SLNode** head)
{
assert(head);
assert(*head);
if ((*head)->next == NULL)
{
free(*head);
*head = NULL;
}
else
{
SLNode* Newhead = (*head)->next;
free(*head);
*head = Newhead;
}
}
二. 测试链表的可行性 (test.c)
1.测试头插
#include"SList.h"
int main()
{
SLNode* head = NULL;
SLNodePushFront(&head,7);
SLNodePushFront(&head,9);
SLNodePushFront(&head,0);
SLNodePushFront(&head,6);
Print(head);
return 0;
}
2.测试头尾插
3. 测试头尾删
三.完善链表
a.在List.c上补充了指定位置的添加和删除。
void SLNodeInsert(SLNode* pos, SLNodetype x)
{
SLNode* NewNode = CreatNode(x);
if (pos->next == NULL)
pos->next = NewNode;
else {
SLNode* Tmp = pos->next;
pos->next = NewNode;
NewNode->next = Tmp;
}
}
void SLNodeEraser(SLNode**head,SLNode* pos)
{
SLNode* pos_pre = *head;
if (pos == head)
{
SLNode* Newhead = (*head)->next;
free(*head);
*head = Newhead;
}
else {
while (pos_pre != pos)
{
pos_pre = pos_pre->next;
}
SLNode* Tmp = pos;
pos_pre->next = Tmp->next;
free(Tmp);
}
}
b.图加文解决其中的难点
Tip: 朋友我们在这里使用的指定位置用的是指针这是区别许多教材里面传递的是头节点往后的几个位置,这里是模仿了后面c++的链表的查找删除功能。这样做是为了方便你后续的学习。
1. 单链表中指针的传递问题
如下如果传递的是一级指针如下:
void Pushback(SLNode*head,int x){
newnode = creat(x);
if(head==NULL)
{
head =newnode
}
}
int main()
{
SLNode*Head =NULL;
Pushback(Head,2);
}
就单纯看这里:我们要只知道函数中的head实际上是形参是传递参数主函数中链表头节点的临时拷贝,这里 head = newnode 是指针等于指针你改变的是指针head,即没有对他的内容进行改动,但是实参Head虽然跟形参head他们指向的内容相同但是他们俩是不同的指针。
比如当链表中不是空参我们看看图中指针的指向
本期带你引入了
单链表以及其中关于其中指针的问题。期待下期关于解决链表更多问题!感觉不错就给个好评吧!