当前位置:首页 » 存储配置 » 从存储和数据判断串的特殊性

从存储和数据判断串的特殊性

发布时间: 2023-02-14 08:10:49

❶ 长度为n的链队列用单循环链表表示,若只设头指针,则怎样进行入队和出队操作;若只设尾指针呢

就行了,准过!
第一章:绪论
1.1:数据结构课程的任务是:讨论数据的各种逻辑结构、在计算机中的存储结构以及各种操作的算法设计。

1.2:数据:是客观描述事物的数字、字符以及所有的能输入到计算机中并能被计算机接收的各种集合的统称。

数据元素:表示一个事物的一组数据称作是一个数据元素,是数据的基本单位。

数据项:是数据元素中有独立含义的、不可分割的最小标识单位。

数据结构概念包含三个方面:数据的逻辑结构、数据的存储结构的数据的操作。

1.3数据的逻辑结构指数据元素之间的逻辑关系,用一个数据元素的集合定义在此集合上的若干关系来表示,数据结构可以分为三种:线性结构、树结构和图。

1.4:数据元素及其关系在计算机中的存储表示称为数据的存储结构,也称为物理结构。

数据的存储结构基本形式有两种:顺序存储结构和链式存储结构。

2.1:算法:一个算法是一个有穷规则的集合,其规则确定一个解决某一特定类型问题的操作序列。算法规则需满足以下五个特性:

输入——算法有零个或多个输入数据。
输出——算法有一个或多个输出数据,与输入数据有某种特定关系。
有穷性——算法必须在执行又穷步之后结束。
确定性——算法的每个步骤必须含义明确,无二义性。
可行性——算法的每步操作必须是基本的,它们的原则上都能够精确地进行,用笔和纸做有穷次就可以完成。
有穷性和可行性是算法最重要的两个特征。

2.2:算法与数据结构:算法建立数据结构之上,对数据结构的操作需用算法来描述。

算法设计依赖数据的逻辑结构,算法实现依赖数据结构的存储结构。

2.3:算法的设计应满足五个目标:

正确性:算法应确切的满足应用问题的需求,这是算法设计的基本目标。
健壮性:即使输入数据不合适,算法也能做出适当的处理,不会导致不可控结
高时间效率:算法的执行时间越短,时间效率越高。 果。
高空间效率:算法执行时占用的存储空间越少,空间效率越高。
可读性:算法的可读性有利于人们对算法的理解。
2.4:度量算法的时间效率,时间复杂度,(课本39页)。

2.5:递归定义:即用一个概念本身直接或间接地定义它自己。递归定义有两个条件:

至少有一条初始定义是非递归的,如1!=1.
由已知函数值逐步递推计算出未知函数值,如用(n-1)!定义n!。
第二章:线性表
1.1线性表:线性表是由n(n>=0)个类型相同的数据元素a0,a1,a2,…an-1,组成的有限序列,记作: LinearList = (a0,a1,a2,…an-1)

其中,元素ai可以是整数、浮点数、字符、也可以是对象。n是线性表的元素个数,成为线性表长度。若n=0,则LinearList为空表。若n>0,则a0没有前驱元素,an-1没有后继元素,ai(0<i<n-1)有且仅有一个直接前驱元素ai-1和一个直接后继元素ai+1。

1.2线性表的顺序存储是用一组连续的内存单元依次存放线性表的数据元素,元素在内存的物理存储次序与它们在线性表中的逻辑次序相同。

线性表的数据元素数据同一种数据类型,设每个元素占用c字节,a0的存储地址为

Loc(a0),则ai的存储地址Loc(ai)为:Loc(ai) = Loc(a0)+ i*c

数组是顺序存储的随机存储结构,它占用一组连续的存储单元,通过下标识别元素,元素地址是下标的线性函数。

1.3:顺序表的插入和删除操作要移动数据元素。平均移动次数是 属数据表长度的一半。(课本第50页)

1.4:线性表的链式存储是用若干地址分散的存储单元存储数据元素,逻辑上相邻的数据元素在物理位置上不一定相邻,必须采用附加信息表示数据元素之间的顺序关系。

它有两个域组成:数据域和地址域。通常成为节点。(课本第55页及56页)

1.5单链表(课本56页)

单链表的遍历:Node<E> p = head; while(p!=null)

