数据结构与算法:串,矩阵,广义表;

一.串

1.基本概念
串:是由 0 个或多个字符组成的有限序列。
零个字符的串称为空串,通常用符号“ ”来表示,它的长度为零。

串的逻辑结构:和线性表极为相似。区别:串的数据对象约定是字符集。

串的基本操作:和线性表有很大差别。线性表的基本操作:以“单个元素”为操作对象;串的基本操作:以“串的整体”作为操作对象。

判断两个串是否相等:只有当两个串的长度相等,并且各个对应位置的字符都相等时才相等。
2.串的顺序存储和实现
先说说顺序存储;
串的顺序存储结构是用数组来存储串中的字符序列的。
在串的顺序存储中,一般有三种方法表示串的长度:
⑴ 用一个变量来表示串的长度
在这里插入图片描述
(2)在串尾存储一个特殊字符作为串的终结符
在这里插入图片描述
(3)用数组的0号单元存放串的长度
在这里插入图片描述
再说说串的实现;
1.串的初始化;

// 无参构造方法
public string ( ) {    }//构造一个空串
// 有参构造方法
public string(int n) {  // 构造一个能保存n个字符的串
	this.maxSize =n;
	this.chars = new char[n];
	this.length = 0;
}

2.串的比较;

public int compare(string t) {
//将当前串与串t进行比较。若相等,则返回值=0;大于返回1,;小于返回-1;
	int i=0;
	while(this.chars[i]= =t.chars[i] &&		                   i<this.length &&i<t.getLength())
	{	i++;	}
	if(i==this.length && i==t.length)
		return 0;
	else if(i==t.getLength() && i<this.length)
		return 1;
	else
		return -1;
}

对于字符串s1和s2,比较大小的话,可以直接使用**s1.compareTo(s2)**来比较大小
3.串连接

public void concat(string t)
{
        if(this.maxSize < this.length+ t.getLength( ))
        {
	//当前串容量不够,暂存到数组a
	this.maxSize = this.length + t.getLength();
	this.chars = new char[this.maxSize];
	 //恢复当前串的原始状态
         }
         for(int i= 0;i<t.getLength();i++)
         {	this.chars[this.length]=t.chars[i];
	this.length++;
          }
}

s1.concat(s2);//将字符串s2的字符添加到s1的末尾;

4.求子串;

public string subString(int pos, int len)
{
	if(pos+len>=this.length) 
		return null;
 	string a = new string(len);
	for(int i=0; i<len; i++)
	{
		a.chars[i] = this.chars[pos+i];
		a.length ++;
	}
	return a;
}

5.复制串;

public void copy(string t)  // 将串t复制给当前串
{	if(this.maxSize<t.maxSize)
	{  
		this.maxSize = t.maxSize;
		this.chars = new char[this.maxSize];
	}
	this.length=0;  //初始化当前串的长度
	for(int i=0; i<t.getLength();i++)
	{
		this.chars[i]=t.chars[i];
		this.length++;
	}
}

下面为我对串的补充操作;
设s1,s2为两个字符串;

  1. s1.compareTo(s2) //比较大小

  2. s1.length(); //求字符串长度

  3. s1.charAt(index); // 查找下标为index的字符

  4. s1.equals(s2) // 判断字符串内容是否相等

  5. s1.substring(index) // 截取从当前串的第index个字符到最后一个字符并输出

  6. s1.substring(index1,index2) //截取当前串的index1位置到index2位置的字符输出

  7. s1.indexOf(“s2”) //寻找s2的字符是否存在,存在输出s2的头字符在s1中的index,不存在则输出-1.

  8. s1.trim() //删除字符串两端的空格

  9. s1.replace(a,b) // 将字符串中所有a换成b

  10. s1.toLowerCase // s1中所有字符换成小写

  11. s1.toUpperCase // 换成大写

  12. s1.toCharArray() // 字符串转换为字符数组

  13. s1.concat(s2) // s2的字符添加到s1的末尾

3.BF算法与KMP算法
这里算是一个小重点了,具体总结一下;
先说BF算法;基本思想是将当前串的第一个字符与子串的第一个字符进行比较,相同后,再比较第二个字符,若第二个字符不同,则比较当前串的第二个字符与子串的首字符。BF算是一种蛮力算法,时间复杂度是O(n*m)。
具体代码:

