数据结构_35

一、线性表
   排序:冒泡排序、选择排序、快速排序、归并排序
   查找:二分查找
二、树
   遍历:递归(前中后序、层次)
   排序:大根堆、小根堆
   哈夫曼树
三、图
   广度优先遍历
   深度优先遍历
   最小生成树:Prim算法、Kus算法
   最短路径:Dij算法

一、线性表

  • 排序算法
       冒泡排序:
//冒泡排序
void bubbleSort(int *arr, int length) {
	//外层for循环控制查找第i大的元素
	for (int i = length; i > 0; i--) {
		//内层for循环,从0开始依次比较前后两个元素
		for (int j = 0; j < i - 1; j++) {
			//如果arr[j] > arr[j+1],则交换位置
			if (arr[j] > arr[j + 1])
				swap(arr[j], arr[j + 1]);
		}
	}
}

   选择排序:

void selectionSort(int *arr,int length) {
	int minIndex;
	for (int i = 0; i < length; i++) {
		minIndex = i;					//记录第i小值的下标

		//查找[i, length]范围内的最小值下标
		for (int j = i + 1; j < length; j++) {
			if (arr[minIndex] > arr[j])
				minIndex = j;
		}
		swap(arr[minIndex], arr[i]);	//把第i小的值,交换到i的位置
	}
}

   归并排序:

 //将arr[l...mid]和arr[mid+1...r]两部分进行归并
void merge(int *arr, int l, int mid, int r) {

	int *aux = new int[r - l + 1];

	for (int i = l; i <= r; i++) {
		aux[i - l] = arr[i];
	}

	// 初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1
	int i = l, j = mid + 1;
	for (int k = l; k <= r; k++) {

		//有一组元素已经全部入队
		if (i > mid) {  // 如果左半部分元素已经全部处理完毕
			arr[k] = aux[j - l]; j++;
			continue;
		} else if (j > r) {  // 如果右半部分元素已经全部处理完毕
			arr[k] = aux[i - l]; i++;
			continue;
		} 
		//两组元素等待入队
		if (aux[i - l] < aux[j - l]) {  // 左半部分所指元素 < 右半部分所指元素
			arr[k] = aux[i - l]; i++;
		} else {  // 左半部分所指元素 >= 右半部分所指元素
			arr[k] = aux[j - l]; j++;
		}
		
	}

	delete[] aux;	//释放创建的空间
}

// 递归使用归并排序,对arr[l...r]的范围进行排序
void mergeSort(int *arr, int l, int r) {

	if (l >= r)
		return;

	int mid = (l + r) / 2;
	mergeSort(arr, l, mid);			//递归l到mid
	mergeSort(arr, mid + 1, r);		//递归mid+1到r
	merge(arr, l, mid, r);			//对l到r进行排序
}

   快速排序:

// 对arr[low...high]部分进行partition操作
// 返回low, 使得arr[low]之前的都小于arr[low]; arr[low]之后的都大于arr[low]
int partition(int *arr, int low, int high) {
	int pivotkey = arr[low];
	while (low < high) {
		while (low < high&&arr[high] >= pivotkey)
			high--;
		swap(arr[low], arr[high]);
		while (low < high&&arr[low] <= pivotkey)
			low++;
		swap(arr[low], arr[high]);
	}
	return low;
}

// 对arr[l...r]部分进行快速排序
void quickSort(int *arr, int l, int r) {

	if (l >= r)
		return;

	int p = partition(arr, l, r);	//得到l处元素应该处于的位置 p
	quickSort(arr, l, p - 1);		//对前半部分(l到p-1)的元素进行快速排序
	quickSort(arr, p + 1, r);		//对后半部分(p+1到r)的元素进行排序
}
  • 查找算法

二、树

  • 遍历
//树的定义
typedef struct BiTree {
	int data;
	BiTree *leftChild;
	BiTree *rightChild;
}*T;

先序遍历:

//先访问根节点,再访问左子树,最后访问右子树
//递归遍历
void preOrder(BiTree *T) {
	if (T != NULL) {
		visit(T);
		preOrder(T -> leftChild);
		preOrder(T -> rightChild);
	}
}

//非递归遍历
void PreOrder(BiTree *root) {
	//判断是否为空树,空树直接返回
	if (root == NULL){
		cout<<"Empty Tree!" << endl;
		return ;
	}
	InitStack(S);		//创建栈
	
	//循环结束条件为当前节点为空且栈为空
	while (root != NULL || !StackEmpty(S)) {
		if (root != NULL) {
			//当前节点不为空,访问当前节点
			visit(root);
			//右子节点不为空时入栈右子节点
			if (root->rightChild != NULL)
				Push(S, root->rightChild);
			//指向左子节点
			root = root->leftChild;
		} else {
			//当前节点为空时,访问栈顶元素
			Pop(S, root);
		}
	}
	
}

