线性表:零个或多个数据元素的有限序列。
关于线性表,我们有两个概念需要知道,分别是前驱元素和后驱元素。
这两个概念应用十分广泛,无论是单链表,双向链表,循环链表,还是模拟链表都有用到其中的概念。
线性表的存储形式:
1.顺序存储结构。
2.链式存储结构。
其实第一种就是按照数组存,第二种就是链表存罢了。
第一种更适合于查找而不是插入与删除,在查找中他的时间复杂度为O(1),而在插入或者删除时他的时间复杂度为O(n)。
第二种则相反,更适合于对链表进行操作,但一般情况下它查找的时间复杂度为O(1),删除与插入的时间复杂度为O(n)。
关于单链表的各种操作以及静态链表(就是用数组模拟的链表)在我其他的博客中有,此篇中不再赘述。此篇主要说双向链表以及加入循环链表。
循环链表:将单链表中终端结点的指针由空指针改为指向头节点,这种头尾相接的单链表就被称为单循环链表,简称循环链表。
单循环链表与单链表十分相似,代码内容也很相近,只是将最后的指针指回头结点了而已。在这里我们一般不使用头指针,因为如果要找到最后一个元素的话,需要从头遍历到尾,时间复杂度为O(n)。我们使用尾指针,使用尾指针的好处是可以从尾开始,也可以很快从头开始,此时要遍历到尾部只用一次赋值即可。
从这里可以看出使用尾指针的好处,可是在我们创建链表时,我们只能返回一个指针,但如果我们即想要头指针也想要尾指针该怎么办呢。
这里解释两种办法:1.可以将所定义的指针定义为全局变量。2.可以定义一个结构体,里面存放两种指针。
双向链表:双向链表是在单链表的每个结点中,在设置一个指向前驱指针的指针域。
结构为:
struct node
{
int num;
struct node *last;
struct node *next;
};
我们现在来从单链表开始创建一个普通的双向链表
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include<malloc.h>
#define N sizeof(struct node)
using namespace std;
struct node
{
int num;
struct node *last;
struct node *next;
};
struct node *creat()
{
struct node *p1,*p2,*head;
head