哈希Map总结以及机试题79:身高体重排序

28 篇文章 3 订阅

/*
某学校举行运动会,学生们按编号(1、2、3…n)进行标识,
现需要按照身高由低到高排列,
对身高相同的人,按体重由轻到重排列,
对于身高体重都相同的人,维持原有的编号顺序关系。
请输出排列后的学生编号
输入描述:
两个序列,每个序列由N个正整数组成,(0<n<=100)。
第一个序列中的数值代表身高,第二个序列中的数值代表体重,
输出描述:
排列结果,每个数据都是原始序列中的学生编号,编号从1开始,
实例一:
输入:
4
100 100 120 130
40 30 60 50
输出:
2134
*/


以下是错误的做法(或者说是可以做但是我能力做不出来的做法)

刚做时也是准备用两个Map来做,一个是身高对用下标一个是体重对应下标。然后在存放的数组中找到身高相等的对象再二者交换,之后把val值对应相应的值。

vector<int>res;
//vector<int>
multimap<int, int>hash_high;
multimap<int, int>hash_weight;
class Solution
{
public:
	
public:
	void fun_Sort() {
		sort(res.begin(), res.end());
		multimap<int, int>::iterator it1 = hash_high.begin();
		multimap<int, int>::iterator it2 = hash_weight.begin();
		for (int i = 0; i < res.size(); ++i)
		{
			it1++;
			it2++;
			if ( i + 1 < res.size()&&res[i] == res[i+1])
			{
				
				if (it2->second> (++it2)->second)//hash_weight.at(i+1) > hash_weight.at(i+2)
				{
					it2--;
					swap();//it1->first, (++it1)->first
					it1--;
					//int tmp = res[i];
					//res[i] = res[i + 1];
					//res[i + 1] = tmp;
				}
			}
		}
	}
	
};
int main()
{
	Solution s1;
	int num, val = 0;
	cin >> num;
	for (int i = 1; i <= num; i++)
	{
		cin >> val;
		hash_high.insert(pair<int,int>(val,i));
		res.push_back(val);
	}
	for (int i = 1; i <= num; i++)
	{
		cin >> val;
		hash_weight.insert(pair<int, int>(i,val ));
	}
	s1.fun_Sort();
	multimap<int, int>::iterator it=  hash_high.begin();
	
	for (it = hash_high.begin(); it != hash_high.end(); it++)
	{
		cout<< it->first << endl;
	}
		return 0;
}

输出还可以这么干(额外两种方法)
此题都要配合sort使用:

一:
for (int i = 0; i < result.size(); i++)
	{
		cout << hash_map.at(result[i]) << " ";//要配合sort使用
	}

二:
for (int i = 0; i < result.size(); i++)
	{
		auto FIND = hash_map.find(result[i]);
		cout << FIND->second;
	}

做着做着发现两点不能解决的问题:
一是map是重复的元素该怎么办?做到好久才发现有问题。
二是发现可以multimap了,但是交换元素位置时,发现交换map里的元素不可行,swap函数是交换两个容器。。。。。。。。。当然,map也是一样的。。。。。在这里插入图片描述
后来就放弃这种做法了。


正确的方法:

我发现身高和体重都是可以重复的,那么map会失效(亲测),可重map还不太会用也可能解决不 了问题。那么string 或者两个值放一起不就可以有效的放入map中正好还能排序吗?(连排序sort都省了。。。。)

这么做是否可行我还用vecotor<vector> arr测试过,排序首先排序第一个元素,第一个元素相同排序第二个。。所以我才这么做了,后来发现map弄好了都不用排序。

在这里插入图片描述


