为您推荐:
精华内容
最热下载
问答
  • 5星
    1.77MB m0_52957036 2020-04-19 17:01:47
  • 5星
    55KB m0_52957036 2020-03-02 21:58:14
  • 5星
    6KB thy77 2021-04-15 16:42:43
  • 5星
    441KB weixin_50804226 2021-07-15 22:02:47
  • 5星
    6.75MB weixin_43796045 2021-05-06 15:26:30
  • 5星
    1.11MB shooter7 2021-01-28 19:04:09
  • 5星
    142KB m0_52957036 2020-08-03 00:16:59
  • 5星
    195KB m0_52957036 2020-10-09 23:57:14
  • 5星
    28KB m0_52957036 2020-04-19 21:40:32
  • 270KB weixin_38656400 2020-09-19 08:52:01
  • 20KB olinlino 2009-06-22 11:57:18
  • 串是由0个或多个字符组成的有限序列,又叫字符串。 空串 长度为0的串,不包含任何字符。 空白串 由一个或多个空白字符组成的串。 子串 串的任意个连续字符组成的串子序列。子串的位置是以子串在主串中首次出现...

    串的基本概念

    • 串的定义
      串是由0个或多个字符组成的有限序列,又叫字符串。

    • 空串
      长度为0的串,不包含任何字符。

    • 空白串
      由一个或多个空白字符组成的串。

    • 子串
      串的任意个连续字符组成的串子序列。子串的位置是以子串在主串中首次出现时的第一个字符在主串中的位置来表示。

    • 主串
      包含子串的串相应的叫主串。

    • 串的比较
      串的比较是通过组成串中的字符之间的编码来进行的,而字符的编码指的是字符在字符集中的序号。通过两串字符的比较,若不等,则返回第一个不相等的字符的数值差。
      例: compareTo(str)算法
      若当前串 > str ,则返回值 > 0;
      当前串 < str ,则返回值 < 0;
      当前串 = str ,则返回值 = 0;

    串的接口描述

    串实际是线性表的一种,它与一般的线性表的不同之处是其每个数据元素的类型一定是字符类型,不能是其它类型。

    • 代码实现
    1. 置空
    	//置空
    	public void clear();
    
    1. 判空
    	//判空
    	public boolean isEmpty();
    
    1. 串长度
    	//长度
    	public int length();
    
    1. 提取字符
    	//提取字符
    	public char charAt(int index)throws Exception;
    
    1. 截取字符
    	//截取子串
    	//0≤begin≤length()-1 ,1≤end≤length()
    	public IString subString(int begin,int end)throws Exception;
    
    1. 串的插入
    	//串的插入:在当前串中第offset个字符之前插入串str
    	public IString insert(int offset, IString str)throws Exception;
    
    1. 串的删除
    	//串的删除:当前串中删除从begin到end-1之间的子串,并返回当前串对象。 
    	//0≤begin≤length()-1 ,1≤end≤length()
    	public IString delect(int begin, int end);
    
    1. 串的比较
    	//串的比较:当前串大于str,返回值大于0,小于则返回小于0,等于则返回=0.
    	public int compareTo(IString str)throws Exception;	
    
    1. 子串的定位
    	//子串的定位:从begin位置(0<begin<length-1)查找与非空串str相等的子串,返回str在当前串的位置。
    	public int indexOf(IString str, int begin)throws Exception;
    
    1. 串的连接
    	//连接操作:把str串连接到当前串的后面
    	public IString concat(IString str) throws Exception;
    

    串的存储结构

    串的顺序存储结构

    串的顺序存储结构是采用一组地址连续的存储单元来存储字符串序列的。我们可以使用一个字符数组strValue来存放字符串的串值,curlen变量用来存放当前长度。

    串的链式存储结构

    串的链式存储结构可以采用单链表来存储串值。下图为串的链式存储结构的两种方式:
    链式存储
    上图可以发现,

    (a)的存储方式中
    优点: 插入和删除的效率是非常方便的。
    缺点: 当有大量的字符串时,它的存储效率是很低的。

    (b)的存储方式中
    串所占的最后一个结点的data域不一定被串值占满,用如图符号补上。
    优点: 该方式的存储效率是有所提高。
    缺点: 该方式的插入和删除效率是很低的,因为你需要把插入字符的指针指向下一个字符,但是,每一个结点存储的又是4个串值,如果存储超过4个串值,则在这个过程中就需要移动大量字符了,非常不方便,而且查询效率也是非常低的。
    所以根据实际需求,选择更为合理的存储结构。

    顺序串的实现

    1. 顺序串类定义及构造方法
    package seqstring;
    //顺序串
    public class SeqString implements IString{
    	public char[] strValue;
    	public int curlen;
    	//无参构造方法
    	public SeqString() {
    		strValue = new char[0];
    		curlen = 0;
    	}
    	//以字符串常量构造串对象
    	public SeqString(String str) {
    		char[] temp = str.toCharArray();	//把str的每一个子串赋给字符数组temp
    		strValue = temp;
    		curlen = temp.length;
    	}
    	//以字符数组构造串对象
    	public SeqString(char[] value) {
    		this.strValue = new char[value.length];		//定义长度为value字符数组长度的strVlue数组
    		for(int i = 0; i < value.length; i++) {		//复制
    			this.strValue[i] = value[i];
    		}
    		curlen = value.length;						//更新当前长度
    	}
    
    1. 置空、判空、长度操作
    	public void clear() {
    		this.curlen = 0;
    	}
    	public boolean isEmpty() {
    		return curlen == 0;
    	}
    	public int length() {
    		return curlen;
    	}
    
    1. 返回字符中序列为index的字符操作、扩容操作:方便后续子串插入时空间不够的操作
    	//返回字符中序列为index的字符
    	public char charAt(int index)throws Exception {
    		if(index <0 || index >= curlen) {
    			throw new Exception("输入的索引不正确!");
    		}
    		return strValue[index];
    	}
    	
    	//扩充存储字符串的存储空间,参数为指定参数
    	public void allocate(int newCapacity) {
    		char[] temp = strValue;
    		strValue = new char[newCapacity];
    		for(int i = 0;i < temp.length;i++) {
    			strValue[i] = temp[i];
    		}
    	}
    
    1. 截取字符串操作
      图解:
      截取begin位置到end位置的字符串,返回串中序列从begin到end-1的子串。
      截取字符串
      代码实现:
    	//返回串中序列从begin到end-1的子串
    	public IString subString(int begin,int end) {
    		if(begin<0) {
    			throw new StringIndexOutOfBoundsException("起始位置不能小于0!");
    		}
    		if(end>curlen) {
    			throw new StringIndexOutOfBoundsException("结束位置不能大于串的当前的长度!");
    		}
    		if(begin>end) {
    			throw new StringIndexOutOfBoundsException("开始位置不能大于结束位置!");
    		}
    		if(begin == 0&& end == curlen) {
    			return this;
    		}
    		char[] buffer = new char[end - begin];
    		for(int i = 0;i < buffer.length;i++) {
    			buffer[i] = this.strValue[i+begin]; 
    		}
    		return new SeqString(buffer);
    	}
    
    1. 字符串的插入操作
      图解:
      串的插入
      代码实现:
    	//讲str串插入到strValue中的从offset开始的位置
    	public IString insert(int offset,IString str) throws Exception {
    		if((offset<0)||(offset>this.curlen)) {
    			throw new StringIndexOutOfBoundsException("插入的位置不合法!");
    		}
    		int len = str.length();
    		int newCount = this.curlen + len;
    		if(newCount > strValue.length) {			//空间不足,需扩容
    			allocate(newCount);
    		}
    		for(int i=curlen-1;i>=offset;i--) {			//从offset开始后移len个字符
    			strValue[len+i] = strValue[i];
    		}	
    		for(int i=0;i<len;i++) {				 	//复制串str
    			strValue[offset+i] = str.charAt(i);
    		}
    		this.curlen = newCount;
    		return this;
    		
    	}
    
    1. 字符串的删除操作
      图解:
      串的删除
      代码实现:
    	//删除当前串中从序号begin到end-1的字符
    	public IString delect(int begin,int end) {
    		if(begin<0) {
    			throw new StringIndexOutOfBoundsException("起始位置不能小于0!");
    		}
    		if(begin>curlen) {
    			throw new StringIndexOutOfBoundsException("起始位置不能大于串的当前长度!");
    		}
    		if(end>curlen) {
    			throw new StringIndexOutOfBoundsException("结束位置不能大于串的当前长度!");
    		}
    		for(int i=0;i<curlen-end;i++) {		//前移的字符数量为:curlen-end
    			strValue[begin+i] = strValue[end+i];
    		}
    		curlen = this.curlen - (end-begin);
    		return this;
    	}
    
    1. 字符串的连接与比较
      解析:
      两个串的字符对应比较,若不等,则返回第一个字符不相等的字符的数值差;
      若对应的字符都相等,则返回两个串长度的差。
    	//添加指定串到当前串尾
    	public IString concat(IString str) throws Exception {
    		return insert(curlen,str);
    	}
    	//将当前串与目标串str比较,结果返回它们的长度差
    	public int compareTo(IString str) throws Exception {
    		int len1 = curlen;
    		int len2 = str.length();
    		int n = Math.min(len1, len2);
    		for(int i = 0; i<n;i++) {
    			if(strValue[i]!= str.charAt(i)) {
    				return strValue[i] - str.charAt(i);
    			}
    		}
    		return len1 - len2;
    	}
    

    串的模式匹配

    BF算法(Brute-Force)

    BF算法解析

    动图分析
    BF
    【说明:动态图来源:链接

    详细图解分析:

    BF

    通过观察发现,在BF算法中,主串与模式串进行字符的比较时,若有字符不等,模式串的指针(j)都会进行一次回溯(回溯到 0 的位置继续比较),主串的指针则从下一个位置再比较( i 返回原位置+1),直到匹配成功。

    • 算法实现
    	//子串的定位(模式匹配算法):BF算法
    	public int index_of(IString str,int start) throws Exception {
    		if(this!=null&&str!=null&&str.length()>0&&this.length()>=str.length()) {
    			int i = start,j = 0;
    			int len1 = this.length();
    			int len2 = str.length();
    			while(i<len1&&j<len2) {
    				if(this.charAt(i) == str.charAt(j)) {	//匹配
    					i++;
    					j++;
    				}else {										
    					i = i - j + 1;						//不匹配时,继续比较主串中的下一个位置
    					j = 0;								//模式串回溯,退回到0
    				}
    			}
    			if(j>=str.length()) {						//返回子串开头字符相等时的序号
    				return i - len2;
    			}else {
    				return -1;
    			}
    		}
    		return -1;
    	}
    	
    

    KMP算法

    KMP对BF算法有很大的改进,它能够把“部分匹配”的结果直接通过滑动模式串到指定位置,不需要对模式串进行回溯比较,大大提高了效率。

    KMP算法

    参考书籍:《数据结构java语言描述第2版-清华大学出版社》

    展开全文
    weixin_45625687 2020-09-01 12:21:09
  • 数据结构学习记录第一章 绪论1.1 数据结构的基本概念数据结构的三要素:逻辑结构、存储结构(物理结构)、数据的运算。 逻辑结构分为线性结构和非线性结构。

    由于最近实在没时间导致这个更新鸽了。。。实在不好意思。

    第一章 绪论

    1.1 数据结构的基本概念

    1. 数据结构的三要素:逻辑结构、存储结构(物理结构)、数据的运算
    2. 数据的逻辑结构分为线性结构非线性结构,线性表是典型的线性结构,集合、树和图是典型的非线性结构。
    线性结构
    一般线性表
    受限线性表
    线性表推广
    栈和队列
    数组
    广义表
    非线性结构
    集合
    树形结构
    图状结构
    一般树
    二叉树
    有向图
    无向图
    数据的逻辑结构
    1. 数据的存储结构主要有顺序存储、链式存储、索引存储和散列存储。
    2. 顺序存储:优点是可以实现随机存取,每个元素占用最少的存储空间;缺点是只能使用相邻的一整块存储单元,因此可能产生较多的外部碎片。
    3. 链式存储:优点是不会出现碎片现象,能充分利用所有存储单元;缺点是每个元素因存储指针而占用额外的存储空间,且只能实现顺序存取
    4. 索引存储。在存储元素信息的同时,还建立附加的索引表。索引表中的每项称为索引项,索引项的一般形式是(关键字,地址)。其优点是检索速度快,缺点是附加的索引表额外占用存储空间。另外,增加和删除数据时也要修改索引表,因而会花费较多的时间。
    5. 散列存储。根据元素的关键字直接计算出该元素的存储地址,又称哈希(Hash)存储。优点是检索、增加和删除节点的操作都很快;缺点是若散列函数不好,则可能出现元素存储单元的冲突,而解决冲突会增加时间和空间开销。
    6. 可以用抽象数据类型(ADT)定义一个完整的数据结构。
    7. 在存储数据时,不仅要存储数据元素的值,而且要存储数据元素之间的关系。

    1.1 练习题

    1. 以下属于逻辑结构的是()
      A、顺序表
      B、哈希表
      C、有序表
      D、单链表
      解析:有序表是指关键字有序的线性表,仅描述元素之间的逻辑关系,它既可以链式存储也可以顺序存储,故属于逻辑结构。顺序表、哈希表、单链表是三种不同的数据结构,既描述逻辑结构,又描述存储结构和数据运算。
      答案:C
    2. 以下与数据的存储结构无关的术语是()
      A、循环队列
      B、链表
      C、哈希表
      D、栈
      解析:循环队列(易错点)是用顺序表表示的队列,是一种数据结构。栈是一种抽象数据类型,可采用顺序存储或链式存储,只表示逻辑结构。
      答案:D
    3. 以下关于数据结构的说法中,正确的是()
      A、数据的逻辑结构独立于其存储结构
      B、数据的存储结构独立于其逻辑结构
      C、数据的逻辑结构唯一决定了其存储结构
      D、数据结构仅由其逻辑结构和存储结构决定
      解析:数据的逻辑结构只采用抽象表达方式,独立于存储结构,数据的存储方式有多种不同的选择;而数据的存储结构是逻辑结构在计算机上的映射,它不能独立于逻辑结构而存在。数据结构包括三个要素,缺一不可。
      答案:A
    4. 链式存储设计时,结点内的存储单元地址()
      A、一定连续
      B、一定不连续
      C、不一定连续
      D、部分连续,部分不连续
      解析:链式存储设计时,各个不同结点的存储空间可以不连续,但结点内的存储单元地址必须连续。
      答案:A
    5. 对于两种不同的数据结构,逻辑结构或物理结构一定不相同吗?
      解答:应该注意到,数据的运算也是数据结构的一个重要方面。
      对于两种不同的数据结构,它们的逻辑结构和物理结构完全有可能相同。比如二叉树二叉排序树,二叉排序树可以采用二叉树的逻辑表示和存储方式,前者通常用于表示层次关系,而后者通常用于排序和查找。虽然它们的运算都有建立树、插入结点、删除结点和查找结点等功能,但对于二叉树和二叉排序树,这些运算的定义是不同的,以查找结点为例,二叉树的时间复杂度为O(n),而二叉排序树的时间复杂度为O(log2n)。
    6. 试举一例,说明对相同的逻辑结构,同一种运算在不同的存储方式下实现时,其运算效率不同。
      解答:线性表既可以用顺序存储方式实现,又可以用链式存储方式实现。在顺序存储方式下,在线性表中插入和删除元素,平均要移动近一半的元素,时间复杂度为O(n);而在链式存储方式下,插入和删除的时间复杂度都是O(1)。

    1.2 算法和算法评价

    1. 算法是对特定问题求解步骤的一种描述,是指令的有限序列,它还具有5个重要特性:有穷性、确定性、可行性、输入、输出。通常,设计一个“好”的算法应考虑达到以下目标:正确性、可读性、健壮性、效率与低存储量需求。
    2. 算法的时间复杂度记为T(n)=O(f(n)),通常采用算法中基本运算的频度f(n)来分析算法的时间复杂度,基本运算的频度不仅与问题规模n有关,而且与输入中各元素的取值有关。
    3. 空间复杂度是问题规模n的函数,记为S(n)=O(g(n)),算法原地工作是指算法所需的辅助空间为常量,即O(1)。

    1.2 练习题

    1. 一个算法应该是()
      A、程序
      B、问题求解步骤的描述
      C、要满足五个基本特性
      D、A和C
      解析:本题是中山大学某年的考研真题,容易误选C,五个特性只是算法的必要条件,不能成为算法的定义。
      答案:B

    第2题代码:

    	x=2;
    	while(x<n/2)
    	x=2*x;
    
    1. 【2011统考真题】设n是描述问题规模的非负整数,下面的程序片段的时间复杂度是()。
      A、O(log2n)
      B、O(n)
      C、O(nlog2n)
      D、O(n2)
      解析:每执行一次,x乘2,设执行次数为t,则有2t+1 < n/2,所以 t < log2(n/2) - 1 = log2n - 2,得T(n) = O(log2n)
      答案:A

    第3题代码:

    	int fact(int n){
    		if(n<=1) return 1;
    		return n*fact(n-1);
    	}
    
    1. 【2012统考真题】求整数n(n≥0)的阶乘的算法如下,其时间复杂度是()
      A、O(log2n)
      B、O(n)
      C、O(nlog2n)
      D、O(n2)
      解析:计算阶乘n!的递归代码,一共执行 n 次递归调用,T(n)=O(n)。
      答案:B
    2. 【2013统考真题】已知两个长度分别为m和n的升序链表,若将它们合并为长度为m+n的一个降序链表,则最坏情况下的时间复杂度是()。
      A、O(n)
      B、O(mn)
      C、O(min(m,n))
      D、O(max(m,n))
      解析:两个升序链表合并,两两比较表中元素,每比较一次,确定一个元素的链接位置(取较小元素,头插法)。当一个链表比较结束后,将另一个链表的剩余元素插入即可。最坏的情况是两个链表中的元素依次进行比较,所以时间复杂度为O(max(m,n))。
      答案:D

    第5题代码:

    	count=0;
    	for(k=1;k<=n;k*=2)
    		for(j=1;j<=n;j++)
    			count++;
    
    1. 【2014统考真题】下列程序段的时间复杂度是()。
      A、O(log2n)
      B、O(n)
      C、O(nlog2n)
      D、O(n2)
      解析:和第2题差不多,内层循环的时间复杂度是O(n),外层循环的时间复杂度是O(log2n),根据乘法规则可知,该段程序的时间复杂度T(n)=T1(n) × T2(n) = O(n) × O(log2n) = O(nlog2n)。
      答案:C

    第6题代码:

    	int func(int n){
    		int i=0, sum=0;
    		while(sum<n) sum += ++i;
    		return i;
    	}
    
    1. 【2017统考真题】下列函数的时间复杂度是()
      A、O(log2n)
      B、O(n1/2)
      C、O(n)
      D、O(nlog2n)
      解析:每执行一次,i自增1,我们如果把 i 当作一个首项为0,公差为1的等差数列的话,那么sum就是等差数列的和,由等差数列求和公式得,sum=(i+1)*i/2,设循环次数为 t ,则 t 满足(t+1)*t/2<n,因此时间复杂度为O(n1/2)。
      答案:B

    第7题代码:

    	x=0;
    	while (n>=(x+1)*(x+1))
    	x=x+1;
    
    1. 【2019统考真题】设n是描述问题规模的非负整数,下列程序段的时间复杂度是()
      A、O(log2n)
      B、O(n1/2)
      C、O(n)
      D、O(n2)
      解析:假设第 k 次循环终止,则第 k 次执行时,(x+1)2 > n,x 的初始值为0,第k次判断时,x=k-1,即k2 > n,k > n1/2,因此该程序段的时间复杂度为O(n1/2),因此选B。
      答案:B
    2. 某算法的时间复杂度为O(n2),表明该算法的()。
      A、问题规模是n2
      B、执行时间等于n2
      C、执行时间与n2成正比
      D、问题规模与n2成正比
      解析:时间复杂度T(n)=O(n2),执行时间与n2成正比。T(n)是问题规模n的函数,其问题规模仍然是n而不是n2
      答案:C

    第9题代码:

    	int m=0, i, j;
    	for(i=1;i<=n;i++)
    		for(j=1;j<=2*i;j++)
    			m++;
    
    1. "m++"的执行次数为()。
      A、n(n+1)
      B、n
      C、n+1
      D、n2
      解析:m++语句的执行次数为 ∑ i = 1 n ∑ j = 1 2 i 1 = ∑ i = 1 n 2 i = 2 ∑ i = 1 n i = n ( n + 1 ) \sum_{i=1}^{n}\sum_{j=1}^{2i}1=\sum_{i=1}^{n}2i=2\sum_{i=1}^{n}i=n(n+1) i=1nj=12i1=i=1n2i=2i=1ni=n(n+1)
      答案:A

    第二章 线性表

    2.1 线性表的定义和基本操作

    1. 线性表的定义。线性表是具有相同数据类型的 n (n ≥ 0)个数据元素的有限序列,其中 n 为表长,当n = 0时线性表是一个空表。若用 L 命名线性表,则其一般表示为 L = (a1,a2,…,ai,ai+1,…,an)式中,a1是唯一的“第一个”数据元素,又称表头元素;an是唯一的“最后一个”数据元素,又称表尾元素。除第一个元素外,每个元素有且仅有一个直接前驱。除最后一个元素外,每个元素有且仅有一个直接后继。这种线性有序的逻辑结构正是线性表名字的由来。
    2. 线性表的基本操作。
      线性表的主要操作如下:
      InitList(&L):初始化表。构造一个空的线性表。
      Length(L):求表长。返回线性表 L 的长度,即 L 中数据元素的个数。
      LocateElem(L,e):按值查找操作。在表 L 中查找具有给定关键字值的元素。
      GetElem(L,i):按位查找操作。获取表 L 中第 i 个位置的元素的值。
      ListInsert(&L,i,&e):插入操作。在表 L 中的第 i 个位置上插入指定元素e。
      ListDelete(&L,i,&e):删除操作。删除表 L 中的第 i 个位置的元素,并用 e 返回删除元素的值。
      PrintList(L):输出操作。按前后顺序输出线性表 L 的所有元素值。
      Empty(L):判空操作。若 L 为空表,则返回 true ,否则返回 false 。
      DestroyList(&L):销毁操作。销毁线性表,并释放线性表 L 所占用的内存空间。
      注意:①基本操作的实现取决于采用哪种存储结构,存储结构不同,算法的实现也不同。②“&”表示C++中的引用调用。若传入的变量是指针型变量,且在函数体内要对传入的指针进行改变,则会用到指针变量的引用型。在C中采用指针的指针也可达到同样的效果。
    3. 总结:线性表的特点:表中元素的个数有限,表中元素具有逻辑上的顺序性,表中元素有其先后次序。表中元素都是数据元素,每个元素都是单个元素。表中元素的数据类型都相同,这意味着每个元素占有相同大小的存储空间。表中元素具有抽象性,即仅讨论元素间的逻辑关系,而不考虑元素究竟表示什么内容。

    2.1 练习题

    1. 线性表是具有 n 个()的有限序列。
      A、数据表
      B、字符
      C、数据元素
      D、数据项
      解析:线性表由具有相同数据类型的有限数据元素组成的,数据元素由数据项组成的。
      答案:C
    2. 以下()是一个线性表。
      A、由 n 个实数组成的集合
      B、由100个字符组成的序列
      C、所有整数组成的序列
      D、邻接表
      解析:线性表定义的要求为:相同数据类型有限序列。选项C的元素个数是无穷个,错误;选项A集合中的元素没有前后驱关系,错误;选项D属于存储结构,线性表是一种逻辑结构,只有选项B符合要求。
      答案:B

    2.2 线性表的顺序表示

    1. 线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。第 1 个元素存储在线性表的起始位置,第 i 个元素的存储位置后面紧接着存储的是第 i + 1 元素,称 i 为元素 ai在线性表中的位序。因此,顺序表的特点是表中元素的逻辑顺序与其物理顺序相同
    2. 线性表中元素的位序是从 1 开始的,而数组中元素的下标是从 0 开始的。
    3. 假定线性表的元素类型为 ElemType,则线性表的顺序存储类型描述为
    #define MaxSize 50				//定义线性表的最大长度 
    typedef struct
    {
    	ElemType data[MaxSize];		//顺序表的元素 
    	int length;					//顺序表的当前长度 
    }SqList;						//顺序表的类型定义 
    
    1. 一维数组可以是静态分配的,也可以是动态分配的。在静态分配时,由于数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据将会产生溢出,进而导致程序崩溃。而在动态分配时,存储数组的空间是在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用以替换原来的存储空间,从而达到扩充存储数组空间的目的,而不需要为线性表一次性地划分所有空间。
    #define InitSize 100			//表长度的初始定义 
    typedef struct
    {
    	ElemType *data;				//指示动态分配数组的指针 
    	int MaxSize, length;		//数组的最大容量和当前个数  
    }SeqList;						//动态分配数组顺序表的类型定义 
    
    1. C的初始动态分配语句为L.data=(ElemType*)malloc(sizeof(ElemType)*InitSize);
    2. C++的初始动态分配语句为L.data=new ElemType[InitSize];
    3. 动态分配并不是链式存储,它同样属于顺序存储结构,物理结构没有变化,依然是随机存取方式,只是分配的空间大小可以在运行时决定。
    4. 顺序表最主要的特点是随机访问,即通过首地址和元素符号可在时间O(1)内找到指定的元素。
    5. 顺序表的存储密度高,每个节点只存储数据元素。顺序表逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素,平均时间复杂度为O(n)。
    6. 按值查找操作(顺序查找)在顺序表L中查找第一个元素值等于e的元素,时间复杂度为O(n)。

    2.2 练习题

    1. 线性表的顺序存储结构是一种()
      A、随机存取的存储结构
      B、顺序存取的存储结构
      C、索引存取的存储结构
      D、散列存取的存储结构
      解析:本题易误选B。存取方式是指读写方式。顺序表是一种支持随机存取的存储结构,根据起始地址加上元素的序号,可以很方便地访问任意一个元素,这就是随机存取的概念。
      答案:A
    2. 一个线性表最常用的操作是存取任一指定序号的元素并在最后进行插入删除操作,则利用()存储方式可以节省时间。
      A、顺序表
      B、双链表
      C、带头结点的双循环链表
      D、单循环链表
      解析:只有顺序表可以按序号随机存取,且在最后进行插入和删除操作不需要移动任何元素。
      答案:A
    3. 在 n 个元素的线性表的数组表示中,时间复杂度为O(1)的操作是()。
      I、访问第 i (1 ≤ i ≤ n)个结点和求第 i (2 ≤ i ≤ n)个结点的直接前驱
      II、在最后一个结点后插入一个新的结点
      III、删除第 1 个结点
      IV、在第 i (1 ≤ i ≤ n)个结点后插入一个结点
      A、I
      B、II、III
      C、I、II
      D、I、II、III
      解析:在最后位置插入新结点不需要移动元素,时间复杂度为O(1);被删结点后的结点需依次前移,时间复杂度为O(n)。
      答案:C
    4. 设线性表由 n 个元素,严格说来,以下操作中,()在顺序表上实现要比链表上实现的效率高。
      I、输出第 i (1 ≤ i ≤ n)个元素值
      II、交换第 3 个元素与第 4 个元素的值
      III、顺序输出这 n 个元素的值
      A、I
      B、I、III
      C、I、II
      D、II、III
      解析:对于II,顺序表上实现仅需 3 次交换操作;链表上则需要分别找到两个结点前驱,前 4 个结点断链后再插入到第 2 个结点后面,效率较低。
      答案:C
    5. 若长度为 n 的非空线性表采用顺序存储结构,在表的第 i 个位置插入一个数据元素,i 的合法值应该是()。
      A、1 ≤ i ≤ n
      B、1 ≤ i ≤ n + 1
      C、0 ≤ i ≤ n - 1
      D、0 ≤ i ≤ n
      解析:线性表元素的序号是从 1 开始,而在第 n + 1 个位置插入相当于在表尾追加。
      答案:B
    6. 【2010统考真题】设将 n(n>1)个整数存放到一维数组 R 中。设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0,X1,…,Xn-1)变换为(Xp,Xp+1,…,Xn-1,X0,X1,…,Xp-1,)。要求:
      (1)给出算法的基本设计思想。
      (2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
      (3)说明你所设计算法的时间复杂度和空间复杂度。
      解答:
      (1)算法的基本设计思想:可将这个问题视为把数组 ab 转换成数组 ba (a代表数组的前 p 个元素,b代表数组中余下的 n - p 个元素),先将 a 逆置得到 a-1b ,再将 b 逆置得到 a-1b-1 ,最后将整个a-1b-1逆置得到 (a-1b-1)-1 = ba。设 Reverse 函数执行将数组元素逆置的操作,对 abcdefgh 向左循环移动 3 (p=3)个位置的过程如下:
      Reverse(0, p - 1)得到 cbadefgh;
      Reverse(p, n - 1)得到 cbahgfed;
      Reverse(0, n - 1)得到 defghabc;
      注:Reverse 中,两个参数分别表示数组中待转换元素的始末位置。
      (2)使用C语言描述算法如下:
      (3)上述算法中三个Reverse 函数的时间复杂度分别为O(p/2)、O((n-p)/2)、O(n/2),故所设计的算法的时间复杂度为O(n),空间复杂度为O(1)。
    //第2小问代码
    void Reverse(int R[], int from, int to)
    {
    	int i, temp;
    	for(i = 0; i < (to - from + 1) / 2; i++)
    	{
    		temp = R[from + i];
    		R[from + i] = R[to - i];
    		R[to - i] = temp;
    	}
    }
    void Converse(int R[], int n, int p)
    {
    	Reverse(R, 0, p - 1);
    	Reverse(R, p, n - 1);
    	Reverse(R, 0, n - 1);
    }
    

    1. 【2011统考真题】一个长度为L(L≥1)的升序序列S,处在第 ⌈ \lceil L 2 \frac{L}{2} 2L ⌉ \rceil 个位置的数称为S的中位数。例如列S1=(11,13,15,17,19),则S1中的中位数是15。两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若92=(2,4,6,8,20),则.S1和S2的中位数是11。现有两个等长升序序列A和B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数。要求:
      (1)给出算法的基本设计思想。
      (2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
      (3)说明你所设计算法的时间复杂度和空间复杂度。
      解答:
      (1)算法的基本设计思想如下:
      分别求两个升序序列A、B的中位数,设为a和b,求序列A、B的中位数的过程如下:
      ①若a=b,则a或b即为所求中位数,算法结束。
      ②若a<b,则舍弃序列A中较小的一半,同时舍弃序列B中较大的一半,要求两次舍弃的长度相等。
      ③若a>b,则舍弃序列A中较大的一半,同时舍弃序列B中较小的一半,要求两次舍弃的长度相等。
      在保留的两个升序序列中,重复过程①、②、③,直到两个序列中均只含一个元素时为止,较小者即为所求的中位数。
      (2)本题代码如下:
      (3)算法的时间复杂度为O(log2n),空间复杂度为O(1)。
    int M_Search(int A[], int B[], int n)
    {
    	int s1 = 0, d1 = n - 1, m1, s2 = 0, d2 = n - 1, m2;
    	//分别表示序列A和B的首位数、末位数和中位数 
    	while(s1 != d1 || s2 != d2)
    	{
    		m1 = (s1 + d1) / 2;
    		m2 = (s2 + d2) / 2;
    		if(A[m1] == B[m2]) return A[m1];	//满足条件① 
    		if(A[m1] < B[m2])					//满足条件② 
    		{
    			if((s1 + d1) % 2 == 0)	//若元素个数为奇数 
    			{
    				s1 = m1;		//舍弃A中间点以前的部分且保留中间点 
    				d2 = m2;		//舍弃B中间点以后的部分且保留中间点 
    			}
    			else					//若元素个数为偶数 
    			{
    				s1 = m1 + 1;	//舍弃A中间点及中间点以前的部分
    				d2 = m2;		//舍弃B中间点以后的部分且保留中间点 
    			}
    		}
    		else								//满足条件③ 
    		{
    			if((s2 + d2) % 2 == 0)			//若元素个数为奇数 
    			{
    				d1 = m1;		//舍弃A中间点以后的部分且保留中间点 
    				s2 = m2;		//舍弃B中间点以前的部分且保留中间点 
    			}
    			else					//若元素个数为偶数 
    			{
    				d1 = m1;		//舍弃A中间点以后的部分且保留中间点 
    				s2 = m2 + 1;	//舍弃B中间点及中间点以前的部分 
    			}
    		}
    	}
    	return A[s1] < B[s2] ? A[s1] : B[s2];
    }
    

    1. 【2013统考真题】已知一个整数序列A=(a0,a1,…,an-1),其中0 ≤ ai < n(0 ≤ i < n)。若存在ap1=ap2=…=apm=x且m>n/2(0 ≤ pk < n,1 ≤ k ≤ m),则称 x 为A的主元素。例如A=(0,5,5,3,5,7,5,5),则5为主元素;又如A=(0,5,5,3,5,1,5,7),则A中没有主元素。假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1。要求:
      (1)给出算法的基本设计思想。
      (2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
      (3)说明你所设计算法的时间复杂度和空间复杂度。
    2. 【2018统考真题】给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组{-5, 3, 2, 3}中未出现的最小正整数是1;数组{1, 2, 3}中未出现的最小正整数是4。要求:
      (1)给出算法的基本设计思想。
      (2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
      (3)说明你所设计算法的时间复杂度和空间复杂度。

    最后一次更新时间:2021/03/09 23:20

    展开全文
    qq_44826711 2020-12-25 20:07:16
  • 的基本知识要点汇总,包括的相关概念、的存储、的模式匹配,next与nextval的求解等

    halo~我是bay_Tong桐小白
    本文内容是桐小白个人对所学知识进行的总结和分享,知识点会不定期进行编辑更新和完善,了解最近更新内容可参看更新日志,欢迎各位大神留言、指点

    【更新日志】

    最近更新:

    • 更新内容——BF算法代码实现(2020.7.8)
    • 内容持续更新中……

    串的相关概念

    • 定义:线性存储的一组数据(默认是字符)
    • 特殊操作集
      • 求串的长度
      • 比较两串是否相等
      • 两串相接
      • 求子串
      • 插入子串
      • 匹配子串
      • 删除子串
        ……
    • C语言中常用的串运算
      调用标准函数库#include<string.h>
      • 串比较,strcmp(char s1,char s2)
      • 串复制,strcpy(char s1,char s2)
      • 串连接,strcat(char s1,char s2)
      • 求串长,strlen(char s)
        ……

    串的存储

    串的顺序存储

    串的顺序存储描述

    串的链式存储

    串的链式存储描述

    串的模式匹配

    C语言库函数strstr

    • 函数原型:char* strstr(char* string,char* pattern)
    • 函数参数:string为要被检索的字符串,pattern为要进行匹配的模式字符串
    • 函数返回值:函数返回在字符串string中第一次出现字符串pattern的位置,如果未匹配成功则返回NULL

    举例:在字符串"This is a simple example.“中匹配字符串"simple”

    #include<stdio.h>
    #include<string.h>
    
    #define NotFound NULL
    typedef char* Position;
    
    int main()
    {
    	char string[] = "This is a simple example.";
    	char pattern[] = "simple";
    	Position p = strstr(string, pattern);
    	if (p == NotFound) { printf("Not Found.\n"); }
    	else { printf("%s\n", p); }
    	return 0;
    }
    

    测试结果如下
    在这里插入图片描述

    BF算法

    • 算法思想:朴素的穷举匹配,即将要进行检索的目标串string的第一个字符与要进行匹配的模式串的第一个字符进行匹配,若相等则继续比较string的第二个字符与pattern的第二个字符;若不相等,则将string下一个字符与pattern当前字符进行比较,依次一直进行下去,直到匹配出结果或匹配结束。
    • 算法实现(C语言):
    int BF(char* str, char* substr) {
    	int i = 1, j = 1, k = i;
    	if (strlen(str) < strlen(substr)) {
    		return 0;
    	}
    	while (str[i] != '\0'&&substr[j] != '\0') {
    		if (str[i] == substr[j]) {
    			i++; j++;
    		}
    		else {
    			j = 1; i = ++k;
    		}
    	}
    	if (substr[j] == '\0')	return k;
    	else return 0;
    }
    

    KMP算法

    next值与nextval值的求解

    【暂时只总结求解方法,具体解释和原理后续更新】

    • 核心思想:寻找当前字符之前的字符串中头部和尾部相等的长度最大的子串
    • 举例:默认字符元素从下标为1的数组单元开始存

    数组下标为1和2的数组单元next值是一定的,分别为0和1
    在这里插入图片描述
    接下来数组单元的next值的求解,需要寻找这个字符之前的字符串中头部和尾部相等的长度最大的子串,这个子串的长度+1即为此字符的next值,如果这个字符之前的字符串头部和尾部没有可以匹配的子串,则此字符的next值为1

    例如此时数组下标为3字符b之前的字符串"aa",头部和尾部相同的长度最大的子串为“a”,长度为1,因此它的next值为1+1=2
    在这里插入图片描述
    数组下标为4的字符a之前的字符串"aab",头部和尾部没有可以匹配的子串,因此它的next值为1
    在这里插入图片描述
    数组下标为5的字符a之前的字符串"aaba",头部和尾部可以匹配的最大长度子串为“a”,因此它的next值为1+1=2
    在这里插入图片描述
    数组下标为6的字符c之前的字符串"aabaa",头部和尾部可以匹配的最大长度子串为“aa”,因此它的next值为1+2=3
    在这里插入图片描述
    【此处需注意,寻找字符串头部和尾部可以匹配的最大长度子串时,顺序需保持一致,如字符串"aabaa"头部和尾部长度为3的子串分别为"aab"与"baa",二者匹配不成功】

    nextval值需要根据next值求解,数组下标为1的字符nextval值是一定的,为0。
    在这里插入图片描述
    接下来数组单元的next值的求解,以它的next值为下标去访问数组单元,比较两个单元的字符是否相等,若相等则它们的nextval值也保持一致,若不相等,则此字符的nextval值与next值保持一致

    例如此时数组下标为2字符a的next值为1,将其作为数组下标对应的字符为a,两者相等,则nextval值也保持一致
    在这里插入图片描述
    数组下标为3字符b的next值为2,将其作为数组下标对应的字符为a,两者不相等,则它的nextval值与next值保持一致
    在这里插入图片描述
    依此继续进行求解,可完成全部求解
    在这里插入图片描述

    持续更新中……
    我是桐小白,一个摸爬滚打的计算机小白

    展开全文
    bay_Tong 2020-06-29 23:54:18
  • 字符串String - 要求字符串类型、字符数组类型,字符指针类型三大类知识点。其中,字符指针特点在于存在移位操作和常量与变量两个属性。字符数组和字符指针可以采用C字符函数,而字符串对象则需要熟悉字符串方法。本...

    【摘要】

    字符串String - 要求字符串类型、字符数组类型,字符指针类型三大类知识点。

    1.要求熟记字符串与数字的转换函数;循环移位函数;拷贝字符串函数strcpy的实现;最频繁字符串查找函数;最长复现字符串查找函数;strstr函数的实现;其中,字符指针特点在于存在移位操作和常量与变量两个属性。字符数组和字符指针可以采用C字符函数,而字符串对象则需要熟悉字符串方法。本章考察点主要有:字符类型转换,寻找字符串中高频子串,最长复现子串,字符串循环移位和字符串类方法与C方法的实现。

    【正文】

    字符串与数字的相互转换

    • 使用 string 类的时候,不仅仅是头文件,而且在main()之前一定要写入“using namespace std; ”。一定要写!!!重要的事情再说一遍!!!一定要写“using namespace std; ”!!!否则,声明一个 string 的变量就报错一个 !!!
    • string要经过转化为char *才可以用strlen( ),strlen是c语言的库,是不能直接用于string!或者这样也行 

    string str = "123456789";

    cout<<strlen(str.c_str());

    • str[i]-"0" 是会报错的,一般使用str[i]-'0'即可,可以理解成字符变量之间的运算。
    • 一般不要随便声明字符串(string)变量在声明的同时最好初始化一个常量或者变量给它,结合构造函数理解。字符串不知道长度的时候,等于是没有分配内存的指针,这个时候给指针赋值,将直接导致运行错误。

    【勘误】

    这里是之前理解错误造成的片面曲解,字符串变量是不能等价于字符指针变量的。

    现给出两者比较如下:

    • 字符串变量与字符指针变量都可以采用字符数组形式读取,但是,如果字符指针指向的是常量,那么指针变量将不可随意更改。

    char *w = "12345678";

    // w[3] = '9'; // 运行报错

    • 如果指针变量指向的是变量,那么指针变量、字符串是相似的,都可以采用字符数组的形式改写变量。

    string w = "12345678";

    w[3] = '9'; 

    char ch[ ] = {'1','2','3','4','5','6'};

    char *c = ch;

    c[3] = '9';

    • 如果指针变量指向的是变量,那么指针时可以采用移位操作对指针指向变量赋值的,但是,指针与移位符表示指针指向该位置及之后的元素,而不是位置元素本身。字符串移位是会报错的。

    cout<<*c+2<<endl; // 输出 3456


    • size()和 length()适合结构体或者类对象,不对应一般数据类型。但是,一般采用length()函数,采用length()函数,采用length()函数!!!!!!重要的事情说 3 遍!!!字符数组的长度可以使用strlen()表示,sizeof()也可以表示。但是,请注意,如果是指针数组,sizeof()将给出的是地址值,如果是数组的话,那么输出的将是数组的长度。
    • itoa函数、atoi函数等 实现
    常用库函数atoi,itoa,strcpy,strcmp的实现 http://blog.csdn.net/jianzhibeihang/article/details/5710722;

    • assert 的头文件与使用

    #include <assert.h>
    void assert( int expression ); // 其作用是如果它的条件返回错误,则终止程序执行
    详见 assert()函数用法总结 http://www.cnblogs.com/ggzss/archive/2011/08/18/2145017.html

    • 为了实现链式表达式,字符串系返回值常常设置为指向字符的指针。

    链式表达式就是相关表达更加方便,就像链子一样简化代码。如: int length = strlen( strcpy( strDest, “hello world”));省去了多行代码标识。

    相关知识详见 关于链式表达式 http://www.cnblogs.com/hnrainll/archive/2011/04/29/2032868.html

    • 一般字符串结尾不是"\0"而是'\0'。这一点一定要引起重视,单个的就是字符,即便是字符串的成员,它也是字符。
    • 为了消除申请的动态内存大于使用内存,导致输出有效码字后有无效乱码干扰,可在字符串之后添加'\0',以示输出完毕。字符数组初始化的时候,字符数组的末尾请记得添'\0'。


    字符串的循环右移

    • 虽然,string 就是 char* 数据类型得变式,书中也曾提到,字符串str 有 *str表示首字符,str表示全字符串,&str表示字符串首地址。但是,这并不能表示代码中就可以将 char* 与 string画上等号。比如,在strcpy()函数上。在循环右移中我们也将遇到 string mystr; 与 char *myptr; ,其中,mystr++就是报错,myptr++就是能运行!
    • char* 变量尽量指向变量,指向常量会引入很多不必要的麻烦!!!
    • memcpy、strcpy、memset函数

    memcpy函数

      原型:extern void *memcpy(void *dest, void *src, unsigned int count);
      用法:#include <string.h>
      功能:由src所指内存区域复制count个字节到dest所指内存区域。
      说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。
    memcpy函数详见  memcpy函数  http://blog.csdn.net/fcrane/article/details/4390991

    memcpy与strcpy的比较
    memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。 
    strcpy就只能拷贝字符串了,它遇到'/0'就结束拷贝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘/0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。也可能不报错,这要看编译器。不过,报不报错这样做都是不安全的。
    这个时候数组要比“指针+分配动态内存”简洁。
    最后,在字符数据之后一定要记得加上'\0',千万记得!!!不管是字符数组还是字符指针,都最好添上,而且,字符数组最好定义大于字符数目。最后,在强调一遍,字符指针在结束处不要忘记'\0' ,这是必须的!!!
    【注】
    面试宝典在strcpy函数上,认为指针拷贝到数组不需要考虑指针的'\0',数组拷贝到数组要保证源数组较目标数组至少小一位。换言之,面试宝典人为目标对象为数组时,必须考虑'\0'。
    无符号字符 unsigned char ch;
    char 型数据的强制整型为-128~127unsigned char 的强制整型转换为 0~255。
    • c++中cerr与cout区别

    cerr:错误输出流,无缓冲,不可以重定向。输出的数据不经过缓冲区,直接放到指定的目标中,既然不经过缓冲区那么其它程序就无法把要输出的内容送到其他目标中,所以说它不能被重定向。 

    cout:标准输出流,有缓冲,可重定向。把要输出的数据先放到缓冲区中,然后再从缓冲区到你指定的设备中。当向cout流插入一个endl,不论缓冲区是否满了,都立即输出流中所有数据,然后插入一个换行符.

    cerr不被缓冲,也就说错误消息可以直接发送到显示器,而无需等到缓冲区或者新的换行符时,才被显示。而cout是一个有缓冲的输出。关于这一点,很多的资料上都有提到,但是cerr也可以通过 rdbuf 方法重定向到文件中。

    C++标准流重定向及cout和cerr的区别 http://blog.csdn.net/FromHJ/article/details/8760763

    字符串常见考题

    求字符串中连续出现次数最多的子串
    • substr 函数
    string str.substr (int val_1,int val_2)的两个参量分别表示起始值和子串长度;
    • 实现步骤
    1)将字符串的同后缀字符串子串集合,可输出查看;
    如:“12345”,同后缀集合为{“12345”;“2345”;“345”;“45”;“5”}。
    2)固定第 i 个子串,以它为基准往后的第 j 个子串,判断它们是否有相同的前缀子串,子串长度为(j - i)个字符。基准串 str[i].substr(0, j - i )。
    a)如果没有相同子串则继续滑动 j 直到找到,如果滑动到最后一个 j 子串还没有发现,那么,就让 i 滑动到下一个;
    b)如果找到相同子串,则让 j 子串为基准,再往后滑动(j - i)个子串,判断与基准串的相似性。直到不同或者到子串集合末尾为止;
    【注】
    这里有个逻辑,就是连续的相同的子串。如果相同连续,那么,第 i 个子串的(j - i)字符之后,恰好就遇到第 j 个子串首字符。
    3)记录每次的重复次数和子串,本次重复次数与之前最大的重复次数比较,最终输出最大重复次数。
    • 详细代码
    1)求一个字符串中连续出现次数最多的子串(程序面试宝典)http://blog.csdn.net/sleeping_dog/article/details/9427075 (亮点在数据结构 pair < *,* > val ( fir,sec) );
    http://blog.csdn.net/ysu108/article/details/7795479 (亮点在动态分配内存) ;
    http://blog.csdn.net/phphot/article/details/2337739(亮点在接口的思想)。
    • pair类型概述

    pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同,基本的定义如下:


    pair<int, string> a;


    表示a中有两个类型元素,第一个元素是int型的,第二个元素是string类型的,如果创建pair的时候没有对其进行初始化,则调用默认构造函数对其初始化。


    pair<string, string> a("James", "Joy");


    也可以像上面一样在定义的时候直接对其初始化。由于pair类型的使用比较繁琐,因为如果要定义多个形同的pair类型的时候,可以时候typedef简化声明


    pair<int, string> a;


    表示a中有两个类型元素,第一个元素是int型的,第二个元素是string类型的,如果创建pair的时候没有对其进行初始化,则调用默认构造函数对其初始化。


    pair<string, string> a("James", "Joy");


    也可以像上面一样在定义的时候直接对其初始化。由于pair类型的使用比较繁琐,因为如果要定义多个形同的pair类型的时候,可以时候typedef简化声明


    typedef pair<string, string> author;

    author pro("May", "Lily");

    author joye("James", "Joyce");


    • pair对象的操作 
    对于pair类,由于它只有两个元素,分别名为first和second,因此直接使用普通的点操作符即可访问其成员


    pair<string, string> a("Lily", "Poly"); 

    string name;

    name = pair.second;


    • 生成新的pair对象

    可以使用make_pair对已存在的两个数据构造一个新的pair类型:


    int a = 8;

    string m = "James";

    pair<int, string> new_one;

    new_one = make_pair(a, m);


    pair两个成员变量的的名字就叫 first 和 second 。
    pair变量可以通过pairval.first = ***;pairval.second = ***;
    和 pairval = make_pair(firval,secval);两种方式赋值,不同的是make_pair的第一个变量不可以是常量,只能是变量名。
    见到 vector 等变量,首先想到的不应该是 vecval[i] 这一种赋值方式,而是vecval的成员函数,诸如push,push_back,pop之列。
    pair相关详细详见,C++ 10.1和10.2 关联容器-----pair 类型 

      http://blog.csdn.net/hlsdbd1990/article/details/46438003


    字符串查找函数:

    1)逆序查找函数rfind;

    2)正序查找函数find。


    查找复现的最长字符串子串

    size_t,在C++中,设计 size_t 就是为了适应多个平台的 。size_t的引入增强了程序在不同平台上的可移植性size_t是针对系统定制的一种数据类型,一般是整型


    不使用库函数实现strstr()函数

    strstr()函数详见:实现strstr()函数 http://blog.csdn.net/tianmohust/article/details/7246587

    在不使用库函数的时候,处理数据最保险的是使用指针和字符数组,尤其是字符数组,安全系数最高,不容易出现溢出等问题。当然,数组的局限性很高,但是,安全系数也较高。

    注意,这里有一个标点的判断,落实多种情况在面试宝典里面没有体现,可自行约束修正;

    注意,不论是字符串、字符数组还是指针都要 '\0'。


    这里一定要明白字符串是可以像字符数组一样操作的,字符串元素的操作跟字符串数组可以一个道理。
    string str = "******"; 
    str[3]是可读写,可删改的,不过以面向对象的思想来处理数组是更提倡的一种方式,不过数组方式也勉强可行,只是不高级罢了。
    但仅仅只是定义的字符串就不可以像这样操作了。
    string str;
    str[0] = '8';
    这样操作是错误的!!!

    sprintf (char* dst , "%format_a%format_b%format_c",val_a,val_b,val_c);//该函数,负责合成字符串,不负责输出!


    固定范式编写字符串移位函数
    【题】移动字符串内容,传入参数char *a和m,规则如下:将a中字符串的倒数m个字符移到字符串前面,其余依次像右移。例如:ABCDEFGHI,M=3,那么移到之后就是GHIABCDEF。注意不得修改原代码
    指针数据也可以字符数组形式读写,可以字符数组删改。
    看见异常点不要慌,比如题目中的 w[len-m] = '\0';
    熟悉表达的执行顺序,从左至右,且一旦满足就不往右看;

    【源码】

    #include<stdio.h>  
    #include<string.h>  
      
    void fun(char *w,int m);  
      
    void main()  
    {  
        char w[30];  
        int m;  
        printf("请输入一个字符串\n");  
        gets(w);  
        printf("请输入移动的字符数\n");  
        scanf("%d",&m);  
        fun(w,m);  
        printf("移动后的结果为%s\n",w);  
    }  
      
    void fun(char *w,int m)  
    {  
        int i = 0,len = strlen(w);  
        if(m > len)       // 此处对于输入的移动字符数超过字符串长度做了处理  
            m = len;        
        while(len-m > 0 || (m = 0) != 0) //(m=0)!=0的目的是给m赋值为0,并且不进入循环,还满足要求  
            for(i = 0,w[len] = w[0],++m;i < len;i++) w[i] = w[i+1];  
        w[len-m] = '\0';  //不要被表象迷惑,刚开始就以为是在中间加了'\0',然后蒙了~  
    }  
    msbd-4.0-P.240-5





    展开全文
    u013630349 2015-06-12 11:29:27
  • qq_34840129 2018-07-18 15:44:21
  • sinat_30372583 2017-12-20 13:58:36
  • qq_40693171 2021-01-06 22:58:12
  • dnc8371 2020-07-08 23:35:52
  • m0_37568814 2018-07-30 18:50:47
  • ShannonNansen 2017-07-29 23:21:55
  • 1.09MB m0_52957036 2020-05-25 23:07:08
  • lu93it 2016-09-09 18:07:38
  • 2KB feng19870412 2009-05-09 16:50:24
  • HB15458755 2019-10-24 16:24:49
  • weixin_44641254 2020-01-02 17:42:09
  • weixin_40113925 2019-09-17 20:21:22
  • a724888 2019-09-26 15:00:58
  • broadview2006 2011-12-07 14:04:48
  • csdn_aiyang 2018-12-12 17:53:21
  • huantuo4908 2017-04-13 22:49:06
  • qq_40925525 2018-06-29 19:41:36
  • yang13563758128 2018-12-19 23:34:51
  • qiuyeyijian 2019-12-22 21:15:26
  • m0_37907797 2020-01-18 12:22:30
  • CSDN_dzh 2019-01-31 20:05:17
  • qq_45950109 2021-05-18 15:56:16
  • qq_43342294 2018-11-20 01:55:35
  • yunfengfengfeng 2020-09-10 11:01:59

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 189,810
精华内容 75,924
关键字:

数据结构字符串知识点

数据结构 订阅