数据结构与算法实践系列文章(二)数组与字符串

2021/5/19 14:25:44

本文主要是介绍数据结构与算法实践系列文章(二)数组与字符串,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

数组与字符串

数组:

数组的定义:

就是线性表的实现。

c语言

定义: int array[N] 或者 int *array = malloc();

数组的名不是指针。

#include <stdio.h>
#include <stdio.h>
// 这个地方其实是传入的数组的地址 *array,和大小
int func(int *array,int size){
    // array[0] 其实就是指针 array求值得出首地址
	return array[0]; // 等价于 *(array+0);
}
int main(int argc,const char * argv[]){
    // array是一个数组
	int array[100] = {11,22,33,44};
    // 指针的形式
	int *p = malloc(100 * sizeof(int));
    // 在这里是获取到了数组的指针
    printf("%d\n",*(array+1));
    
    // 传入的其实是数组首地址的指针
	printf("%d\n",func(array,100));
	return 0;
}

c++:

数组定义:int array[N] 或 int * array = new int[N];

java

数组定义:int array[] = new int[N];

public class main{
	public static void main(String[] args){
		int [] array = new int[10];
		array[1]=222;
		array[2]=333;
		System.out.println(array.length);
        ArrayList<Integer> list = new ArrayList<>();
        list.add(123);
        list.add(22);
        System.out.println(list);
	}
}

python

数组定义: array = [];

数组元素的查找:
c语言实现:
#include <stdio.h>

/**
** 根据值找到下标
*/
int findX(int * array,int size,int x){
	int flag=0;
	int index=-1;
	for(int i=0;i<size;i++){
		if(array[i]==x){
			flag =1;
			index = i;
		}
	}
	return index;
}
/**
** 根据下标找到值,并把原来的地址给返回过来,并返回状态。
*/
int findElement(int * array,int size, int k, int *px){
    if(k>=size || k<0) return 0;
    else{
        *px=array[k];
        return 1;
    }
}
/**
* 查找最大的。
*/
int findMax(int * array, int size){
    // 是将数组中的一个元素初始为max;
    int max =array[0];
    for(int i=1;i<size;i++){
        if(max<array[i]) max = array[i];
    }
    return max;
}
int main(int argc,const char * argv[]){
	int array[10] = {111,112,33,44,55};
	int x;
	x=12;
	int k;
	k= findX(array,10,x);
	printf("%d\n",k);
    int m,flag;
    // 传入的是数组引用,长度,和下标,和地址
    flag= findElement(array,10,3,&m);
    printf("%d,%d\n",flag,m);
	// 查找最大值
    int max ;
    max = findMax(array,10);
    printf("%d\n",max);
	return 0;
}
求两个100位的十进制的和。
C语言实现
int main(int argc, const char * argv[]){
    // 
    // 思路 用数组 ,数组的底位存0号元素(如果0号元素存在高位,则是不可以进位的)
    int a[11] = {0,9,8,7,6,5,4,3,2,1};
    int b[11] = {1,2,3,4,5,6,7,8,9,9};
    int sum[11] = {0};
    int carry=0;//进位操作
    // i< 11是为了计算最后一个
    for(int i=0;i<11;i++){
        int s;
        s=a[i]+b[i]+carry;
        carry = s/10;
        sum[i] = s%10;
    }
    for(int i=10;i>=0;i--){
        printf("%d",sum[i]);
    }
    putchar('\n');
	return 0;
}
java 实现:
public static void main(String[] args){
	BigInteger a= new BigInteger("12345678");
	BigInteger b= new BigInteger("12345678");
	BigInteger c= a.add(b);
	System.out.println(c);
}

二维数组

二维数组的实质:数组的数组。数组中的每一个元素仍然是个数组。

逻辑上可看做二维,其实并不是二维的

c语言

int array [][] 与 int **array

int array[3][4];和int **pa 的中的array和pa类型是相同的,但是 pa== array的写法是错误的

int array [ ][ ]int * *

array是数组的数组。

int *p ===> 是p 指向一个整形变量。

