c++查找与排序

目录

搜索

1、顺序搜索

2、二分搜索

排序

1、冒泡排序

2、选择排序

3、插入排序

4、快速排序

5、堆排序

6、归并排序

7、希尔排序

8、基数排序

9、计数排序

10、桶排序

搜索

1、顺序搜索

  • 适用于所有数组
int linearSearch(vector<int>& nums, int target) {
	for (int i = 0; i < nums.size(); i++) {
		if (nums[i] == target) return i;
	}
	return -1;
}

2、二分搜索

  •  只适用于排好序的数组
int binarySearch(vector<int>& nums, int target) {
	int left = 0, right = nums.size() - 1;
	while (left <= right) {
		int mid = left + (right - left) / 2;
		if (nums[mid] == target) return mid;
		if (nums[mid] > target) right = mid - 1;
		else left = mid + 1;
	}
	return -1;
}

排序

1、冒泡排序

  • LB三人组之一------O(n^2)
// 1-1、冒泡排序
vector<int> bobbleSort(vector<int>& nums) {
	for (int i = 0; i < nums.size() - 1; i++) {    // n-1趟
		for (int j = 0; j < nums.size() - 1 - i; j++) {  // 未排好序区间
			if (nums[j] > nums[j + 1]) {
				int tmp = nums[j];      // 交换
				nums[j] = nums[j + 1];
				nums[j + 1] = tmp;
			}
		}
	}
	return nums;
}

// 1-2、冒泡排序改进:一趟未交换说明已经排好序了
vector<int> bobbleSort1(vector<int>& nums) {
	for (int i = 0; i < nums.size() - 1; i++) {
		bool exchange = false;   // 标志位
		for (int j = 0; j < nums.size() - 1 - i; j++) {
			if (nums[j] > nums[j + 1]) {
				int tmp = nums[j];
				nums[j] = nums[j + 1];
				nums[j + 1] = tmp;
				exchange = true;  // 交换了标志位改变
			}
		}
		if (!exchange) return nums;
	}
	return nums;
}

2、选择排序

  • 每次选择最小值排序
  • LB三人组之一------O(n^2)
// 2-1、选择排序(非原地排序)
vector<int> selectSort(vector<int>& nums) {
	vector<int> res;
	for (int i = 0; i < nums.size(); i++) {
		int index = 0, minVal = nums[0];
		for (int j = 1; j < nums.size(); j++) {  // 获得最小值
			if (nums[j] < minVal) {
				index = j;
				minVal = nums[j];
			}
		}
		res.push_back(minVal);
		nums[index] = 1000;   // 最小值位置用一个较大数覆盖
	}
	return res;
}

// 2-2、选择排序改进(原地排序)
vector<int> selectSort1(vector<int>& nums) {
	for (int i = 0; i < nums.size() - 1; i++) {
		int index = i;
		for (int j = i + 1; j < nums.size(); j++) {
			if (nums[index] > nums[j]) index = j;  // 确定最小值索引
		}
		if (index != i) {  // 不是原位置才需交换
			int tmp = nums[i];
			nums[i] = nums[index];
			nums[index] = tmp;
		}
	}
	return nums;
}

3、插入排序

  • 每次选数插入到适合位置,即已经选好的数排好序
  • LB三人组之一------O(n^2)
// 3、插入排序
vector<int> insertSort(vector<int>& nums) {
	for (int i = 1; i < nums.size(); i++) {
		int tmp = nums[i];  // 摸到的数
		int index = i - 1;  // 手里数下标
		while (index >= 0 && nums[index] > tmp) {
			nums[index + 1] = nums[index]; // 右移
			index--;
		}
		nums[index + 1] = tmp;  // 找到适合位置放入
	}
	return nums;
}

4、快速排序

  1. 选取一个数,使这个数归位
  2. 即数组被分为两部分,左边都比这个数小,右边都比这个数大
  3. 递归完成排序
  • NB三人组之一------O(n*log(n))