单链表的插入和删除操作非常简便,只要改变节点间的链接关系,不需移动数据元素。

单链表的插入操作:1):空表插入/头插入 2)中间插入/尾插入

if(head == null) Node<E> q = new Node<E>(x);

{ head = new Node<E>(x); q.next = p.next;

}else{ p.next = q;

Node<E> q=new Node<E>(x); 中间插入或尾插入都不会改变单表

q.next = head; 的头指针head。

head = q;

}

单链表的删除操作:

头删除:head = head.next;
中间/尾删除:if(p.next!=null)
循环单链表:如果单链表最后一个节点的next链保存单链表的头指针head值,则该单链表成为环形结构,称为循环单链表。(课本67)

若rear是单链表的尾指针,则执行(rear.next=head;)语句,使单链表成为一条循环单链表。当head.next==head时,循环单链表为空。

1.6:双链表结构:双链表的每个结点有两个链域,分别指向它的前驱和后继结点,

当head.next==null时,双链表为空。

设p指向双链表中非两端的某个结点,则成立下列关系:p=p.next.prev=p.prev.next。

双链表的插入和删除:1)插入 2)删除

q=new DLinkNode(x); p.prev.next = p.next;

q.prev=p.prev;q.next =p; if(p.next=null){

p.prev.next = q;p.prev=q; (p.next).prev = p.prev;}

循环双链表:当head.next==head且head.prev==head时,循环双链表为空。

第三章:栈和队列
1.1栈:栈是一种特殊的线性表,其中插入和删除操作只允许在线性表的一端进行。允许操作的一端称为栈顶,不允许操作的一端称为栈底。栈有顺序栈和链式栈。

栈中插入元素的操作称为入栈,删除元素的操作称为出栈。没有元素的中称为空栈。

栈的进出栈顺序:后进先出,先进后出。(及75页的思考题)。

1.2:队列:队列是一种特殊的线性表,其中插入和删除操作分别在线性表的两端进行。

向队列中插入元素的过程称为入队,删除元素的过程称为出对,允许入队的一端称为队尾,允许出队的一端称为对头。没有元素的队列称为空队列。队列是先进先出。

第四章:串
1.1:串是一种特殊的线性表,其特殊性在于线性表中的每个元素是一个字符。一个串记为: s=“s0s1s2…sn-1” 其中n>=0,s是串名,一对双引号括起来的字符序列s0s1s2…sn-1是串值,si(i=0,1,2,…n-1)为特定字符集合中的一个字符。一个串中包含的字符个数称为串的长度。

长度为0的串称为空串,记作“”,而由一个或多个空格字符构成的字符串称为空格串。

子串:由串s中任意连续字符组成的一个子序列sub称为s的子串,s称为sub的主串。子串的序号是指该子串的第一个字符在主串中的序号。

串比较:两个串可比较是否相等,也可比较大小。两个串(子串)相等的充要条件是两个串(子串)的长度相同,并且各对应位置上的字符也相同。

两个串的大小由对应位置的第一个不同字符的大小决定,字符比较次序是从头开始依次向后。当两个串长度不等而对应位置的字符都相同时,较长的串定义为较“大”。

第五章:数组和广义表
1.1:数组是一种数据结构,数据元素具有相同的数据类型。一维数组的逻辑结构是线性表,多维数组是线性表的扩展。

1.2:一维数组:一维数组采用顺序存储结构。一个一维数组占用一组连续的存储单元。

设数组第一个元素a0的存储地址为Loc(a0),每个元素占用c字节,则数组其他元素ai的存储地址Loc(ai)为: Loc(ai)= Loc(a0)+i*c

数组通过下标识别元素,元素地址是下标的线性函数。一个下标能够唯一确定一个元素,所划给的时间是O(1)。因此数组是随机存取结构,这是数组最大的优点。

1.3:多维数组的遍历:有两种次序:行主序和列主序。

行主序:以行为主序,按行递增访问数组元素,访问完第i行的所有元素之后再访问第i+1行的元素,同一行上按列递增访问数组元素。
a00,a01,…a0(n-1), a10,a11,…a1(n-1),…a(m-1)0,a(m-1)1,…,a(m-1)(n-1)

2)列主序:以列为主序,按列递增访问数组元素,访问完第j列的所有元素之后再访问第j+1列的元素,同一列上按列递增访问数组元素。