p[2] <==> *(p+2) 就是 p指向的整形变量再+2的位置就是 p[2]

int * * p 因为*靠p元素最近,所以p是一个指针。所以 * * p是指的是指针的指针。p[1][1]p[0][1]的位置截然不同,并不是相差一个

int * *p= array是错误的

#include <stdio.h>

int main(void) { 
	printf("test");
	int array[3][5]; // 是由int[5]
	
	//int *p[5];
	//p =array; // 这样是错误的。
	
	
	int (*p)[5];
	p = array; // 数组名赋值与指针。 那也就是 array是 一个指针。
	
	int a[10];
	int *pa =a // s数组的名求值可获取数组元素的受地址。所以 *pa就是一个指针。
	
	return 0;
}

数组传参:

#include <stdio.h>
vaid func(int (*)[5] , int ){
    // int (*)[5] 就是一个指向[5]的指针
}
void func(int array[][5] ,int k){
    // int array[][5]==>int (*p) [5];
    
}

int main(void) { 
	printf("test");
	int array[3][5]; // 是由int[5]
	
	//int *p[5];
	//p =array; // 这样是错误的。
	
	
	int (*p)[5];
	p = array; // 数组名赋值与指针。 那也就是 array是 一个指针。
	
	// 这传递的是指针
	func(array, 3);
	
	int a[10];
	int *pa =a // s数组的名求值可获取数组元素的受地址。所以 *pa就是一个指针。
	
	return 0;
}

java

public void test(){
    // 这是个3行的但是列未定义。
	int[][] array= new int[3][];
	array[0] = new int[5]; // 第0行有5列 ,创建有5个整形变量的数组
	arry[1] = new int[4];
	array[2]= new int[3];
}
大炮打蚊子案例:
/**
 * 蚊子分布在一个M×N格的二维平面上,每只蚊子占据一格。向该平面的任意位置发射炮弹,炮弹的杀伤范围如下示意:

 O
OXO
 O
其中,X为炮弹落点中心,O为紧靠中心的四个有杀伤力的格子范围。若蚊子被炮弹命中(位于X格),一击毙命,若仅被杀伤(位于O格),则损失一半的生命力。也就是说,一次命中或者两次杀伤均可消灭蚊子。现在给出蚊子的分布情况以及连续k发炮弹的落点,给出每炮消灭的蚊子数。

输入格式:
第一行为两个不超过20的正整数M和N,中间空一格,表示二维平面有M行、N列。

接下来M行,每行有N个0或者#字符,其中#表示所在格子有蚊子。

接下来一行,包含一个不超过400的正整数k,表示发射炮弹的数量。

最后k行,每行包括一发炮弹的整数坐标x和y(0≤x<M,0≤y<N),之间用一个空格间隔。

输出格式:
对应输入的k发炮弹,输出共有k行,第i行即第i发炮弹消灭的蚊子数。

输入样例:
5 6
00#00#
000###
00#000
000000
00#000
2
1 2
1 4
输出样例:
0
2
 * */
#include <stdio.h>

int board[20][20];
int M,N;
// 函数处理逻辑 当前坐标 和 杀上力
int bang(int x, int y, int kill){
    if((x>=0 && x<M) && (y>=0 && y<N) && board[x][y]>0){
        board[x][y] -=kill;
        if(board[x][y]<=0){
            // 蚊子死了
            return 1;
        }else{
            return 0;
        }
    }else{
        return 0;
    }
    return 1;
}
int main(int argc, const char * argv[]){
   scanf("%d%d",&M,&N);
   getchar();// 去除换行符
   for(int i=0;i<M;i++){
       for(int j=0;j<N;j++){
           // 给数组赋值:令蚊子的生命力为2;因为如果为1时炮弹没有击中,而是在
           // 炮弹范围内所以让其生命力为2更好计算。
           board[i][j] = getchar() == '0' ? 0:2;
       }
       // 再次读取换行符
       getchar();
   }
   int k;
   scanf("%d",&k);
   
   for(int i=0;i<k;i++){
    // 用来定义大炮打的一泡的落点
       int x,y;
       scanf("%d%d",&x,&y);
       int count=0;
       count += bang(x,y,2);
       count += bang(x-1,y,1);
       count += bang(x,y-1,1);
       count += bang(x,y+1,1);
       printf("%d\n",count);
           
   }
   
	return 0;
}