// 4、快速排序
int partition(vector<int>& nums, int left, int right) {
	int tmp = nums[left];  // 选取的数
	while (left < right) {
		while (left < right && nums[right] >= tmp) right--;
		nums[left] = nums[right];  // 小数放左边
		while (left < right && nums[left] <= tmp) left++;
		nums[right] = nums[left];  // 大数放右边
	}
	nums[left] = tmp;  // 选取的数放回数组
	return left;
}

vector<int> quickSort(vector<int>& nums, int left, int right) {
	if (left < right) {
		int mid = partition(nums, left, right);  // 归位函数
		quickSort(nums, left, mid - 1);
		quickSort(nums, mid + 1, right);
	}
	return nums;
}

5、堆排序

  1. 建堆---农村包围城市(从最后一个孩子节点的父节点开始一步步使得子树有序)
  2. 得到堆顶元素为最大值
  3. 去掉堆顶,将最后一个元素置于堆顶,通过一次向下调整使堆有序
  4. 堆顶为第二大元素
  5. 重复步骤3
  • NB三人组之一------O(n*log(n))
// 5、堆排序
// 大根堆------父节点的值大于左右孩子节点的值
void siftLarge(vector<int>& nums, int low, int high) {
	int i = low;  // 根节点
	int j = 2 * i + 1;  // 左孩子节点
	int tmp = nums[low]; // 堆顶元素
	while (j <= high) {
		if (j + 1 <= high && nums[j] < nums[j + 1]) j++;  // 右孩子大
		if (nums[j] > tmp) {
			nums[i] = nums[j];
			i = j;
			j = 2 * i + 1;
		}
		else {
			nums[i] = tmp;  // 找到适合位置放入
			break;
		}
	}
	nums[i] = tmp;  // 放在叶子节点
}

vector<int> heapSort(vector<int>& nums) {
	int n = nums.size() - 1;
	for (int i = (n - 1) / 2; i >= 0; i--) {  // 建堆
		siftLarge(nums, i, n);
	}
	for (int i = n; i >= 0; i--) {
		int tmp = nums[0];   // 交换堆顶和最后一个元素
		nums[0] = nums[i];
		nums[i] = tmp;
		siftLarge(nums, 0, i-1);
	}
	return nums;
}

堆排序应用------topk问题

  • 排序后切片   O(nlogn)
  • LB三人组      O(kn)
  • 堆排序思想   O(nlogk)
  1. 选取k个元素建立小根堆------堆顶就是第k大元素
  2. 每次从剩下元素中选取一个元素,if<堆顶,忽略;else置于堆顶并向下调整
  3. 倒序弹出堆顶
// 堆排序应用---topk问题
// 小根堆------父节点的值小于左右孩子节点的值
void siftSmall(vector<int>& nums, int low, int high) {
	int i = low;  // 根节点
	int j = 2 * i + 1;  // 左孩子节点
	int tmp = nums[low]; // 堆顶元素
	while (j <= high) {
		if (j + 1 <= high && nums[j] > nums[j + 1]) j++;  // 右孩子小
		if (nums[j] < tmp) {
			nums[i] = nums[j];
			i = j;
			j = 2 * i + 1;
		}
		else {
			nums[i] = tmp;  // 找到适合位置放入
			break;
		}
	}
	nums[i] = tmp;  // 放在叶子节点
}

vector<int> topk(vector<int>& nums, int k) {
	vector<int> heap;
	for (int i = 0; i < k; i++) heap.push_back(nums[i]);   // 取前k个元素
	for (int i = (k - 2) / 2; i >= 0; i--) siftSmall(heap, i, k - 1);  // 建小跟堆
	for (int i = k; i < nums.size(); i++) {  
		if (nums[i] > heap[0]) {     // 大于堆顶元素替换并向下调整
			heap[0] = nums[i];
			siftSmall(heap, 0, k - 1);
		}
	}
	for (int i = k-1; i >= 0; i--) {
		int tmp = heap[0];   // 交换堆顶和最后一个元素
		heap[0] = heap[i];
		heap[i] = tmp;
		siftSmall(heap, 0, i - 1);
	}
	return heap;
}

