数据结构复试常问问题详解

一、基本的数据结构分类

1、数据结构是一个抽象的概念,可分为线性结构和非线性结构。线性结构有线性表、队列、栈和数组。非线性结构有树、图等。
2、数组是一组连续的空间,每个元素占用相同的空间。访问数组元素的时间复杂度为O(1)。但插入和删除操作的时间复杂度为O(n)。
3、链表是一种非连续的数据结构,由节点组成。单向链表和双向链表,访问元素的时间复杂度为O(n),但插入和删除操作时间复杂度为O(1)。
4、栈和队列是特殊的线性结构,栈是后进先出,队列是先进先出。
5、树是一种以分支关系连接的非线性结构,由节点组成。树形结构包括二叉树、红黑树、AVL树和B树。
6、图是一种由节点和边组成的非线性结构。图可分为有向图和无向图,根据边权重不同可分为带权图和无权图。


//示例代码:链表的定义和实现
class Node{
public:
    int data;
    Node* next;
    Node(int val):data(val),next(nullptr){}
};
class LinkedList{
public:
    LinkedList():head(nullptr){}
    void add(int val){
        Node* temp=new Node(val);
        if(head==nullptr){
            head=temp;
        }else{
            temp->next=head;
            head=temp;
        }
    }
    void print(){
        Node* curr=head;
        while(curr!=nullptr){
            cout<data<next;
        }
    }
private:
    Node* head;
};

二、时间和空间复杂度

1、时间复杂度是算法在运行过程中,所需要计算的基本操作次数的数量级。用大O表示法表示,常用的有O(1)、O(logn)、O(n)、O(n^2)等。
2、空间复杂度是算法所需要占用的内存空间数量级。常见的是O(1)和O(n)。
3、要注意最坏时间复杂度和平均时间复杂度的区别。循环语句、条件判断语句和递归都可能影响算法的时间和空间复杂度。


//示例代码:归并排序
void MergeSort(int* arr,int l,int r){
    if(l>=r) return;
    int mid=(l+r)/2;
    MergeSort(arr,l,mid);
    MergeSort(arr,mid+1,r);
    int* temp=new int[r-l+1];
    int i=l,j=mid+1,k=0;
    while(i<=mid && j<=r){
        if(arr[i]<=arr[j]) temp[k++]=arr[i++];
        else temp[k++]=arr[j++];
    }
    while(i<=mid){
        temp[k++]=arr[i++];
    }
    while(j<=r){
        temp[k++]=arr[j++];
    }
    for(i=l,j=0;i<=r;i++,j++){
        arr[i]=temp[j];
    }
    delete[] temp;
}

三、递归和迭代

1、递归是一种经典的算法,可以简化代码,但可能会降低性能,容易出现堆栈溢出等问题。递归问题中必须有一个递归结束的条件。
2、迭代比递归效率高,但可能不如递归好理解。许多递归问题都可以转化为循环,因此迭代使用较多。
3、注意递归和迭代的优缺点,合理运用二者。


//示例代码:斐波那契数列的递归和迭代实现
//递归
int Fibonacci(int n){
    if(n==1 || n==2) return 1;
    else return Fibonacci(n-1)+Fibonacci(n-2);
}
//迭代
int Fibonacci(int n){
    if(n==1 || n==2) return 1;
    int pre=1,cur=1;
    for(int i=3;i<=n;i++){
        int temp=pre+cur;
        pre=cur;
        cur=temp;
    }
    return cur;
}

四、树的遍历方式

1、树的遍历方式包括先序遍历、中序遍历和后序遍历。先序遍历是先遍历根节点,再遍历左子树和右子树;中序遍历是先遍历左子树,再遍历根节点和右子树;后序遍历是先遍历左子树和右子树,再遍历根节点。
2、利用递归和栈都可以进行树的遍历。
3、应该注意到为了遍历,不管是递归还是栈,都需要对树的每个节点进行遍历。对于算法的时间和空间复杂度都有一定的影响。


//示例代码:二叉树的后序遍历实现
class Node{
public:
    int val;
    Node *left,*right;
    Node(int val):val(val),left(nullptr),right(nullptr){}
};
void PostOrder(Node* root){
    if(root==nullptr) return;
    PostOrder(root->left);
    PostOrder(root->right);
    cout<val<<" ";
}

五、哈希表

1、哈希表是一种常见的数据结构,可以快速查找某个元素。哈希表由一个数组和哈希函数组成,其中哈希函数将元素映射到数组的某个位置。如果有多个元素映射到同一位置,就需要使用链表解决冲突问题。
2、需要注意哈希表的建立、插入、删除和查找操作,以及哈希函数的设计,如何解决哈希冲突等问题。
3、哈希表可以用来解决很多算法问题,如Lru Cache,Two Sum等。