字符串

字符串就是一串字符。

字符串的定义:

c语言:“abcdefeg” 或 字符数组

#include <stdio.h>

int main(void) { 
	// c 语言运行时内存有四个部分: 栈,堆,常量区,代码块
	char *str ="hello world";
	printf("%s\n",str);
	printf("%p\n",str);
	char *str2 ="hello world";
    printf("%s\n",str2);
	printf("%p\n",str2);
	
	// 这的是s3放到了堆栈里了
	char s3[] = "hello";
	printf("%s\n",s3);
	printf("%p\n",s3);
	
	// s4数组是将常量池中的拿过来
	char s4[] = "hello word";
	printf("%s\n",s4);
	printf("%p\n",s4);
	printf("%d\n",sizeof(s3));
	return 0;
}
// 输出:
hello world
0x402004
hello world
0x402004
hello
0x7fffc8a4589a
hello word
0x7fffc8a4588f
6
可以看到 *str 与*str 两个字符的指针指向的位置相同。

c++

#include <iostream>
using namespace std;

int main() {
    string name;
    
	cout  << name <<"\n"; // 什么都没有是空字符串
	
	string name2="llk";
	
	cout  << name2 <<"\n"; 

	return 0;
}

java

public void name(){
	String name ="张三";
	System.out.println(name);
	// java一般都是new出来的而这个却可以直接复值;
	// String name = "zhang" 这个其实就是在常量池中创建了一个对象,然后name引用指向常量池; 等价于 char data[] = {'z','h','a','n',y};
	String namestr= new String(data);
	// String name = new String("zhang");
	// 这个是在堆栈中创建一个新的对象将“zhang”放到静态区
}
String str="hello";//直接赋值的方式,先在栈中创建一个对String类的对象的引用变量str,然后查找栈中有没有存放“hello”,如果没有就将“hello”存放在栈,并令star指向“hello”,如果已经有“hello”直接令str指向“hello”

通过构造方法创建字符串对象是在堆内存
String str=new String("hello");//实例化的方式

1)直接赋值(String str = "hello"):只开辟一块堆内存空间,并且会自动入池(到常量池中),不会产生垃圾。

2)构造方法(String str=  new String("hello");):会开辟两块堆内存空间,其中一块堆内存会变成垃圾被系统回收,而且不能够自动入池(到常量池中),需要通过public  String intern();方法进行手工入池(到常量池中)。new的每次都会创建对象,他只会存在堆中,每次调用一次就会创建一个新的对象。 将“hello”放到静态区

在开发的过程中不会采用构造方法进行字符串的实例化。
正则表达式与串的匹配

正则表达式是用于对字符串的匹配。

自动机
  • 非确定型有限状态自动机(NFA):
  • 确定型有限状态自动机(DFA):
// C++;

#include <iostream>
using namespace std;
#include <regex>
int main() {
    string str ="abcd";
    regex r("[a-z]+"); // 匹配一个或多个字母
    string email = "abc123@123.xm";
    regex r1("[a-z0-9]+@[a-z0-9]+\\.[a-z0-9]+");
    bool x=regex_match(str,r);
    cout << x <<endl;

    cout << regex_match(email,r1) << endl;
	return 0;
}
// java 使用类 pattern类
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数

public static void main(String args[]){
      String content = "I am noob " +
        "from runoob.com.";
 
      String pattern = ".*runoob.*";
 
      boolean isMatch = Pattern.matches(pattern, content);
      System.out.println("字符串中是否包含了 'runoob' 子字符串? " + isMatch);
 }
 
// python
import re;
re(r"正则表达式","匹配的字符")



这篇关于数据结构与算法实践系列文章(二)数组与字符串的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程