数据结构_刷面经前必了解-个人复习(简单篇)

本文脑图:
在这里插入图片描述

1 数组、链表

方式一 静态初始化
int[] arr0 = new int[]{2,4,6};

方式二 动态初始化
int[] arr1 = new int[3];//[3]代表这个数组可以存放3个元素
arr1[0] = 2;//[0]代表数组的第1个数据  将2存进去到数组第1个位置
arr1[1] = 4;//[1]代表数组的第2个数据	将4存进去到数组第2个位置
arr1[2] = 6;//[2]代表数组的第3个数据  将6存进去到数组第3个位置

方式三 隐式初始化
int[] arr1 = {2,4,6};

链表:创建链表的过程和创建数组的过程不同,不会先划出一块连续的内存。因为链表中的数据是不连续的,链表在存储数据的内存中有两块区域,一块区域用来存储数据,一块区域用来记录下一个数据保存在哪里(指向下一个数据的指针)。当有数据进入链表时候,会根据指针找到下一个存储数据的位置,然后把数据保存起来,然后再指向下一个存储数据的位置。这样链表就把一些碎片空间利用起来了,虽然链表是线性表,但是并不会按线性的顺序存储数据。
在这里插入图片描述
拓展必知:ArrayList和linklist。

目前,我比较多使用的是arraylist,毕竟很多开源小项目只确保程序能运行,不管他性能好不好,毕竟小项目,肉眼上看也看不出来。

  1. ArrayList是基于数组实现的,LinkedList是基于双链表实现的。LinkedList可以作为双向队列 ,栈和List集合使用,功能强大。
  2. 因为Array是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的,可以直接返回数组中index位置的元素,因此在随机访问集合元素上有较好的性能。Array获取数据的时间复杂度是O(1),但是要插入、删除数据却是开销很大的本人也大致了解到这,剩下的要接触在市场上已经在用的项目才更好地去理解运用。
  3. LinkedList需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而LinkedList中的每个节点中存储的是实际的数据和前后节点的位置。

2 队列、栈

队列:队列是一种先进先出的数据结构,数组和链表也都可以生成队列。当数据进入到队列中时也是先进入的在下面后进入的再上面,但是出队列的时候是先从下面出,然后才是上面的数据出,最晚进入的队列的,最后出。
在这里插入图片描述
栈:栈是一种先进后出的数据结构,数组和链表都可以生成栈。当数据进入到栈时会按照规则压入到栈的底部,再次进入的数据会压在第一次的数据上面,以此类推,在取出栈中的数据的时候会先取出最上面的数据,所以是先进后出。
由于数组和链表都可以组成栈,所以操作特点就需要看栈是由数组还是链表生成的了,然后就会继承相应的操作特点。
在这里插入图片描述

3 树、堆、图

树: 此处树特指二叉树(BinaryTree)。二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树右子树的二叉树组成。二叉树的特点:

  • 每个结点最多有两棵子树。(注意:不是都需要两棵子树,而是最多可以是两棵,没有子树或者有一棵子树也都是可以的。)
  • 左子树和右子树是有顺序的,次序不能颠倒。
  • 即使树中某结点只有一棵子树,也要区分它是左子树还是右子树,下面是完全不同的二叉树:

在这里插入图片描述

堆:堆是一颗完全二叉树。在这棵树中,所有父节点都满足大于等于其子节点的堆叫大根堆。所有父节点都满足小于等于其子节点的堆叫小根堆。堆虽然是一颗树,但是通常存放在一个数组中,父节点和孩子节点的父子关系通过数组下标来确定。
在这里插入图片描述

