数据结构相关知识总结(绪论,线性表,栈和队列)

注意:事先应判断: 插入位置i 是否合法?表是否已满?

应当符合条件: 1≤i≤n+1 或 i=[1, n+1]

核心语句:

for (j=n; j>=i; j–)

a[j+1]=a[ j ];

a[ i ]=x;

n++;

插入时的平均移动次数为:n(n+1)/2÷(n+1)=n/2≈O(n)

3)删除:删除线性表的第i个位置上的元素

实现步骤:

①将第i+1 至第n 位的元素向前移动一个位置;

②表长减1。

注意:事先需要判断,删除位置i 是否合法?

应当符合条件:1≤i≤n 或 i=[1, n]

核心语句:

{

for ( j=i+1; j<=n; j++ )

a[j-1]=a[j];

n–;

}

顺序表删除一元素的时间效率为:T(n)=(n-1)/2 ≈O(n)

顺序表插入、删除算法的平均空间复杂度为O(1)

5.线性表的链式表示和实现


线性链表:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。

一个数据元素称为一个结点,包括两个域:存储数据元素信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称作指针或链。

由于链表的每个结点中只包含一个指针域,故线性链表又称为单链表。

1)单链表的修改(或读取)

思路:要修改第i个数据元素,必须从头指针起一直找到该结点的指针p,return p;

然后才能:p->data=new_value

读取第i个数据元素的核心语句是:

Linklist *find(Linklist *head ,int i)

{

int j=1;

Linklist *p;

P=head->next;

While((p!=NULL)&&(j<i))

{

p=p->next;

j++;

}

}

2)单链表的插入

在这里插入图片描述

链表插入的核心语句:

Step 1:s->next=p->next;

Step 2:p->next=s;

3)单链表的删除

在这里插入图片描述

删除动作的核心语句(要借助辅助指针变量q):

q = p->next; //首先保存b的指针,靠它才能找到c;

p->next=q->next; //将a、c两结点相连,淘汰b结点;

free(q) ; //彻底释放b结点空间

4)双向链表的插入操作

在这里插入图片描述

设p已指向第i 元素,请在第 i 元素前插入元素 x:

① ai-1的后继从 ai ( 指针是p)变为 x(指针是s) :

s->next = p ; p->prior->next = s ;

② ai 的前驱从ai-1 ( 指针是p->prior)变为 x ( 指针是s);

s->prior = p ->prior ; p->prior = s ;

5)双向链表的删除操作

在这里插入图片描述

设p指向第i 个元素,删除第 i 个 元素

后继方向:ai-1的后继由ai ( 指针p)变为ai+1(指针 p ->next );

p ->prior->next = p->next ;

前驱方向:ai+1的前驱由ai ( 指针p)变为ai-1 (指针 p -> prior );

p->next->prior = p ->prior ;

6.循环链表


循环链表是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。

循环链表的操作和线性链表基本一致,差别仅在于算法中的循环条件不是p或p->next是否为空,而是它们是否等于头指针。

学习重点:

线性表的逻辑结构,指线性表的数据元素间存在着线性关系。在顺序存储结构中,元素存储的先后位置反映出这种线性关系,而在链式存储结构中,是靠指针来反映这种关系的。

顺序存储结构用一维数组表示,给定下标,可以存取相应元素,属于随机存取的存储结构。

链表操作中应注意不要使链意外“断开”。因此,若在某结点前插入一个元素,或删除某元素,必须知道该元素的前驱结点的指针。

掌握通过画出结点图来进行链表(单链表、循环链表等)的生成、插入、删除、遍历等操作。

数组(主要是二维)在以行序/列序为主的存储中的地址计算方法。

补充重点:

每个存储结点都包含两部分:数据域和指针域(链域)

在单链表中,除了首元结点外,任一结点的存储位置由 其直接前驱结点的链域的值 指示。

在链表中设置头结点有什么好处?

头结点即在链表的首元结点之前附设的一个结点,该结点的数据域可以为空,也可存放表长度等附加信息,其作用是为了对链表进行操作时,可以对空表、非空表的情况以及对首元结点进行统一处理,编程更方便。

如何表示空表?

(1)无头结点时,当头指针的值为空时表示空表;

(2)有头结点时,当头结点的指针域为空时表示空表。

链表的数据元素有两个域,不再是简单数据类型,编程时该如何表示?

因每个结点至少有两个分量,且数据类型通常不一致,所以要采用结构数据类型。

sizeof(x)—— 计算变量x的长度(字节数);

malloc(m) — 开辟m字节长度的地址空间,并返回这段空间的首地址;

free§ —— 释放指针p所指变量的存储空间,即彻底删除一个变量。

链表的运算效率分析:

(1)查找

因线性链表只能顺序存取,即在查找时要从头指针找起,查找的时间复杂度为 O(n)。

(2) 插入和删除

因线性链表不需要移动元素,只要修改指针,一般情况下时间复杂度为 O(1)。

但是,如果要在单链表中进行前插或删除操作,因为要从头查找前驱结点,所耗时间复杂度将是 O(n)。

例:在n个结点的单链表中要删除已知结点*P,需找到它的前驱结点的地址,其时间复杂度为 O(n)

顺序存储和链式存储的区别和优缺点?

顺序存储时,逻辑上相邻的数据元素,其物理存放地址也相邻。顺序存储的优点是存储密度大,存储空间利用率高;缺点是插入或删除元素时不方便。

链式存储时,相邻数据元素可随意存放,但所占存储空间分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针。链式存储的优点是插入或删除元素时很方便,使用灵活。缺点是存储密度小,存储空间利用率低。

顺序表适宜于做查找这样的静态操作;