多维数组的存储结构:多维数组也是由多个一维数组组合而成,组合方式有一下两种。

静态多维数组的顺序存储结构:可按行主序和列主序进行顺序存储。
按行主序存储时,元素aij的地址为:Loc(aij)= Loc(a00)+(i*n+j)*c

按列主序存储时,Loc(aij)= Loc(a00)+(j*m+i)*c

动态多维数组的存储结构。
二维数组元素地址就是两个下标的线性函数。无论采用哪种存储结构,多维数组都是基于一维数组的,因此也只能进行赋值、取值两种存取操作,不能进行插入,删除操作。

第六章:

树是数据元素(结点)之间具有层次关系的非线性结构。在树结构中,除根以外的结点只有一个直接前驱结点,可以有零至多个直接后继结点。根没有前驱结点。

树是由n(n>=0)个结点组成的有限集合(树中元素通常称为结点)。N=0的树称为空树;n>0大的树T;

@有一个特殊的结点称为根结点,它只有后继结点,没有前驱结点。

@除根结点之外的其他结点分为m(m>=0)个互不相交的集合T0,T1,T3……..,Tm-1,其中每个集合Ti(0<=i<m)本身又是一棵树,称为根的子树。

树是递归定义的。结点是树大的基本单位,若干个结点组成一棵子树,若干棵互不相交的子树组成一棵树。树的每个结点都是该树中某一棵子树的根。因此,树是由结点组成的、结点之间具有层次关系大的非线性结构。

结点的前驱结点称为其父母结点,反之,结点大的后继结点称为其孩子结点。一棵树中,只有根结点没有父母结点,其他结点有且仅有一个父母结点。

拥有同一个父母结点的多个结点之间称为兄弟结点。结点的祖先是指从根结点到其父母结点所经过大的所有结点。结点的后代是指该结点的所有孩子结点,以及孩子的孩子等。

结点的度是结点所拥有子树的棵数。度为0的结点称为叶子结点,又叫终端结点;树中除叶子结点之外的其他结点称为分支结点,又叫非叶子结点或非终端结点。树的度是指树中各结点度的最大值。

结点的层次属性反应结点处于树中的层次位置。约定根结点的层次为1,其他结点的层次是其父母结点的层次加1。显然,兄弟结点的层次相同。

树的高度或深度是树中结点的最大层次树。

设树中x结点是y结点的父母结点,有序对(x,y)称为连接这两个结点的分支,也称为边。

设(X0,X1,….,Xk-1)是由树中结点组成的一个序列,且(Xi,Xi+1)(0<=i<k-1)都是树中的边,则该序列称为从X0到Xk-1的一条路径。路径长度为路径上的边数。

在树的定义中,结点的子树T0,T1…..,Tm-1之间没有次序,可以交换位置,称为无序树,简称树。如果结点的子树T0,T1……,Tm-1从左到右是有次序的,不能交换位置,则 称该树为有序树。

森林是m(m>=0)棵互不相干的树的集合。给森林加上一个根结点就变成一棵树,将树的根节点删除就变成森林。

二叉树的性质1:若根结点的层次为1,则二叉树第i层最多有2 的i-1次方(i>=1)个结点。

二叉树的性质2:在高度为k的二叉树中,最多有2的k次方减一个结点。

二叉树的性质3:设一棵二叉树的叶子结点数为n0,2度结点数为n2,则n0=n2+1。

一棵高度为k的满二叉树是具有2的k次方减一个结点的二叉树。满二叉树中每一层的结点数目都达到最大值。对满二叉树的结点进行连续编号,约定根节点的序号为0,从根节点开始,自上而下,每层自左至右编号。

一棵具有n个结点高度为k的二叉树,如果他的每个节点都与高度为k的满二叉树中序号为0~n-1

的结点一一对应,则这棵二叉树为为完全二叉树。

满二叉树是完全二叉树,而完全二叉树不一定是满二叉树。完全二叉树的第1~k-1层是满二叉树第k层不满,并且该层所有结点必须集中在该层左边的若干位置上。

二叉树的性质4:一棵具有n个结点的完全二叉树,其高度k=log2n的绝对值+1

二叉树的性质5:一棵具有n个结点的完全二叉树,对序号为i的结点,有

@若i=0,则i为根节点,无父母结点;若i>0,则i的父母结点的序号为[(i-1)/2]。

