您的位置:首页 > 新闻 > 资讯 > 网上营销推广_查排名的网站_2022年列入传销组织最新骗法_今日头条十大新闻最新

网上营销推广_查排名的网站_2022年列入传销组织最新骗法_今日头条十大新闻最新

2024/12/27 10:12:32 来源:https://blog.csdn.net/2401_87995839/article/details/144353238  浏览:    关键词:网上营销推广_查排名的网站_2022年列入传销组织最新骗法_今日头条十大新闻最新
网上营销推广_查排名的网站_2022年列入传销组织最新骗法_今日头条十大新闻最新

        Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!

e27eb9aa0ad04060b17eadde3815c761.gif

我的博客:<但凡.

我的专栏:《数据结构与算法之美》、《编程之路》、《题海拾贝》

欢迎点赞,关注!

 

目录

 

1、使用C++实现单链表

1.1节点的声明

1.2节点的初始化

1.3头插和尾插

1.3.1头插

1.3.2尾插

1.4头删和尾删

1.4.1头删

1.4.2尾删

1.5打印链表

1.6测试

 2、面向对象的方式实现单链表

2.1面向对象和面向过程

2.2面向对象的方式实现单链表

3、静态链表实现

3.1动态实现链表和静态实现链表

3.2链表静态实现

3.2.1理解

3.2.2创建

3.2.3头插

3.2.3遍历打印链表

3.2.4测试


 

1、使用C++实现单链表

        虽然我还没说过C++,但是使用C++实现单链表的大体操作和步骤与C语言几乎没有区别,所以我们用C++实现一下单链表,为的是做我们的面向对象方式实现单链表。当然了,后面我可能会出一篇c到c++衔接的博客,大家也可以看完那个之后再回来看这个哈~        

        当然了,在实现单链表时有的c++的新增函数我会做出说明的,大家了解就行。

1.1节点的声明

typedef struct Node
{int a;Node* next;}Node;

1.2节点的初始化

咱们还是先来经典的初始化节点:

Node* BuyNode(int n)//初始化节点
{Node* NewNode = new Node;if (NewNode == NULL){cout << "节点内存申请失败!" << endl;return NULL;}NewNode->a = n;NewNode->next = NULL;return NewNode;
}

        其中,我们的cout<<是输出打印,我可以理解为printf(但是还是有区别的),endl是换行(end line)。

        new可以看成是C++版的malloc,new Node就是开辟一个Node类型的空间。

1.3头插和尾插

1.3.1头插

void TouCha(Node* & ph, int x)
{Node* NewNode = BuyNode(x);NewNode->next = ph;ph = NewNode;
}

        我们这里使用&引用来取别名,当然了使用C语言里面的二级指针也是可以实现的,但是需要注意的是,如上代码我们传入的参数应该是Node*类型的,而二级指针我们应该传入&Node。(我也懒得整英文名了,还是直接拼音取名吧看着还舒服点,但是我们以后尽量还是英文取名,遵循取名习惯规则)。

1.3.2尾插

void WeiCha(Node*& ph, int x)
{Node* NewNode = BuyNode(x);Node* pcur = ph;if (ph == NULL)//链表为空的情况{ph = NewNode;}else{while (pcur->next)//让pcur找到链表最后一个节点{pcur = pcur->next;}pcur->next = NewNode;}
}

1.4头删和尾删

1.4.1头删

void TouShan(Node*& ph)
{if (ph == NULL){cout << "无可删除元素" << endl;}Node* pcur = ph;ph = ph->next;delete pcur;pcur = NULL;
}

1.4.2尾删

void WeiShan(Node*& ph)
{if (ph == NULL){cout << "无可删除元素" << endl;}else if (ph->next == NULL)//表中就一个元素{TouShan(ph);//这时候头删尾删都一样,调用头删}else{Node* pcur = ph;Node* pb = ph;//记录pcur的前一个节点while (pcur->next)//让pcur找到最后一个节点{pb = pcur;pcur = pcur->next;}delete pcur;pcur = NULL;pb->next = NULL;}
}

        在删除操作中,C++提供了一个新的删除函数delete,他的用法和作用和free相似,当然我们这里用free也可以,但是new和delete是配对的,所以我们在这用的delete。

1.5打印链表

void Printlist(Node* ph)
{while (ph->next){cout << ph->a << "-->";ph = ph->next;}cout << ph->a << endl;
}

1.6测试

        在这我们还是和上两篇一样,把函数封装成头文件,然后在主程序的源文件中包含这个头文件。

测试程序:

#include"FileName.h"
int main()
{//初始化链表Node* phead=BuyNode(1);//1//节点的插入TouCha(&phead,0);//0 1WeiCha(phead, 2);//0 1 2WeiCha(phead, 3);//0 1 2 3WeiCha(phead, 4);//0 1 2 3 4TouShan(phead);//1 2 3 4WeiShan(phead);//1 2 3Printlist(phead);return 0;
}

输出结果:

9df8861bb2724b78a1c8e3e9cd222e5c.png

 2、面向对象的方式实现单链表

2.1面向对象和面向过程

  • 面向过程强调的是功能行为,以函数为最小单位,考虑怎么做。
  • 面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

        我们以上的单链表是以面向过程的方式实现的,而其实际上我们写的单链表大多是以面向对象的形式来实现的,现在我们对以上代码进行改造,使其以面向对象的形式展现出来。 

2.2面向对象的方式实现单链表

        在C++中,我们的结构体进行了升级,现在它可以包含成员函数,也就是说结构体的成员现在也可以是函数了。

        此外,C++的结构体会有⼀些默认的成员函数,比如:构造函数、析构函数等这些函数都是自动被调用,不需要手动调用。

        现在我们先给大家把代码写出来,然后再进行讲解:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