public int index(string t) 
{ 
        if(this.length < t.getLength())
	return -1;	
  int a=-1;  
  for(int i=0; i< this.length;i++)
  {	int j=0;
	//在当前串中从位置i开始查找子串t
	if(j==t.getLength())
	{	a=i;	break; 	}
  }
  return a;
}

接下来说说KMP算法;
刚开始我也不太懂,然后去看了几位博主的KMP算法详解,有点感觉,在这里总结一下,如果看不懂我写的可以去我转载的博文里看看。

假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置。
若j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
若j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]。此举意味着失配时,模式串P相对于文本串S向右移动了j - next [j] 位。
对于这个next[]数组,就是模式串p的最大前缀后缀结果整体右移一位,然后第一位变成-1。
代码表示

//此代码转自https://www.cnblogs.com/imzhr/p/9613963.html
public class KMP {

    /**
     * 求出一个字符数组的next数组
     * @param t 字符数组
     * @return next数组
     */
    public static int[] getNextArray(char[] t) {
        int[] next = new int[t.length];
        next[0] = -1;
        next[1] = 0;
        int k;
        for (int j = 2; j < t.length; j++) {
            k=next[j-1];
            while (k!=-1) {
                if (t[j - 1] == t[k]) {
                    next[j] = k + 1;
                    break;
                }
                else {
                    k = next[k];
                }
                next[j] = 0;  //当k==-1而跳出循环时,next[j] = 0,否则next[j]会在break之前被赋值
            }
        }
        return next;
    }

    /**
     * 对主串s和模式串t进行KMP模式匹配
     * @param s 主串
     * @param t 模式串
     * @return 若匹配成功,返回t在s中的位置(第一个相同字符对应的位置),若匹配失败,返回-1
     */
    public static int kmpMatch(String s, String t){
        char[] s_arr = s.toCharArray();
        char[] t_arr = t.toCharArray();
        int[] next = getNextArray(t_arr);
        int i = 0, j = 0;
        while (i<s_arr.length && j<t_arr.length){
            if(j == -1 || s_arr[i]==t_arr[j]){
                i++;
                j++;
            }
            else
                j = next[j];
        }
        if(j == t_arr.length)
            return i-j;
        else
            return -1;
    }

    public static void main(String[] args) {
        System.out.println(kmpMatch("abcabaabaabcacb", "abaabcac"));
    }

}

二,矩阵

1.对称矩阵
若n阶矩阵A中的元素满足下述性质:
a[i][j]=a[j][i] 1≦i,j≦n ,则称A为n阶对称矩阵。
在这里插入图片描述
2.三角矩阵

主对角线以上全是常数c,叫做下三角矩阵
反之,叫做上三角矩阵。
3.稀疏矩阵
假设m行n列的矩阵含t个非零元素,则非零元素的比例δ=t/(m×n) 称为稀疏因子,通常认为δ≦0.05的矩阵为稀疏矩阵。

在这里插入图片描述

三,广义表

广义表是n≥1个元素 a1, a1, …, an 的有限序列,其中每一个ai 或者是原子,或者是一个子表。
表头:若 LS 非空 (n≥1 ),则第一个元素 a1 就是表头。记作 Head(LS) = a1。
注:表头可是原子,也可是子表。
表尾:除表头之外的其它元素组成的表。记作 Tail(LS) = (a2, …, an) 注意空表。
注:表尾不是最后一个元素,而是一个子表。

广义表的性质

  1. 广义表中的数据元素有相对次序。
  2. 广义表的长度定义为最外层所包含元素的个数;如:C=(a, (b, c)) 是长度为 2 的广义表。
  3. 广义表的深度定义为该广义表展开后所含括号的重数;A = (b, c) 的深度为 1,B = (A, d) 的深度为 2,C = (f, B, h) 的深度为 3。
  4. 广义表可以为其他广义表共享;如:广义表 D 就共享表 A、B、C。在 D中不必列出 A、B、C的值,而是通过名称来引用。
  5. 广义表可以是递归的表。
    如:E=(a, E)=(a, (a, (a, …)))
    注意:递归表的深度是无穷值,长度是有限值。
  6. 广义表是多层次结构,广义表的元素可以是单元素,
    也可以是子表,而子表的元素还可以是子表,…。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值