算法与数据结构常见面试知识点

堆栈的区别

堆和栈都是一种数据项按序排列的数据结构。
栈是先进后出,而堆是一种经过排序的树形数据结构,每个结点都有一个值。通常我们所说的堆的数据结构,是指二叉堆。堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。由于堆的这个特性,常用来实现优先队列,堆的存取是随意的。

申请方式和回收方式区别
栈(英文名称是stack)是系统自动分配空间的,也是自动回收的。而堆(英文名称是heap)则是程序员根据需要自己申请的空间,如果不释放会一直占用。

堆栈溢出
栈溢出是由于C语言系列没有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小,因此当这个数据足够大的时候,将会溢出缓冲区的范围。 堆溢出的产生是由于过多的函数调用,导致调用堆栈无法容纳这些调用的返回地址,一般在递归中产生。堆溢出很可能由无限递归


数组链表区别

C++语言中可以用数组处理一组数据类型相同的数据,但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小。而在实际应用中,用户使用数组之前无法确定数组的大小,只能够将数组定义成足够大小,这样数组的空间可能不被使用,从而造成内存空间的浪费

链表是一种常见的数据组织形式,他采用动态分配内存的形式实现。需要时可以用new分配内存空间,不需要时用delete将已分配的空间释放,不会造成内存空间的浪费。


线程和进程

进程:在操作系统中能够独立运行,并且作为资源分配的基本单位。它表示运行中的程序。

线程:是进程中的一个实例,作为系统调度和分派的基本单位。是进程中的一段序列,能够完成进程中的一个功能。

1.同一个进程可以包含多个线程,一个进程中至少包含一个线程,一个线程只能存在于一个进程中。
2.同一个进程下的所有线程能够共享该进程下的资源。(系统运行时会为每个进程分配不同的内存区域,但不会为线程分配内存。线程只能共享它所属进程的资源。)
3.进程结束后,该进程下的所有线程将销毁,而一个线程的结束不会影响同一进程下的其他线程。
4.线程是轻量级的进程,它的创建和销毁所需要的时间比进程小得多,所有操作系统的执行功能都是通过创建线程去完成的。
5.线程在执行时是同步和互斥的,因为他们共享同一个进程下的资源。
6.在操作系统中,进程是拥有系统资源的独立单元,它可以拥有自己的资源。一般而言,线程不能拥有自己的资源,但是它能够访问其隶属进程的资源。


排序算法

最基本的排序算法:冒泡排序,选择排序,插入排序
注重思想和复杂度:堆排序,归并排序,快速排序

(1)当数据规模较小的时候,可以用简单的排序算法如直接插入排序或直接选择排序。(2)当文件的初态已经基本有序时,可以用直接插入排序或冒泡排序。(3)当数据规模比较大时,应用速度快的排序算法。
在这里插入图片描述
快速排序
1、在数列之中,选择一个元素作为”基准”(pivot),或者叫比较值。
2、数列中所有元素都和这个基准值进行比较,如果比基准值小就移到基准值的左边,如果比基准值大就移到基准值的右边;
3、以基准值左右两边的子列作为新数列,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

'''
单指针,判断列表中的每一个元素,都与基准值进行比较,如果大于则放到右边,小于则放在左边,然后迭代,直到剩下一个元素为止
'''
def split(A,low,high):
    i = low
    x = A[low]

    for j in range(low+1,high):
        if A[j] <= x:
            i +=1
            A[i],A[j] = A[j],A[i]

    A[low],A[i] = A[i],A[low]
    return i

def quicksort(A,low,high):
    if low<high:
        i = split(A,low,high)
        quicksort(A,low,i-1)  #i是i-1与i+1的中间点,也是这个列表中元素递增的分割点
        quicksort(A,i+1,high)
        print("i",i,"A:",A)

    return A

A = [3,2,1,6,7,4]
print(quicksort(A,0,6))

'''
双指针:partition算法使用头尾两个方向相反的指针进行遍历,先将数组第一个元素设置为比较元素,
头指针从左至右找到第一个大于比较元素的数,尾指针从右至左找到第一个小于比较元素的数,全部交换完毕后将比较元素放到中间位置。
'''