中序遍历:

//先访问左子树,再访问根节点,最后访问右子树
//递归遍历
void inOrder(BiTree *T) {
	if (T != NULL) {
		inOrder(T -> leftChild);
		visit(T);
		inOrder(T -> rightChild);
	}
}

//非递归遍历
void InOrder(BiTree *root) {
	//判断是否为空树,空树直接返回
	if (root == NULL){
		cout<<"Empty Tree!" << endl;
		return ;
	}
	InitStack(S);			//创建栈

	//循环结束条件为当前节点为空且栈为空
	while (root != NULL || StackEmpty(S)) {
		if (root != NULL) {	//当前节点不为空,入栈;指向左子树
			Push(S, root);
			root = root->leftChild;
		} else {			//当前节点为空,访问栈顶元素;指向右子树
			Pop(S, root);
			visit(root);
			root = root->rightChild;
		}
	}

}

后续遍历:

//先访问左子树,再访问右子树,最后访问根节点
void postOrder(BiTree *T) {
	if (T != NULL) {
		postOrder(T->leftChild);
		postOrder(T->rightChild);
		visit(T);
	}
}

//非递归
//思想:后序遍历为左右跟,可以先根右左访问,再倒置
void PostOrder(BiTree* root) {
	//判断是否为空树,空树直接返回
	if (root == NULL){
		cout<<"Empty Tree!" << endl;
		return ;
	}
	InitStack(S);
	InitStack(Data);
	int data;

	//循环结束条件为当前节点为空且栈为空
	while (root != NULL || !StackEmpty(S)) {
		if (root != NULL) {
			//当前节点不为空,入栈当前节点值
			Push(Data, root->data);
			//右子节点不为空时入栈左子节点
			if (root->leftChild != NULL)
				Push(S, root->leftChild);
			//指向右子节点
			root = root->rightChild;
		}
		else {
			//当前节点为空时,访问栈顶元素
			Pop(S, root);
		}
	}
	
	//倒序输出节点值(由“根右左”变为“左右根”)
	while (StackEmpty(Data)) {
		Pop(Data, data);
		cout << data;
	}
}

层次遍历

//二叉树层次遍历
void LevelOrder(BiTree *root) {
	InitQueue(Q);						//初始化指针
	BiTree tmp;							//创建临时变量用于访问节点
	
	Q.push(root);						//入队根节点

	while (!Q.empty()) {

		tmp = Q.pop();					//取出队头元素,并访问
		visit(tmp);

		if (tmp.leftChild != NULL)		//判断左子树是否为空,不为空时加入队列
			Q.push(tmp.leftChild);
		if (tmp.rightChild != NULL)		//判断右子树是否为空,不为空时加入队列
			Q.push(tmp.rightChild);
	}
}

  • 堆排序
    大根堆

void HeapAdjust(int *arr, int low, int high) {

	int rc = arr[low];									//rc为本次调整的根的值
	
	for (int j = 2 * low; j < high; j *= 2) {

		if (j < high && arr[j] < arr[j + 1])	//j为rc左右子树中较大的(j<high保证了不会越界)
			j++;

		if (rc > arr[j])									//以rc为根的子树符合大根堆,直接退出调整
			break;

		//调整以rc为根的子树,使得根节点大于左右子树
		arr[low] = arr[j];
		low = j;	
	}
	arr[low] = rc;
}

void HeapSort(int *arr,int length) {
	
	for (int i = length / 2; i > 0; i--)		//对数组进行堆排序
		HeapAdjust(arr, i, length);

	for (int i = length; i > 1; i--) {			//依次输出数组
		cout << arr[1];
		arr[1] = arr[i];
		HeapAdjust(arr, 1, i - 1);
	}
}

小根堆


void HeapAdjust(int *arr, int low, int high) {

	int rc = arr[low];									//rc为本次调整的根的值
	
	for (int j = 2 * low; j < high; j *= 2) {

		if (j < high && arr[j] > arr[j + 1])	//j为rc左右子树中较小的(j<high保证了不会越界)
			j++;

		if (rc < arr[j])									//以rc为根的子树符合大根堆,直接退出调整
			break;

		//调整以rc为根的子树,使得根节点大于左右子树
		arr[low] = arr[j];
		low = j;	
	}
	arr[low] = rc;
}

void HeapSort(int *arr,int length) {
	
	for (int i = length / 2; i > 0; i--)		//对数组进行堆排序
		HeapAdjust(arr, i, length);

	for (int i = length; i > 1; i--) {			//依次输出数组
		cout << arr[1];
		arr[1] = arr[i];
		HeapAdjust(arr, 1, i - 1);
	}
}
  • 哈夫曼树

三、图

  • 广度优先遍历
  • 深度优先遍历(计算联通分量
  • 最小生成树
  • 最短路径
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值