@若2i+1<n,则i的左孩子结点序号为2i+1;否则i无左孩子。

@若2i+2<n,则i的右孩子结点的序号为2i+2,否则i无右孩子。

二叉树的遍历

二叉树的遍历是按照一定规则和次序访问二叉树中的所有结点,并且每个结点仅被访问一次。

二叉树的三种次序遍历

1:先根次序;访问根节点,遍历左子树,遍历右子树。

2:中根次序;遍历左子树,访问右子树,遍历右子树。

3:后根次序;遍历左子树,遍历右子树,访问根节点。

先根次序遍历时,最先访问根节点;后根次序遍历时,最后访问根节点;中根次序遍历时,左子树上的结点在根节点之前访问,右子树上的结点在根节点之后访问。

二叉树的插入和删除操作P147

二叉树的层次遍历P149

习题P167 6—10,6—19

第七章

图是由定点集合及顶点间的关系集合组成的一种数据关边系。顶点之间的关系成为边。一个图G记为G=(V,E),V是顶点A的有限集合,E是边的有限集合。即 V=

E=或E=其中Path(A,B)表示从顶点A到B的一条单向通路,即Path(A,B)是有方向的。

无向图中的边事没有方向,每条边用两个顶点的无序对表示。

有向图中的边是有方向,每条边用两个顶点的有序对表示。

完全图指图的边数达到最大值。n个顶点的完全图记为Kn。无向完全图Kn的边数为n*(n-1)/2,有向完全图Kn的边数为n*(n-1)。

子图:设图G==(V,E),G’=(V’,E’),若V’包含于V且E’包含于E,则称图G’是G的子图。若G’是G的真子图。

连通图:在无向图G中,若从顶点VI到Vj有路径,则称Vi和Vj是联通的。若图G中任意一对顶点Vi和Vj(Vi不等于Vj)都是联通的,则称G为连通图。非连通图的极大联通子图称为该图的联通分量。

强连通图:在有向图中,若在每一对顶点Vi和Vj(Vi不等于Vj)之间都存在一条从Vi到Vj的路径,也存在一条从Vi到Vj的路径,也存在一条从Vi到Vj的路径,则称该图的强连通图。非强连通图的极大强连通子图称为该图的强连通图分量。

图的遍历

遍历图是指从图G中任意一个顶点V出发,沿着图中的边前行,到达并访问图中的所有顶点,且每个顶点仅被访问一次。遍历图要考虑一下三个问题:

@指定遍历的第一个访问顶点

@由于一个顶点可能与多个顶点相邻,因此要在多个邻接顶点之间约定一种访问次序。

@由于图中可能存在回路,在访问某个顶点之后,可能沿着某条路径又回到该顶点。

深度优先搜索

图的深度优先搜索策略是,访问某个顶点v,接着寻找v的另一个未被访问的邻接顶点w访问,如此反复执行,走过一条较长路径到达最远顶点;若顶点v没有未被访问的其他邻接顶点,则回到前一个被访问顶点,再寻找其他访问路径。

图的深度优先搜索遍历算法P188

联通的无回路的无向图,简称树。树中的悬挂点又成为树叶,其他顶点称为分支点。各连通分量均为树的图称为森林,树是森林。

由于树中无回路,因此树中必定无自身环也无重边(否则他有回路)若去掉树中的任意一条边,则变成森林,成为非联通图;若给树加上一条边,形成图中的一条回路,则不是树。P191

生成树和生成森林:

一个连通无向图的生成树是该图的一个极小联通生成子图,它包含原图中所有顶点(n个)以及足以构成一棵树的n-1条边。

一个非联通的无向图,其各连通图分量的生成图组成该图的生成森林。

图的生成图或生成森林不是唯一的,从不同顶点开始、采用不同遍历可以得到不同的生成树或森林。

在生成树中,任何树中,任何两个顶点之间只有唯一的一条路径。

第八章

折半查找算法描述 P206,P207

二叉排序树及其查找:

二叉排序树或者是一棵空树;或者是具有下列性质的二叉树:

@每个结点都有一个作为查找依据的关键字,所有结点的关键字互不相同。

@若一个结点的左子树不空,则左子树上所有结点的关键字均小于这个节点的关键字;

@每个结点的左右子树也分别为二叉排序树。