def patition(A,low,high):
    i = low
    j = high
    x=A[low]
    while i<j:
        while (i<j and A[j]>=x):
            j -= 1
        #利用while从左到右找到第一个大于比较元素的数,记录下来
        while (i<j and A[i]<=x):
            i += 1

        if i!=j:
            print("i,j",(i,j))
            A[i],A[j]=A[j],A[i]

    A[i],A[low]=A[low],A[i]
    return i

def quicksort(A,low,high):
    if low<high:
        i = patition(A,low,high)
        quicksort(A,low,i-1)
        quicksort(A,i+1,high)
    return A

print(quicksort([3,1,6,5,4,2],0,5))

#方法三
def quick_sort(b):
    """快速排序"""
    if len(b) < 2:
        return b
    # 选取基准,随便选哪个都可以,选中间的便于理解
    mid = b[len(b) // 2]
    # 定义基准值左右两个数列
    left, right = [], []
    # 从原始数组中移除基准值
    b.remove(mid)
    for item in b:
        # 大于基准值放右边
        if item >= mid:
            right.append(item)
        else:
            # 小于基准值放左边
            left.append(item)
    # 使用迭代进行比较
    return quick_sort(left) + [mid] + quick_sort(right)

b = [11, 99, 33, 69, 77, 88, 55, 11, 33, 36, 39, 66, 44, 22]
print(quick_sort(b))



冒泡排序
原理:比较两个相邻的元素,将值大的元素交换到右边

def bubblesort(A):
    for j in range(len(A)-1):
        for i in range(len(A)-1-j):
            if A[i+1]<A[i]:
                A[i+1],A[i]=A[i],A[i+1]

    return A
print(bubblesort([2,3,1,7,4,5]))

归并排序

def merge(left, right):
    """假设left和right是两个有序列表,compare定义了一种元素排序规则。
    返回一个新的有序列表(按照compare定义的顺序),其中包含与
    (left+right)相同的元素。"""
    result = []
    i,j = 0, 0
    while i < len(left) and j < len(right):
        if left[i]<right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    while (i < len(left)):
        result.append(left[i])
        i += 1
    while (j < len(right)):
        result.append(right[j])
        j += 1
    print("result:",result)
    return result


def mergeSort(L, compare = lambda x, y: x < y):
    """假设L是列表,compare定义了L中元素的排序规则
    on elements of L
    返回一个新的具有L中相同元素的有序列表。"""
    if len(L) < 2:
        return L[:]
    else:
        middle = len(L)//2
        left = mergeSort(L[:middle])
        right = mergeSort(L[middle:])
        print("left:",left,"right:",right)
        return merge(left, right)

print(mergeSort([1,2,3,4,5,2,3,5,6,7]))

选择排序
选择排序的工作原理是维持一个循环不变式,它会将列表分成前缀部分( L[0 : i] )和后缀部分( L[i+1 : len(L)] ),前缀部分已经排好序,而且其中的每一个元素都不大于后缀部分中的最小元素

def selSort(L):
    """假设L是列表,其中的元素可以用>进行比较。
    compared using >.
    对L进行升序排列"""
    suffixStart = 0
    while suffixStart != len(L):
    #检查后缀集合中的每个元素
        for i in range(suffixStart, len(L)):
            if L[i] < L[suffixStart]:
                print(i)
                #交换元素位置
                L[suffixStart], L[i] = L[i], L[suffixStart]
        suffixStart += 1
    return L
print(selSort([2,3,1,5,6,8,4]))

归并排序与快排 : 归并排序与快排两种排序思想都是分而治之,但是它们分解和合并的策略不一样:归并是从中间直接将数列分成两个,而快排是比较后将小的放左边大的放右边,所以在合并的时候归并排序还是需要将两个数列重新再次排序,而快排则是直接合并不再需要排序,所以快排比归并排序更高效一些

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jeremy_lf

你的鼓励是我的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值