为了完成学校假期作业被迫营业,想要整个完整的代码可以评论我私发给你,哈哈哈,仅供参考不喜勿喷,欢迎大佬指点
大家好我今天为大家讲的是链表。
想必大家一定会问:
什么是链表?
链表是一中物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。
这句话可能会不好理解 ,没关系我会带领大家进一步理解
那么,我来问问大家
链表由什么组成的呢?
链表是由一系列结点组成的,而每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
如图所示
代码如下:
typedef int ElementType;
struct Node
{
ElementType date;
struct Node* next;
};
typedef struct Node* List;//链表
typedef List Position;//位置
结点有了 那我们如何创建链表呢 ?
观察上面的图我们会发现链表都是有一个结点作为头结点,后面的每个结点都是通过上一个指针域找到的,所以我们创造链表首先要为链表创造出一个头结点。
struct Node* L=NULL;
L = makelist(L);
头结点创建完后,我们知道头结点是struct LNode*类型的指针,所以我们为头结点分配内存空间,
struct Node* makelist(struct Node* L)
{
L = (struct Node*)malloc(sizeof(struct Node));
L->next = NULL;
return L;
}
拥有了头结点,那么链表就可以进行插入数据了
如何向链表中插入数据呢?
插入的方法有两种一个是头插法,而另一个是尾插法
那么我先说头插法,头插法就是将新结点插入到当前链表的头结点之后
答案:不可以颠倒顺序的;
L->next中存储的是A结点的地址 如果 没有把A结点的地址保存 而直接把B结点的地址装进L->next,那么A结点的地址将会丢失,我们就无法再访问A结点(若A结点后面还有结点我们也将无法访问)
代码实现:
//插入元素(头插法)
void Insert(ElementType X, List L)
{
Position TmpCell, age;
TmpCell = malloc(sizeof(struct Node));
if (TmpCell == NULL)
printf("内存申请失败");
//将数据放入插入结点的数据域内
TmpCell->date = X;
//将新节点插入链表中
TmpCell->next = L->next;
L->next = TmpCell;
printf("插入成功\n");
}
而尾插法就是将新结点插入到当前链表的尾结点之后
答案:不可以颠倒顺序的;
因为r指向的是链表末尾的结点,如果我们先把r指向新生成的结点s,这样我们就无法找到链表末尾结点,那么我们还怎么把新生成的结点插入链表的末尾呀!所以顺序不可以颠倒的。
尾插法的代码,由于时间关系我没有写,但有兴趣的可以自己去了解的一下原理和我讲的没什么差别,也很容易就可以实现。
有些同学说插入了这么多结点我都不知道插入多少个结点啦,
所以我们可以创造出一个函数 打印链表中的每个结点,这样我们就可以清楚链表中有那些结点啦,一目了然。
如何打印链表?
代码实现:
//打印链表
void Printf(List L)
{
Position P,Tmp;
P = L->next;
while (P != NULL)
{
Tmp = P->next;
printf("%d->", P->date);
P = Tmp;
}
printf("NULL\n");
}
当然,有了插入结点就有他的对立删除结点
如何删除链表中的结点呢?
我们可以通过结点中数据域中的数据寻找我们所要删除的结点,通过数据遍历整个链表找到我们要删除的结点的前一个结点。注意这里要找的是删除的结点的前一个结点。如果链表中每个结点存放的数据都不是我们所要删除的数据,那么我们就不进行结点删除。
清楚思路之后来看看如何用代码实现呢?
代码如下:
//检测链表是否为末尾
int IsLast(Position P, List L)
{
return P->next == NULL;
}
//返回要删除元素结点的前一个结点的位置
Position FindPrevious(ElementType X, List L)
{
Position P;
P = L;
while (P->next != NULL && P->next->date!= X)
P = P->next;
return P;
}
//删除链表上的某一个结点
void Delete(ElementType X, List L)
{
Position P, TmpCell;
P = FindPrevious(X, L);
if (!IsLast(P, L))
{
TmpCell = P->next;
P->next = TmpCell->next;
free(TmpCell);
}
}
那么有的同学说一个一个删除结点,好费劲 有没有快捷的方法能够把整个链表中的结点全部删除呢,我可以负责人的告诉你当然有啦
如何将链表清空?
我们直接看代码还是很简单的
//清空链表
void DeleteList(List L)
{
Position P, Tmp;
P = L->next;
L->next = NULL;
while (P != NULL)
{
Tmp = P->next;
free(P);
P = Tmp;
}
}
我们还可以检测链表是否清空成功
//检验链表是否为空
int IsEmpty(List L)
{
return L->next == NULL;
}
int main()
{
......
if (IsEmpty(L))
{
printf("链表为空\n");
}
else
{
printf("链表不为空\n");
}
......
}
这样整个链表的知识我们就学完了
我们来一起回顾一下我们都学了那些知识
1.什么是链表
2.链表的组成
3.链表的创建
4.向链表中插入结点
5.从链表中删除结点
6.链表的打印
7.链表的清空
记得掌握这七个小知识点哦,谢谢大家