#include <algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
int main()
{
	int num;
	vector<vector<int>>result ;
	int val;
	vector<int>high;
	vector<int>weight;
	vector<int>tmp;
	map<vector<int>, int>hash_map;
	cin >> num;
	for (int i = 1; i <= num; i++)
	{
		cin >> val;
		high.push_back(val);
		
		
	}
	for (int i = 1; i <=num; i++)
	{
		cin >> val;
		weight.push_back(val);
		
	}
	for (int i = 0; i < num; i++)//将两个数据合并到同一个元素集中。
	{
		tmp.push_back(high[i]);
		tmp.push_back(weight[i]);
		result.push_back(tmp);
		hash_map.insert(pair<vector<int>, int>(tmp, i+1));//插入哈希元素
			
		tmp.clear();
	}
	map<vector<int>, int>::iterator it = hash_map.begin();
	sort(result.begin(), result.end());
		for (it = hash_map.begin(); it != hash_map.end(); it++)
		{
			cout << it->second << endl;//直接打印即可都不用排序了,map自动排。
		}

MAP用法

在这里插入图片描述
1.插入元素

 
// 第一种 用insert函數插入pair
mapStudent.insert(pair<int, string>(000, "student_zero"));
 
// 第二种 用insert函数插入value_type数据
mapStudent.insert(map<int, string>::value_type(001, "student_one"));
 
// 第三种 用"array"方式插入
mapStudent[123] = "student_first";
mapStudent[456] = "student_second";
map<string, string> dict;
dict.insert(pair<string, string>("string", "字符串"));//模板类型pair:构造了一个匿名对象插入到map
dict.insert(make_pair("apple", "苹果"));//模板函数make_pair:偷懒了,实际调的是pair
dict.insert({ "left", "左边" });
dict.insert({ "left", "剩余" });

2.删除元素
从map中删除元素的函数是erase(),该函数有如下的三种形式:

m.erase(k);第一种方法删除的是m中键为k的元素,返回的是删除的元素的个数;
m.erase( p );第二种方法删除的是迭代器p指向的元素,返回的是void;
m.erase(b, e);第三种方法删除的是迭代器b和迭代器e范围内的元素,返回void

3.map大小查询

int nSize = mapStudent.size();


4.map的元素访问
1.数组方式

下标访问,如果访问的键值不存在会和插入工作相同。
map<int ,int> m;
m[1]=111;
m[2]=222;
m[3]=333;
cout<<m[4];

2.at()访问

么有找到会抛出一个异常,比较安全的访问方式。
map<int ,int> m;
m[1]=111;
m[2]=222;
m[3]=333;
cout<<m.at(4);

**3.find(访问)(map,multimap)***********重要


    multimap<int ,int> m;
    m.insert({1,11});
    m.insert({1,12});
    m.insert({1,13});
    m.insert({1,14});
    m.insert({2,21});
    m.insert({3,31});
    auto Find=m.find(1);
    auto Count=m.count(1);
    while(Count)
    {
        cout<<Find->second<<endl;
        Find++;
        Count--;
    }

此时可以输出所有key=1的 元 素,multimap容器的 元 素添 加方 式不同于map,不能直接用m[key]=value 的 方 式直 接 添加元素,必 须 用insert或者emplace。

multimap不存在operate【】和at().

在这里插入图片描述
multimap获取可以获取相同键元素:
在这里插入图片描述
4 一种面向迭代器的解决方法lower_bound\upper_bound


```clike
  multimap<int ,int> m;
    m.insert({1,11});
    m.insert({1,12});
    m.insert({1,13});
    m.insert({1,14});
    m.insert({2,21});
    m.insert({3,31});
    for(auto lo=m.lower_bound(1),hi=m.upper_bound(2);lo!=hi;lo++)
    {
        cout<<lo->second<<endl;
    }

11
12
13
14
21
可以见到,此时不仅可以输出key为1的元素,也能输出key为2的元素。


set和map特性和区别




set是一种关联式容器,其特性如下:

set以RBTree作为底层容器
所得元素的只有key没有value,value就是key
不允许出现键值重复
所有的元素都会被自动排序
不能通过迭代器来改变set的值,因为set的值就是键
**********************************************************************888
map和set一样是关联式容器,它们的底层容器都是红黑树,区别就在于map的值不作为键,键和值是分开的。它的特性如下:

map以RBTree作为底层容器
所有元素都是键+值存在
不允许键重复
所有元素是通过键进行自动排序的
map的键是不能修改的,但是其键对应的值是可以修改的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值