链表宜于做插入、删除这样的动态操作。

若线性表的长度变化不大,且其主要操作是查找,则采用顺序表;

若线性表的长度变化较大,且其主要操作是插入、删除操作,则采用链表。

① 数组中各元素具有统一的类型;

② 数组元素的下标一般具有固定的上界和下界,即数组一旦被定义,它的维数和维界就不再改变。

③数组的基本操作比较简单,除了结构的初始化和销毁之外,只有存取元素和修改元素值的操作。

三元素组表中的每个结点对应于稀疏矩阵的一个非零元素,它包含有三个数据项,分别表示该元素的 行下标 、列下标 和 元素值 。

第三章:栈和队列

=======================================================================

1.栈:


限定仅在表尾进行插入或删除操作的线性表。

栈的基本操作:在栈顶进行插入或删除,栈的初始化、判空及取栈顶元素等。

入栈口诀:堆栈指针top “先压后加”

出栈口诀:堆栈指针top “先减后弹”

top=0表示空栈。

2.栈的表示和实现


1)构造一个空栈S

Status InitStack(SqStack &S)

{

S.base = (SElemType *) malloc(STACK_INIT_SIZE * sizeof(SElemType));

if(!S.base) exit (OVERFLOW); //存储分配失败

S.top = S.base;

S.stacksize = STACK_INIT_SIZE;

return OK;

}

2)返回栈顶元素

Status GetTop(SqStack S, SElemType e)

{//若栈不空,则用e返回S的栈顶元素,并返回OK,否则返回ERROR

if(S.top == S.base) return ERROR;

e = *(S.top-1);

return OK;

}//GetTop

3)顺序栈入栈函数PUSH()

Status Push(SqStack &S, SElemType e)

{ //插入元素e为新的栈顶元素

if(S.top-S.base>=S.stacksize)//栈满,追加存储空间

{

s.base = (SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));

if(!S.base) exit(OVERFLOW);//存储分配失败

S.top = S.base + S.stacksize;

S.stacksize += STACKINCREMENT;

}

*S.top++ =e;

return OK:

}//PUSH

4)顺序栈出栈函数POP()

status Pop( SqStack &S,SElemType &e)

{ //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR

if(S.top == S.base) return ERROR;

e=* —S.top;

return OK;

}

3.栈的应用


数制转换,括号匹配的检验,行编辑程序,迷宫求解,表达式求值,递归实现。

4.队列:


是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素。

允许插入的一端叫做队尾,允许删除的一端叫做队头。

除了栈和队列外,还有一种限定性数据结构是双端队列。双端队列是限定插入和删除操作在表的两端进行的线性表。

5.链队列结点类型定义:


typedef Struct QNode{

QElemType data; //元素

Struct QNode *next; //指向下一结点的指针

}Qnode , * QueuePtr ;

链队列类型定义:

typedef struct {

QueuePtr front ; //队首指针

QueuePtr rear ; //队尾指针

} LinkQueue;

结局:总结+分享

看完美团、字节、腾讯这三家的一二三面试问题,是不是感觉问的特别多,可能咱们真的又得开启面试造火箭、工作拧螺丝的模式去准备下一次的面试了。

开篇有提及我可是足足背下了Java互联网工程师面试1000题,多少还是有点用的呢,换汤不换药,不管面试官怎么问你,抓住本质即可!能读到此处的都是真爱

  • Java互联网工程师面试1000题

image.png

而且从上面三家来看,算法与数据结构是必备不可少的呀,因此我建议大家可以去刷刷这本左程云大佬著作的 《程序员代码面试指南 IT名企算法与数据结构题目最优解》,里面近200道真实出现过的经典代码面试题。

  • 程序员代码面试指南–IT名企算法与数据结构题目最优解

image.png

  • 其余像设计模式,建议可以看看下面这4份PDF(已经整理)

image.png

  • 更多的Java面试学习笔记如下,关于面试这一块,我额外细分出Java基础-中级-高级开发的面试+解析,以及调优笔记等等等。。。

image.png

以上所提及的全部Java面试学习的PDF及笔记,如若皆是你所需要的,那么都可发送给你!

typedef struct {

QueuePtr front ; //队首指针

QueuePtr rear ; //队尾指针

} LinkQueue;

结局:总结+分享

看完美团、字节、腾讯这三家的一二三面试问题,是不是感觉问的特别多,可能咱们真的又得开启面试造火箭、工作拧螺丝的模式去准备下一次的面试了。

开篇有提及我可是足足背下了Java互联网工程师面试1000题,多少还是有点用的呢,换汤不换药,不管面试官怎么问你,抓住本质即可!能读到此处的都是真爱

  • Java互联网工程师面试1000题

[外链图片转存中…(img-CjLTzGO0-1714722946129)]

而且从上面三家来看,算法与数据结构是必备不可少的呀,因此我建议大家可以去刷刷这本左程云大佬著作的 《程序员代码面试指南 IT名企算法与数据结构题目最优解》,里面近200道真实出现过的经典代码面试题。

  • 程序员代码面试指南–IT名企算法与数据结构题目最优解

[外链图片转存中…(img-Xo9W6Czh-1714722946130)]

  • 其余像设计模式,建议可以看看下面这4份PDF(已经整理)

[外链图片转存中…(img-72iTxBgo-1714722946131)]

  • 更多的Java面试学习笔记如下,关于面试这一块,我额外细分出Java基础-中级-高级开发的面试+解析,以及调优笔记等等等。。。

[外链图片转存中…(img-HB3ucnNq-1714722946131)]

以上所提及的全部Java面试学习的PDF及笔记,如若皆是你所需要的,那么都可发送给你!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值