:(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。图有各种形状和大小。边可以有权重(weight),即每一条边会被分配一个正数或者负数值。
在这里插入图片描述

4 哈希表

哈希表在应用中也是比较常见的,就如Java中有些集合类就是借鉴了哈希原理构造的,例如HashMap,HashTable等,利用hash表的优势,对于集合的查找元素时非常方便的,然而,因为哈希表是基于数组衍生的数据结构,在添加删除元素方面是比较慢的,所以很多时候需要用到一种数组链表来做,也就是拉链法。拉链法是数组结合链表的一种结构,较早前的hashMap底层的存储就是采用这种结构,直到jdk1.8之后才换成了数组加红黑树的结构,其示例图如下:
在这里插入图片描述
拓展必知:hashmap和hashtable(略)
hashmap(基础+源码+面试题)参考链接

5 7种基本排序

七种排序算法(最常见)的各种指标比较,稳定是只能是两两之间进行操作

(不记表,记排序规则,这个顺序记忆方便,记住动态图,看完后在看表,我这个表好有规律的哦)

排序方法平均情况最好情况最坏情况空间复杂度稳定性
冒泡排序O(n²)O(n)O(n²)O(1)稳定
插入排序O(n²)O(n)O(n²)O(1)稳定
选择排序O(n²)O(n²)O(n²)O(1)稳定
归并排序O(n logn)O(n logn)O(n logn)O(n)稳定
堆排序O(n logn)O(n logn)O(n logn)O(1)不稳定
快速排序O(n logn)O(n logn)O(n²)O(logn)~O(n)不稳定
希尔排序O(n logn)~O(n²)O(n^1.3~1.5)O(n²)O(1)不稳定

5.1 冒泡排序

两两比较,大的后排,所以是o(n²),如果一开始就是排序好的,只进行一次两两比较,没交换那就是o(n)
在这里插入图片描述

5.2 直接插入排序

取下一个数和前面比较,比它打就排在它后面,如果一开始就是排序好的,只进行取出插入,没进行和前面比较那就是o(n)
在这里插入图片描述

5.3 折半插入排序:

在这里插入图片描述

5.4 选择排序

找最小,放前头,都要全找一遍,两次for叠加,所以是o(n²)
在这里插入图片描述

5.5 归并排序

从小到大排序,首先让数组中的每一个数单独成为长度为1的区间,然后两两一组有序合并,得到长度为2的有序区间,依次进行,直到合成整个区间。

img

5.6 快速排序

从小到大排序:一个基准数,小于基准数排放左边,大的放右边

在数组中随机选一个数(默认数组首个元素),数组中小于等于此数的放在左边,大于此数的放在右边,再对数组两边递归调用快速排序,重复这个过程。
img
在这里插入图片描述

5.7 希尔排序

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序font>,具体算法描述:
在这里插入图片描述
在这里插入图片描述

6 简单算法篇

6.1 冒泡排序

public static int[] bubbleSort(int[] array){
	if(array.length > 0){
		for(int i = 0;i<array.length;i++){
			for(int j = 0;j<array.length - 1 - i;j++){
				if(array[j] > array[j+1]){
					int temp = array[j];
					array[j] = array[j+1];
					array[j+1] = temp;
				}
			}
		}
	}
	return array;
}

6.2 直接插入排序

public static int[] insertionSort(int[] array) {
    if (array.length == 0)
        return array;
    int current;
    for (int i = 0; i < array.length - 1; i++) {
        current = array[i + 1];
        int preIndex = i;
        while (preIndex >= 0 && current < array[preIndex]) {
            array[preIndex + 1] = array[preIndex];
            preIndex--;
        }
        array[preIndex + 1] = current;
    }
    return array;
}

6.3 选择排序

public static int[] selectionSort(int[] array) {
        if (array.length == 0)
            return array;
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i; j < array.length; j++) {
                if (array[j] < array[minIndex]) //找到最小的数
                    minIndex = j; //将最小数的索引保存
            }
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
        return array;
}

6.4 归并排序

public static int[] MergeSort(int[] array) {
    if (array.length < 2) return array;
    int mid = array.length / 2;
    int[] left = Arrays.copyOfRange(array, 0, mid);
    int[] right = Arrays.copyOfRange(array, mid, array.length);
    return merge(MergeSort(left), MergeSort(right));
}
public static int[] merge(int[] left, int[] right) {
    int[] result = new int[left.length + right.length];
    for (int index = 0, i = 0, j = 0; index < result.length; index++) {
        if (i >= left.length)
            result[index] = right[j++];
        else if (j >= right.length)
            result[index] = left[i++];
        else if (left[i] > right[j])
            result[index] = right[j++];
        else
            result[index] = left[i++];
    }
    return result;
}