//示例代码:哈希表的实现--开放地址法
struct Node{
    int key;
    int val;
    Node(int k,int v):key(k),val(v){}
};
class HashTable{
public:
    HashTable(int size):size(size),used(0){
        table=new Node*[size];
        for(int i=0;ikey!=key){
            index=(index+1)%size;
        }
        if(table[index]==nullptr){
            table[index]=new Node(key,val);
            used++;
        }else{
            table[index]->val=val;
        }
    }
    void erase(int key){
        int index=hash(key);
        while(table[index]!=nullptr){
            if(table[index]->key==key) break;
            index=(index+1)%size;
        }
        if(table[index]==nullptr) return;
        else{
            delete table[index];
            table[index]=nullptr;
            used--;
        }
    }
    int get(int key){
        int index=hash(key);
        while(table[index]!=nullptr){
            if(table[index]->key==key) return table[index]->val;
            index=(index+1)%size;
        }
        return -1;
    }
    bool contains(int key){
        int index=hash(key);
        while(table[index]!=nullptr){
            if(table[index]->key==key) return true;
            index=(index+1)%size;
        }
        return false;
    }
private:
    int size,used;
    Node** table;
};

原创文章,作者:KWIM,如若转载,请注明出处:https://www.506064.com/n/134645.html

(0)
KWIMKWIM
上一篇 2024-10-04
下一篇 2024-10-04

相关推荐

  • 提高移动应用性能的几种方法

    一、设计可扩展的架构 移动应用的架构设计不仅仅影响应用的可扩展性和可维护性,也会对性能造成直接或间接的影响。要在应用开发的早期阶段考虑应用的架构设计,以满足应用在未来可能面临的新增…

    编程 2024-10-04
  • 深入了解sendevent

    一、发送事件是什么 sendevent 是一个命令行工具,用于向输入子系统发送事件,通常被用于模拟硬件操作(如按键,触摸等)或测试应用程序的交互性。在安卓平台中,sendevent…

    编程 2024-10-04
  • c语言指针p1与p,指针p1p2

    本文目录一览: 1、c语言中指针型变量p1,p2 那*p1=*p2和p1=p2什么区别? 2、c语言中的指针中有一段 *p=*p1,我想问一下 *P有具体的值 也就是说是一个常量,…

    编程 2024-10-04
  • python环境设置为32位(32位系统安装python)

    1、python 32位和64位的区别在哪 2、如何使用pyinstaller打包32位的exe 3、如何python设置成默认启动32位模式 4、怎么查看python是32位还是…

    编程 2024-10-03
  • 5位python专家告诉你,关于Python

    本文目录一览: 1、怎样才能学好python语言? 2、python与php的区别 专家解析python与php的四大区别 3、Python有哪些技术上的优点?比其他语言好在哪儿?…

    编程 2024-10-03
  • 非关系数据库mysql(非关系数据库包括哪些)

    本文目录一览: 1、国产DBMS有哪些?除了关系数据库管理系统外,还有哪些非关系数据库管理系统? 2、有哪些轻型的非关系型数据库? 3、Mongodb和mysql的区别 4、什么是…

    编程 2024-10-03
  • 掌握十个实用命令行指令,让你的工作效率翻倍!

    在日常工作中,命令行是一个非常实用的工具。掌握一些实用的命令行指令,可以让你的工作效率大大提高。下面介绍十个实用的命令行指令。 一、ls ls ls命令用于列出目录下的文件和子目录…

    编程 2024-10-04
  • c语言与嵌入式的区别,嵌入式和c语言的区别

    本文目录一览: 1、嵌入式系统开发中的C语言编程和普通C语言编程有何区别? 2、嵌入式C语言和普通的C语言有什么区别,有什么新的东西吗? 3、嵌入式c语言和c语言的异同 4、嵌入式…

    编程 2024-10-08
  • 想输入php后(php输入数据)

    本文目录一览: 1、php输入语句怎么写 2、php 在输入框输入内容,提交后自动在这段内容前后添加特定内容并把这些内容生成多个文件名不同的文件供下 3、想用PHP做个查询页面,接…

    编程 2024-10-03
  • PHP时间格式化指南

    PHP作为一门高级编程语言,在时间处理方面拥有强大而丰富的工具和函数。本篇文章将为大家介绍一些PHP时间格式化的方法,以及对应的代码示例,希望能够帮助大家更好地处理时间相关的问题。…

    编程 2024-10-04

发表回复

登录后才能评论