在一棵二叉排序树中,查找值为value的结点,算法描述如下:

@从根结点开始,设p指向根结点

@将value与p结点的关键字进行比较,若两者相等,则查找成功;若value值较小,则在p的左子树中继续查找;若value值较大,则在p的右子树中继续查找。

@重复执行上一步,直到查找成功或p为空,若p为空,则查找不成功。

习题 8-6

第九章

直接插入排序算法描述:p228

冒泡排序算法的描述:p232

快速排序算法描述p233

直接选择排序算法描述p236

直接选择排序算法实现如下:

Public static void selectSort(int[]table){

for(int i=0;i<table.length-1;i++){

int min=I;

for(int j=i+1;j<table.length;j++){

if(table[j]<table[min])

min=j;

if(min!=i){

int temp=table[i];

table[i]==table[min];

table[min]=temp;

}

}

}

}

堆排序是完全二叉树的应用,是充分利用完全二叉树特性的一种选择排序。

堆定义:设n个元素的数据序列,当且仅当满足下列关系

k1<=k2i+1且ki<=k2i+2 i=0,1,2,3,….,[n/2-1]

或ki>==k2i+1且ki>=2i+2i=0,1,2,3,…..[n/2-1]时,序列称为最小堆或最大堆。将最小(大)堆看成是一颗完全二叉树的层次遍历序列,则任意一个结点的关键字都小于等于(大于等于)它的孩子节点的关键字值,由此可知,根结点值最小(大)。根据二叉树的性质5,完全二叉树中的第i(0<=i<n)个结点,如果有孩子,则左孩子为第2i+1个结点,右孩子为第2i+2个结点。

希望对你会有所帮助。

❷ 408数据结构可以写汉字吗

408数据结构(全)
一个数据元素可由若干数据项组成,数据项是构成数据元素的不可分割的最小单位。所以可以写汉字!!!

❸ 对于字符串computer七长度为四的字串共有几个

4.1 串的定义和实现

穿的定义是有零个或者多个字符组成的有限序列,串中字符的个数称为串的长度,n=0的时候串称为空串。串中任意连续的字符组成的子序列称为该串的子串。

串和线性表在逻辑结构上十分相似,但是基本操作上有很大区别,线性表的基本操作主要是以单个元素作为操作对象,但是串的基本操作通常以子串作为操作对象。

串的存储结构

1.定长顺序存储表示

类似于线性表的顺序存储结构

#define MAXSIZE 255

typedef struct{

​ char ch[MAXSIZE];

​ int length;}

超过预定一长度的串值会被舍去,称之为截断

2.堆分配存储表示

堆分配存储仍然以一组地址连续的存储单元存放串值的字符序列,但是他们的存储空间是在执行过程中动态分配得到的。

3.块链存储表示

类似于线性表的链式存储结构,也可以采用链表方式存储串值。由于串的特殊性,在具体实现的时候,可以在每个节点存放一个字符或者多个字符。
TIPS:在字符串中,可以将char[0]设定为存储长度的元素,但是最多只能表示255;也可以使用\0表示字符串结尾,但是想要获取长度需要遍历整个串

4.2 串的模式匹配

简单的模式匹配算法

子串的定位操作称为串的模式匹配,其中简单的模式匹配算法是一种不依赖其他串操作的暴力匹配算法。其算法思想是,将主串中和模式串等长的子串全部提取出来,并且依次对比。

暴力模式匹配算法的最坏时间复杂度为O(nm),最好的时间复杂度为O(m),其中n,m分别为主串和模式串的长度。

改进的模式匹配算法——KMP算法

在暴力匹配算法中,每次匹配失败都是后移一位再从头开始比较,但是比如:

在 a b a b c a b c a c 中查找abcac

这会导致一定的重复比较,从而导致效率下降(展开说)

1.字符串的前缀、后缀和部分匹配值

前缀指的是出最后一个字符外所有的头部子串,后缀指的是除第一个字符外字符串的所有尾部子串;部分匹配值为字符串的前缀和后缀的最长相等前后缀长度。

在对比到第k个字符时,如果发生了串不匹配,可以寻找已匹配的串的最大公共前后缀,从而使得不需要重复对比。

在一个有n个字符的串中,可能存在n种匹配失败的情景,对应的是n种部分匹配串。每一种部分匹配串的最大前后缀是固定的,因此可以提前计算出对比到k个字符错配时主串需要前进的步数,并且将其存储在next数组中。这样在KMP算法执行时,可以直接使用

