寒假自学数据结构打卡 Day1 单链表

寒假自学数据结构打卡 Day1 单链表

​ 众所周知,南京某顶着985,211,双一流名头的三本大学的放假时间是极晚的,若不是学生闹一闹,恐怕得到二月份才放假。上学期的C++课我虽然考了100,但越学越觉得力不从心。所以抽出来寒假来学一下数据结构。

​ 数据结构书配合网课虽然易于理解,但使用的毕竟是类C语言而且还不完整,所以用C++来实操一下就特别有必要了。

C++中单链表的构建

struct ListNode
{
    double value;
    ListNode *next;
    ListNode(double value1, ListNode *next1 = nullptr)
    {
        value = value1; next = next1;
    }//构造函数
};

​ 链表就是用链子把一连串节点给串起来,节点中存有数据与指向下一个节点的指针,用结构体来实现再合适不过了。(虽然我们C++课学的是类,不过类还是要用public之类的语句,我觉得不如结构体简便)

ListNode* head=NULL;

​ 这里我建立了头节点,它不存储数据,但是整个链表的开始。

ListNode* first=new ListNode(1);
head->next=first;

​ 这里我创建了首元节点,并存入了数据1,然后把头节点的next指向了首元,这样就基本串了起来。

对单链表进行操作

取第i个值

Status GetElem(LinkList L,int i,ElemType &e)
{
p=L->next;j=1;
while(p&&j<i)
{
p=p->next;
++j;
}
if(!p||j>1)return 0;
e=p->data;
return 1;
}

这是类C语言描述出来的函数,用e来承接返回来的数据。这个函数还是比较简单的,把它转换为C++语言很容易。

查找某个元素

查找的算法与取值类似,不同之处在于查找到后返回的是地址。不过我感觉这种方法还是有缺陷的,它只能返回查找到的首个数据地址,如果之后还有的话那就查不到了。我认为可以给它改一下,用数组指针来承接每个元素。

插入

插入来说相对难实现一些。假如我们要在第二和第三个节点之间插入一个节点A,应该如何实现呢?

一开始我们要插入的节点其next为nullptr,只存有数据

第一步,让A节点的next指向三,代码为

A->next=second->next;

第二步,让第二个节点的next指向A

second->next=A;

这两步是不能互换的,一换就会出问题。

于是,其完整的算法为

Status ListInsert(ListNode &L,int i,ElemType e)
{
    p=L;j=0;
    while(p&&(j<i-1))
    {p=p->next;++j;}
    if(!p||j>i-1)return error;
    s=new LNode(e);
    s->next=p->next;
    p->next=s;
    return OK;
}
    

展示一下我写的一个很简单的C++代码

int insert(ListNode* head,int e,int i)
{
	int j=0;ListNode* p=head;
	while(p->next!=nullptr&&j<i-1)
	{
		p=p->next;
		j++;
	}
	ListNode* s;
	s=new ListNode(e);
	s->next=p->next;
	p->next=s;
	return 1;
}

这段代码基本上实现了简单的插入,当然其健壮性不高。

删除

删除单链表中的一个节点,我们仅需让该节点的前驱指向该节点的后继,然后再把该节点的next改为nullptr。但这样操作后节点所占内存还是存在的,我们要想办法把它给释放掉。我们一般把要删除的节点的地址保存在一个临时的q中,然后C++中通常用delete删除。这个算法个人感觉比较简单,因此不再赘述。

创建单链表

前面研究这些操作时我创建了first,second等结构体指针来作为节点。但这样子不仅效率不高而且与顺序表没有本质区别,因此必须寻求一种高效的方法。

前插法

void CreateList_H(LinkList &L,int n)
{
L=new LNode;
L->next=NULL;
for(int i=0;i<n;i++)
{
p=new LNode;
cin>>p->data;
p->next=L->next;L->next=p;
}
}

​ 这个算法还是容易理解的,我们要在L后插入n个节点,每次都要创建一个新的节点,让它的next变为L的next(即上一个p的next),然后让L的next变为这个p。

​ 这个可以这么理解,在初始的L后面还存在着一个NULL节点,每次操作都相当于在NULL和NULL之前的节点之间插入一个节点。

​ 前插法中数据的顺序并不是按照输入顺序来的

后插法

后插法数据的顺序就是按照输入顺序来的了。

L=new LNode;
L->next=NULL;
r=L;
for(int i=0;i<n;++i)
{
p=new LNode;
cin>>p->data;
p->next=NULL;r->next=p;
r=p;
}

不同的是后插法需要辅助节点,该辅助节点始终指向链表的最后一个元素

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值