3

本文介绍了数据结构中的树和二叉树的基本概念,包括结点、度、层次等,并详细阐述了二叉树的先序、中序和后序遍历方法。此外,还讲解了两种经典排序算法——归并排序和快速排序的工作原理及实现。归并排序采用分治策略,将数组不断分解并合并;快速排序则通过选取基准元素,分而治之。最后,简要提及了BFS和DFS两种图的遍历方法。
摘要由CSDN通过智能技术生成

树与二叉树
1.定义:树是一种非线性的结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。我们平常在生活中所看到的树是根在下,枝叶在上面。而对于数据结构中的树则是根朝上,枝叶朝下,正好与生活中的树的结构相反。
2.特点:
<1>.每个结点有零个或多个子节点。
<2>.一个非根结点有且只有一个父节点。
<3>.只有根节点没有父节点。
<4>.除了根结点外,每个子节点可以分为多个不相交的子树。
3.树内的基本概念
结点:树中的元素,包含数据项及若干指向其子树的分支。
结点的度:所有结点当中,子树分支最最多的就是树的度
结点的层次:从根结点开始算起,根为第一层,
叶子:度为零的结点,也称端结点。
孩子:结点子树的根称为该结点的孩子结点。
双亲:孩子结点的上层结点,称为这些结点的双亲。
兄弟:同一双亲的孩子。
深度: 树中结点的最大层次数
森林:互不相交的树的集合
4.二叉树的遍历
在这里插入图片描述

A.先序遍历:
访问根结点
访问左子树的左子树,再访问左子树中的右子树
访问右子树的左子树,再访问右子树中的右子树
任意子树输出顺序为:父结点——左子结点——右子结点
如上图先序遍历顺序为:A-B-D-H-I-E-J-C-F-K-G
B.中序遍历:
先访问左子树中的左子树,再访问左子树中的右子树
访问根结点。
后访问右子树中的左子树,再访问右子树中的右子树
任意子树输出顺序为:左子结点——父结点——右子结点
如上图中序遍历顺序为:H-D-I-B-E-J-A-F-K-C-G
C.后序遍历:
先访问左子树中的左子树,再访问左子树中的右子树
再访问右子树中的左子树,再访问右子树中的右子树
访问根结点
任意子树输出顺序为:左子结点——右子结点——父结点
如上图后序遍历顺序为:H-I-D-J-E-B-K-F-G-C-A
快速排序与归并排序
1.归并排序
思想:分治思想:分解,合并。
过程:分解:在归并排序中,一个数组取下标中点的数字对应的值。将数组分成两部分。重复上述这个动作,直到每一小块至多只有2个数字。然后再做对比。
合并:两个小的数据集。依次比较。第1位比较另一个数据集的第1位。哪个小,哪个先进tmp数据集(append)。然后进去的那个数据所属的数据集往后稍1个,继续和另一个数据集的第1位比较。
模板:

 private static int[] helper;

 public static void mergeSort(int[] arr) {
	 if (helper == null)
	     helper = new int[arr.length];
	 else {
	     helper = null;
	     helper = new int[arr.length];
	 }
	
	 mergeSort(arr, 0, arr.length - 1);
	
	 helper = null;
 }

 private static void mergeSort(int[] arr, int lo, int hi) {
     if (lo >= hi)
         return;

     int mid = (lo + hi) >>> 1;
     mergeSort(arr, lo, mid);
     mergeSort(arr, mid + 1, hi);
     merge(arr, lo, mid, hi);
 }

 private static void merge(int[] arr, int lo, int mid, int hi) {
     System.arraycopy(arr, lo, helper, lo, hi - lo + 1);

     int left = lo;
     int right = mid + 1;
     int current = lo;

     while (left <= mid && right <= hi) {
         if (helper[left] <= helper[right])
             arr[current++] = helper[left++];
         else
             arr[current++] = helper[right++];
     }
     // 这里注意我们只需要处理这种情况,right > hi,但是 left <= mid
     // 也就是左边的数组还没有走完,右边不需要管,自己画画就知道为什么了
     while (left <= mid)
         arr[current++] = helper[left++];
 }

2.快速排序
思想:分治思想
过程:随便选取一项(一般是中间值),然后形成三个组,小于被选项组,大于被选项组合等于被选项组,递归的对小于被选项组,大于被选项组进行排序,然后合并这三个组。
模板:

public class QuickSort {

	/**
	 * 快速排序   O(NlogN)
	 * @param list
	 */
	private static void quickSort(ArrayList<Integer> list) {
		
		if(list.size()>1) {
			
			ArrayList<Integer> smallerlist = new ArrayList<>();
			ArrayList<Integer> centerList = new ArrayList<>();
			ArrayList<Integer> largeList = new ArrayList<>();
			
			//中间元素
			Integer center = list.get(list.size()/2);
			
			//分类
			for(Integer i : list) {
				if(i < center) {
					//比中间元素小
					smallerlist.add(i);
				}else if (i > center) {
					//比中间元素大
					largeList.add(i);
				}else {
					//与中间元素相等
					centerList.add(i);
				}
			}
			
			//分组排序
			quickSort(smallerlist);
			quickSort(largeList);
			
			//清空
			list.clear();
			//合并
			list.addAll(smallerlist);
			list.addAll(centerList);
			list.addAll(largeList);
		}
	}
	
	
	public static void main(String[] args) {
		int[] a = {1,8,2,6,4,2,3,8,4,6,10,12,45,21,31};
		
		ArrayList<Integer> list = new ArrayList<>();
		
		for(int i = 0;i<a.length;i++) {
			list.add(a[i]);
		}
		
		quickSort(list);
		
		for(Integer integer : list) {
			System.out.println(integer+"\t");
		}
	}
}

BFS和DFS
1.BFS
思路:算法自始至终一直通过已找到和未找到顶点之间的边界向外扩展,即算法首先搜索和s距离为k的所有顶点,然后再去搜索和S距离为k+l的其他顶点。
模板:

#include<iostream>
#include<queue>
#include<cstring> //string.h
using namespace std;

typedef pair<int,int> PII;

int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

const int N = 25;
char g[N][N]; //存图的
int st[N][N]; //标记这个点有没有被搜过
int n,m; //n行m列
int res;

void bfs(int x,int y)
{
    queue<PII> q; 
    q.push({x,y});
    
    while(q.size() > 0) //队列不空 
    {
        PII t = q.front(); //取出队头
        q.pop();//出队
        
        for(int i=0; i<4; i++) //遍历四个方向
        {
            int a = t.first + dx[i], b = t.second + dy[i]; //队头邻接点的坐标
            if(a<0 || a>=n || b<0 || b>=m) continue; //出界
            if(st[a][b] == 1) continue; //已经被访问过
            if(g[a][b] != '.') continue; //不能走
            
            res++;
            q.push({a,b});
            st[a][b] = 1; //标记(a,b)已经被访问过
        }
    }
}


int main()
{
    while(cin >> m >> n)
    {
        if(m==0 && n==0) break;
        res = 1;
        memset(st,0,sizeof st); //memset(数组名,值,sizeof 数组名); 0/-1/0x3f
        
        for(int i=0; i<n; i++) cin >> g[i];
    
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                if(g[i][j] == '@')
                {
                    bfs(i,j);
                    break;
                }
        cout << res << endl;        
    }
   

2.DFS
思路:将节点按照深度优先的次序压栈,后面再以相反的次序出栈进行新的检测
模板:

const int32_t maxn = 100;
bool visted[maxn][maxn]; // 访问标记
int32_t positionRange[maxn][maxn]; // 坐标范围
int32_t direction[][2] = {0, 1, 0, -1, 1, 0, -1, 0}; // 方向向量,(x,y)周围的四个方向

// 边界条件和约束条件的判断
bool CheckEdge(int32_t x, int32_t y)
{
    // 满足条件
    if (!visted[x][y] && ...) {
        return true;
    } else {
        return false;
    }
}

void dfs(int32_t x,int32_t y)
{
    visted[x][y] = true; // 标记该节点被访问过
    // 出现目标态G
    if (positionRange[x][y] == G) {
        ... // 做相应处理
        return;
    }
    for (int32_t i = 0; i < 4; i++) {
        // 按照规则生成下一个节点,上面左右四个点
        if (CheckEdge(x + direction[i][0], y + direction[i][1])) {
            dfs(x + direction[i][0], y + direction[i][1]);
        }
    }
    return; // 没有下层搜索节点,回溯
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值