重点:next数组的计算

最长相等前后缀长度可以使得主串不需要回退,故KMP算法可以在O(n+m)的时间数量级上完成串的模式匹配操作,提高了模式匹配效率。其中,O(m)的时间复杂度是在求next数组时产生的,O(n)的时间复杂度是在执行KMP算法时产生的。

总的来说,相对于朴素模式匹配算法,KMP算法能够避免主串指针频繁回溯,从而提高了效率

2.KMP算法的原理是什么

当子串与扫描到的主串不匹配的时候,首先计算出已匹配的子串的前缀和后缀的最大公共子集。然后可以将子串向后移动,将共有前缀移动到原子集的共有后缀处,从而避免重复查找,使得子串不需要回退。

右移位数 = 已匹配的字符数 - 对应的部分字符值

3.KMP算法的进一步优化
KMP算法在对比诸如"aaaab"这类串的时候,还是会出现重复匹配的问题,为了解决而需要在next数组的基础上再进一步处理得到nextval数组

❹ 数据结构中关于串的一个简单问题

在这里定义的两个串:S1和T 如果可以执行T[1..S1[0]] = S1[1..S1[0]];
这条语句,那么就表示该串是顺序存储的串,就想数组一样的顺序存储方式,并且在该顺序结构的第一个存储单元中,存储的是该存储串的存储单元的大小,所以该语句应该是:T[1..T[0]] = S1[1..S1[0]]; 表示的是,将S1中的所有内容按照下表数的对应放入到T串中,并且,两个顺序串的存储空间大小最好一样!呵呵。。。。。。在定义该串的结构的时候进行设定就行了!

❺ 比较字符串的问题字符串到底是怎么储存的

耐心的把下面的看完你就明白了:

简单的说:
java把内存划分成两种:一种是栈内存,一种是堆内存。

在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。

当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

堆内存用来存放由new创建的对象和数组。

在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。

引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

具体的说:
栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。

比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的。

String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的方式是生成不同的对象。每一次生成一个。
因此用第一种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。
另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

java中内存分配策略及堆和栈的比较
2.1 内存分配策略
按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.
静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.
栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放.

2.2 堆和栈的比较
上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:
从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的.而这种不同又主要是由于堆和栈的特点决定的:
编程中,例如C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程序运行时进行的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时.
堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.但是堆的优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。事实上,面向对象的多态性,堆内存分配是必不可少的,因为多态变量所需的存储空间只有在运行时创建了对象之后才能确定.在C++中,要求创建一个对象时,只需用 new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存.当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!这也正是导致我们刚才所说的效率低的原因,看来列宁同志说的好,人的优点往往也是人的缺点,人的缺点往往也是人的优点(晕~).

2.3 JVM中的堆和栈
JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的 Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译原理中的活动纪录的概念是差不多的.
从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。

❻ 串是一种特殊的线性表,其特殊性表现在

数据元素是一个字符

❼ 关于串的问题

1,B
2,
3,C
5,A

c语言数据结构(顺序存储字符串,判断字符串是否对称,借助链栈)

#include <stdio.h>
#include <malloc.h>
#include <conio.h>
typedef struct SNode
{
int data;
struct SNode *next;

}SNode,*LinkStack;
int Push(LinkStack &top,char e)
{
SNode *q;
q=(LinkStack)malloc(sizeof(SNode));
if(!q)
{
printf("\nOverflow!");
return 0;
}
q->data=e;
q->next=top->next;
top->next=q;
return 1;
}
char Pop(LinkStack &top,char &e)
{
SNode *q;
if(!top->next)
{
return 0;
}
q=top->next;
top->next=q->next;
e=q->data;
free(q);
return e;
}
char GetTop(LinkStack top,char &e)
{
e=top->next->data;
return e;
}
int Check(char * ch)
{
int i,m,flg=0;
char *c;
char temp;
SNode *top;
top=(LinkStack)malloc(sizeof(SNode));
top->next=NULL;
for(m=1;ch[m]!='\0';m++);
for(i=0;i<m/2;i++)
{
Push(top,ch[i]);
}
if(m%2)
i++;
while(i<m)
{
if(ch[i]==GetTop(top,temp))
Pop(top,temp);
else
return 0;
i++;
}
return 1;
}
void main()
{
char c[40];
printf("输入字符串: ");
scanf("%s",c);
if(Check(c))
printf("\n字符串对称");
else
printf("\n字符串不对称");
getch();
}