using namespace std;
typedef struct Node
{int a;Node* next;}Node;
struct list
{//初始化链表Node* phead;list()//构造函数{phead = BuyNode(1);}~list(){while (phead){TouShan();}}Node* BuyNode(int n)//初始化节点{Node* NewNode = new Node;if (NewNode == NULL){cout << "节点内存申请失败!" << endl;return NULL;}NewNode->a = n;NewNode->next = NULL;return NewNode;}void TouCha(int x){Node* NewNode = BuyNode(x);NewNode->next = phead;phead = NewNode;}void WeiCha(int x){Node* NewNode = BuyNode(x);Node* pcur = phead;if (phead == NULL)//链表为空的情况{phead = NewNode;}else{while (pcur->next)//让pcur找到链表最后一个节点{pcur = pcur->next;}pcur->next = NewNode;}}void WeiShan(){if (phead == NULL){cout << "无可删除元素" << endl;}else if (phead->next == NULL)//表中就一个元素{TouShan();//这时候头删尾删都一样,调用头删}else{Node* pcur = phead;Node* pb = phead;//记录pcur的前一个节点while (pcur->next)//让pcur找到最后一个节点{pb = pcur;pcur = pcur->next;}delete pcur;pcur = NULL;pb->next = NULL;}}void TouShan(){if (phead == NULL){cout << "无可删除元素" << endl;}else{Node* pcur = phead;phead = phead->next;delete pcur;pcur = NULL;}}void Printlist(){while (phead->next){cout << phead->a << "-->";phead = phead->next;}cout << phead->a << endl;}};int main()
{struct list list;//节点的插入list.TouCha(0);//0 1list.WeiCha(2);//0 1 2list.WeiCha(3);//0 1 2 3list.WeiCha(4);//0 1 2 3 4list.TouShan();//1 2 3 4list.WeiShan();//1 2 3list.Printlist();return 0;
}

        为了方便展示,我们把这些代码都放到一起了。

我们来说一下都做了哪些改动:

1、我们把前面写的所有代码都放到了struct list这个结构体的声明里面,让他们作为结构体的成员。

2、我们把所有函数的参数Node* ph都去掉了,并且把所有函数大括号里的ph都改成了phead。这样做是因为我们在list这个结构体里声明或者说创建了phead,那么我们直接对它进行更改就行,不用再传参了。

3、我们新建一个该结构体类型的变量取名为list,但需要注意的是,这样做的话我们在结构体中调用函数时不用带list.,但是在主函数中调用函数需要带list.。

4、我们创建了一个构造函数和一个析构函数。这两个函数会自动调用。我们在使用结构体中的函数之前自动调用构造函数,初始化phead,在完成使用完结构体中的函数后调用析构函数,删除这个链表中的每一个节点(这也是为什么我没写销毁链表这个函数的原因)。

输出结果:

b3d8ba1cb2644b29857b93cb8b3ab156.png

3、静态链表实现

3.1动态实现链表和静态实现链表

        我们上面写的代码就是动态实现链表,因为我们运用了new和delete,以及上两篇我们使用的malloc和free。这种实现方法的优点是空间可以由我们自由操作,不浪费空间,但缺点是耗时,而且不好写。

        所以在算法竞赛中,我们更常用的是静态实现链表。我们直接开辟一个足够大的空间,就不用频繁的malloc和free占用时间了。

        其实链表有很多种,如下图,组合起来一共可以有八种!但是他们的原理都是一样的。我们在这实现一个有头的,循环的链表。

098a5e1b5a704e66b075e44953c86781.png

3.2链表静态实现

3.2.1理解

fc12636681c84c5d8db7bc001150210a.png

         这是链表的理解图,其中红色框框里存放的是节点的数据(我i们这里让节点等于下标),黑色框框里存放的是下一个节点的下标。需要注意的是,第七个节点存放我们第一个节点的下标,达到循环的效果。

3.2.2创建

//创建
int e[N], ne[N], h, id;
//e[N]存放元素,ne[N]存放下一个节点下标

3.2.3头插

void TouCha(int x)//注意我们哨兵位是不动的
{id++;e[id] = x;ne[id] = ne[h];ne[h] = id;
}

       我们的id存放的是有效的数据个数,比方说我现在存放了2个数据,id就是2,同时最后一个数据的下标是2。

       头插我们可以理解为我们先给有效数据id加加,然后再在这个有效数据的位置放上我们想要存放的数据,然后让下标为id的这个位置存放哨兵节点h指向的节点的坐标,再让哨兵位置存放的下标变成id。

3.2.3遍历打印链表

void print()
{for (int i = ne[h];i;i = ne[i]){cout << e[i] << endl;}
}

       当i等于0时停止打印。

3.2.4测试

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
const int N = 1e5 + 10;//10的五次方加10
//创建
int e[N], ne[N], h, id;
//e[N]存放元素,ne[N]存放下一个节点下标
void TouCha(int x)//注意我们哨兵位是不动的
{id++;e[id] = x;ne[id] = ne[h];ne[h] = id;
}
void print()
{for (int i = ne[h];i;i = ne[i]){cout << e[i] << endl;}
}
int main()
{TouCha(1);TouCha(2);TouCha(3);print();return 0;
}

输出结果:

4a1e041b38624a6d9ec9170be8858d48.png

       这里我们只实现了头插和遍历两个操作,这也是我们用的最多的两个操作。

       好了,今天的内容就分享到这,我们下期再见!

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com