6、归并排序

  1. 分解------将数组越分越小,直到分成一个元素
  2. 终止条件------一个元素是有序的
  3. 合并------将元素数组合并,越来越大
  • NB三人组之一------O(n*log(n))
// 6、归并排序
void merge(vector<int>& nums, int left, int mid, int right) {
	vector<int> ltmp;
	int i = left;
	int j = mid + 1;
	while (i <= mid && j <= right) {  // 两边都有数
		if (nums[i] < nums[j]) {
			ltmp.push_back(nums[i]);
			i++;
		}
		else {
			ltmp.push_back(nums[j]);
			j++;
		}
	}
	while (i <= mid) {     // 一边没数
		ltmp.push_back(nums[i]);
		i++;
	}
	while (j <= right) {
		ltmp.push_back(nums[j]);
		j++;
	}
	int index = 0;   // 更新nusm
	for (int k = left; k <= right; k++) {
		nums[k] = ltmp[index];
		index++;
	}
}

vector<int> mergeSort(vector<int>& nums, int left, int right) {
	if (left < right) {
		int mid = left + (right - left) / 2;
		mergeSort(nums, left, mid);
		mergeSort(nums, mid + 1, right);
		merge(nums, left, mid, right);
	}
	return nums;
}

7、希尔排序

8、基数排序

9、计数排序

10、桶排序

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树排序查找的代码如下所示: ```c++ #include<iostream> using namespace std; //定义二叉树结点 struct TreeNode{ int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL){} }; //插入结点 TreeNode* insertNode(TreeNode* root, int val){ if(root == NULL){ return new TreeNode(val); } if(val < root->val){ root->left = insertNode(root->left, val); }else{ root->right = insertNode(root->right, val); } return root; } //搜索结点 TreeNode* searchNode(TreeNode* root, int val){ if(root == NULL || root->val == val){ return root; } if(val < root->val){ return searchNode(root->left, val); }else{ return searchNode(root->right, val); } } //删除结点 TreeNode* deleteNode(TreeNode* root, int val){ if(root == NULL){ return root; } if(val < root->val){ root->left = deleteNode(root->left, val); }else if(val > root->val){ root->right = deleteNode(root->right, val); }else{ if(root->left == NULL){ TreeNode* temp = root->right; delete root; return temp; }else if(root->right == NULL){ TreeNode* temp = root->left; delete root; return temp; }else{ TreeNode* temp = root->right; while(temp->left != NULL){ temp = temp->left; } root->val = temp->val; root->right = deleteNode(root->right, temp->val); } } return root; } //中序遍历 void inorderTraversal(TreeNode* root){ if(root == NULL){ return; } inorderTraversal(root->left); cout << root->val << " "; inorderTraversal(root->right); } int main(){ TreeNode* root = NULL; root = insertNode(root, 10); insertNode(root, 5); insertNode(root, 15); insertNode(root, 3); insertNode(root, 8); insertNode(root, 12); insertNode(root, 20); cout << "中序遍历结果为:"; inorderTraversal(root); cout << endl; TreeNode* node = searchNode(root, 12); if(node != NULL){ cout << "查找到结点:" << node->val << endl; }else{ cout << "未找到该结点!" << endl; } root = deleteNode(root, 15); cout << "删除15后中序遍历结果为:"; inorderTraversal(root); cout << endl; return 0; } ``` 这段代码实现了二叉树排序查找的基本操作,包括插入结点、搜索结点、删除结点以及中序遍历等。其中,`insertNode`函数用于插入结点,`searchNode`函数用于搜索结点,`deleteNode`函数用于删除结点,`inorderTraversal`函数用于中序遍历二叉树。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值