❾ 数据结构串的基本操作的实现

希望下面这个程序符合你的要求,呵呵#include<iostream>#include<malloc.h>#define OK 1#define ERROR 0using namespace std;typedef struct{ char *ch; int length; //串的长度}HString;//========= int StrAssign(HString &T){//生成一个串常量 int j; cout<<"请输入串T的长度:"<<endl; cout<<"T.length="; cin>>T.length; cout<<"请输入串:"<<endl; if(!T.length){T.ch=NULL;T.length=0;} else{ if(!(T.ch=(char*)malloc(T.length*sizeof(char)))) return ERROR; for(j=0;j<T.length;j++) cin>>T.ch[j]; } return OK;} //串的链接======= int Concat(HString &T){ int i,j; HString S1; HString S2; if(T.ch) free(T.ch); StrAssign(S1); StrAssign(S2); if(!(T.ch=(char*)malloc((S1.length+S2.length)*sizeof(char)))) return ERROR; for(i=0;i<S1.length;i++) T.ch[i]=S1.ch[i]; T.length=S1.length+S2.length; for(i=S1.length,j=0;i<T.length,j<S2.length;i++,j++) T.ch[i]=S2.ch[j]; return OK;} //串的插入======== int StrInsert(HString &T) //在串的T第pos个字符之前插入串S{ int i,j,k,pos; HString S; cout<<"请输入串S的长度:"; cin>>S.length; cout<<"请输入串S:"<<endl; if(!(S.ch=(char*)malloc(S.length*sizeof(char)))) return ERROR; for(i=0;i<S.length;i++) cin>>S.ch[i]; cout<<"请输入插入的位置:"; cin>>pos; if(pos<1||pos>T.length+1) return ERROR; if(S.length) { if(!(T.ch=(char*)realloc(T.ch,(T.length+S.length)*sizeof(char)))) return ERROR; for(i=T.length-1;i>=pos-1;i--) T.ch[i+S.length]=T.ch[i]; for(j=pos-1,k=0;j<=pos+S.length-2,k<S.length;j++,k++) T.ch[j]=S.ch[k]; T.length+=S.length; } return OK;} //串的输出========== void print(HString &T){ int i; for(i=0;i<T.length;i++) cout<<" "<<T.ch[i];} //主函数=========== void main(){ cout<<"=============串的堆分配存储表示=============="<<endl; HString T; StrAssign(T); cout<<"您输入有效串为:"<<endl; print(T); cout<<endl; cout<<"==========串连接操作=========="<<endl<<endl; Concat(T); cout<<"连接后的串为:"<<endl; print(T); cout<<endl; cout<<"==========串插入操作=========="<<endl<<endl; StrInsert(T); cout<<"插入后的串为:"<<endl; print(T); cout<<endl; }

❿ 串和字符的存储结构有什么不同串通常采用什么存储结构

1、所有数据在计算机中,存放的均是二进制串,只有不同类型的数据在读写时按照读写的方式不同;
2、c++中的string类型是类对象,字符串是
char类型的数组,char则是更基本的类型。如果不懂类对象与char数组的区别的话,可以取了解一下c++的类。对于字符串与字符的区别的话,那就基本是批发与零售的区别了。

热点内容
密码器动态密码怎么弄 发布:2025-07-14 00:44:27 浏览:384
小米怎么把视频加密 发布:2025-07-14 00:42:59 浏览:405
在线申诉找回密码根本什么都没有 发布:2025-07-14 00:41:22 浏览:306
拉新用什么安卓手机可以 发布:2025-07-14 00:41:19 浏览:418
androidhome键退出 发布:2025-07-14 00:30:03 浏览:506
我都世界模组反编译教程 发布:2025-07-14 00:29:45 浏览:646
法因数控钻床编程手册 发布:2025-07-14 00:18:26 浏览:490
gcc编译怎么知道错误的行数 发布:2025-07-14 00:06:21 浏览:383
压强算法 发布:2025-07-14 00:02:52 浏览:552
dns怎么配置端口 发布:2025-07-13 23:49:16 浏览:761