6.5 快速排序

public static int[] QuickSort(int[] array, int start, int end) {
    if (array.length < 1 || start < 0 || end >= array.length || start > end) return null;
    int smallIndex = partition(array, start, end);
    if (smallIndex > start)
        QuickSort(array, start, smallIndex - 1);
    if (smallIndex < end)
        QuickSort(array, smallIndex + 1, end);
    return array;
}
//快速排序算法
public static int partition(int[] array, int start, int end) {
    int pivot = (int) (start + Math.random() * (end - start + 1));
    int smallIndex = start - 1;
    swap(array, pivot, end);
    for (int i = start; i <= end; i++)
        if (array[i] <= array[end]) {
            smallIndex++;
            if (i > smallIndex)
                swap(array, i, smallIndex);
        }
    return smallIndex;
}
//交换数组内两个元素
public static void swap(int[] array, int i, int j) {
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

6.6 希尔排序

public static int[] ShellSort(int[] array) {
    int len = array.length;
    int temp, gap = len / 2;
    while (gap > 0) {
        for (int i = gap; i < len; i++) {
            temp = array[i];
            int preIndex = i - gap;
            while (preIndex >= 0 && array[preIndex] > temp) {
                array[preIndex + gap] = array[preIndex];
                preIndex -= gap;
            }
            array[preIndex + gap] = temp;
        }
        gap /= 2;
    }
    return array;
}

6.7 其他算法,优先度低

算法重要,但优先度低,因短时间补不回来,战略性延后。本人身边同学面试的算法有:链表反转(超多人面试到)、合并有序数组、快速排序算法(超多人面试到)
其余算法可参考:剑指 Offer 题解Leetcode 题解

7 参考链接

数组的定义、声明、初始化、遍历、冒泡排序:https://blog.csdn.net/qq_43519384/article/details/106203666

“高频面经”之数据结构与算法篇:https://blog.csdn.net/qq_36936730/article/details/104342464

十大经典排序算法最强总结(含JAVA代码实现):https://blog.csdn.net/sinat_38325967/article/details/88851025

如有遗漏,请在评论区留言。

8 备注

大多公司都有各自的题库,大厂需要刷对应面经。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
C语言的数据结构面经主要包括C语言基础、操作系统、计算机网络、数据结构与算法、设计模式等内容。 在C语言的面经中,C++的增强特性也是常见的一部分,比如引用、类与对象、模板、智能指针等,还有STL模板库等。这些特性使得C++的使用更加便捷和安全。 此外,C++11引入了一些新特性,比如std::enable_if和SFINAE。SFINAE是Substitution failure is not an error的缩写,意思是匹配失败不是错误。简单来说,当调用模板函数时,编译器会根据传入参数推导最合适的模板函数,在这个推导过程中,如果某些模板函数的推导结果是编译无法通过的,只要有一个可以正确推导出来的模板函数,那些推导结果可能引发编译错误的模板函数并不会导致整个编译错误。 在面试中,还会涉及到指向数据成员的指针。C++中可以使用指向类成员函数的指针来调用函数,也可以使用指向类数据成员的指针来访问数据成员。 多线程也是面试中常见的一个话题,关于多线程的问题,需要考虑线程安全性。在C++中,需要采取一些措施来保证线程安全,比如使用互斥锁、条件变量等。 综上所述,C语言的数据结构面经主要围绕C语言基础、操作系统、计算机网络、数据结构与算法、设计模式等内容展开,并且会涉及到C++的一些增强特性,以及指向数据成员的指针和多线程的相关知识。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [C++开发工程师面经总结](https://blog.csdn.net/Arcofcosmos/article/details/127156504)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [2020秋招_C++基础、数据结构基础面经记录](https://blog.csdn.net/XindaBlack/article/details/107120742)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LQ小林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值