Array sorting backwards? - c++

Okay so I have this function that takes an array and sorts it by using swap sort(?) however when I enter the numbers it sorts it from largest to smallest instead of smallest to largest.
I went through and did this to see what happens each step of the way however it all seems correct to me.
iterator = &first element
temp = smallest number
tempstore = &smallest number
val tempstore = val first element
val first element = val temp
If i change it so that
if(array[i] < *iterator)
becomes:
if(array[i] > *iterator)
it works perfectly but I don't understand this as now it is testing to see if the number is larger and I want smaller.
I know I should probably be using a vector but I am still a newbie and I am yet to learn them. Thanks for any help.
int *sort(int *array, int size)
{
int temp, *iterator, *tempStore;
for(int j = 0; j < size; j++)
{
iterator = &array[j];
for(int i = 0; i < size; i++)
{
if(array[i] < *iterator)
{
temp = array[i];
tempStore = &array[i];
*tempStore = *iterator;
*iterator = temp;
}
}
}
return array;
}

Your algorithm compares the first element of the array with all the subsequent, so when you use:
if(array[i] > *iterator)
you swap the first element with the ith element every time the ith element is greater than the first. So at the end of the first pass you have the greatest element in the first position. if you use the < operator, you get the smallest in front.
Then the second pass should compare the second element of the array with all the subsequent and so on, that's why i needs to start iterating from j + 1.
As you saw it is not straightforward to read and understand the code, moreover the algorithm itself is very poor (it looks like a selection sort with some extra swaps). You do not necessarily need to use a std::vector but you really should learn the standard library.
This is the C++11 way to do it:
#include <algorithm> //for std::sort
#include <iterator> //for std::begin/end
#include <functional> //for std::greater
int v[1000];
... fill v somehow ...
std::sort(std::begin(v), std::end(v), std::greater<int>());
Compact, clear and extremely fast.

Related

Pick every element once from sorted array

I have a sorted array and I want to take every element once into an other array
Example:
Input: array[] = { 1,2,2,3,3,5 }
Output: array2[] = { 1,2,3,5 }
Here is my attempt
int db = 0,array2[100];
for(int i = 0;i < k;i++){
int j = 0;
for(j = 0;j < db;j++){
if(array[i] == array2[j]){
break;
}
}
if(i == j){
array2[db] == array[i];
db++;
}
}
/* PRINT
for(int i = 0;i < db;i++){
cout<<array2[i]<<" ";
}
cout<<endl;*/
There's a standard algorithm std::unique_copy that does exactly this:
auto end = std::unique_copy(std::begin(array), std::end(array), array2);
The returned iterator end points to one past the last element that is inserted into array2, so you can calculate the number of unique elements that were copied like this:
auto num = std::distance(array2, end);
I would recommend using std::vector instead of arrays anyway, and then you don't have to worry about computing the number of copied unique elements. In case you use a vector the 3rd argument to the algorihtm would be std::back_inserter(vec).
We can't give you an answer about what happened to your code if we don't know what k is.
But generally, if you want unique values from a sorted array, the quick way to do it is just employ the set.
#include <set>
then set<int, greater<int> > s1;
for (int i: array) s1.insert(i);
this will only add unique value in the new vector in increasing order.

Can you change a pointer in loop?

Let's say I have a vector of integers:
vector<int> v(n);
Which I fill up in a for loop with valid values. What I want to do is to find a index of a given value in this vector. For example if I have a vector of 1, 2, 3, 4 and a value of 2, i'd get a index = 1. The algorithm would assume that the vector is sorted in ascending order, it would check a middle number and then depending of it's value (if its bigger or smaller than the one we're asking for) it would check one of halves of the vector. I was asked to do this recursive and using pointer. So I wrote a void function like:
void findGiven(vector<int> &v){
int i = 0;
int *wsk = &v[i];
}
and I can easily access 0th element of the vector. However I seem to have some basic knowledge lacks, because I can't really put this in a for loop to print all the values. I wanted to do something like this:
for (int j = 0; j<v.size(); j++){
cout << *wsk[j];
}
Is there a way of doing such a thing? Also I know it's recurisve, I'm just trying to figure out how to use pointers properly and how to prepare the algorithm so that later I can build it recursively. Thanks in advance!
The correct way is:
for (int wsk : v) {
cout << wsk;
}
If you insist on pointers:
int* first = v.data();
for (size_t j = 0; j < v.size(); ++j) {
cout << first[j];
}

deleting multiple elements in an array

i am trying to write a code that will delete all the elements if an array has same element at different index . it works fine for one element deletion or elements at odd index i.e 1,3,5 etc but it neglects one element if the consecutive index have same element.
i have just tried this to get my hands on arrays
for(int i=0;i<n;i++) //for deletion
{
if(arr[i]==_delete)
{
arr[i]=arr[i+1];
--n;
}
}
I suggest you use std::vector as a container for your objects.
std::vector<TYPE> vec ;
// initialise vector
You can use
vec.erase(std::remove_if(vec.begin(), vec.end(),
[](const auto & item){return item == _delete;}), vec.end());
Alternatively, you can use std::list. Its list::erase has linear time complexity.
As an additional solution, if you want to deal with built-in C++ arrays, the standard std::remove algorithm can be rewritten like this:
void remove(int _delete) {
int j = 0;
for (int i = 0; i < n; ++i) {
if (arr[i] != _delete) {
arr[j++] = arr[i];
}
}
// update the size!
n = j;
}
It's quite pretty:
We keep in the array the elements we only need, and override the ones in which we are not interested (they can be either equal or not to _delete and start at position j till the end)

Finding the minimum distance between any pair of equal elements in an array

Given some array of integers A = [a0, a1, ..., an], find the minimum distance between ai and aj such that ai = aj and i != j (or indicate that no such indices exist).
So I've implemented a naive O(n2) approach in C++, involving iterating through the array looking for equal elements and updating the minimum distance appropriately:
#include <vector>
#include <climits>
#include <algorithm>
int MinPair(const std::vector<int>& nums)
{
int ret = std::numeric_limits<int>::max();
for(int i = 0; i != nums.size(); ++i)
{
for(int j = 0; j != i; ++j)
{
if(nums[i] == nums[j])
ret = std::min(ret, i - j);
}
}
if(ret == std::numeric_limits<int>::max())
return -1;
return ret;
}
This works well, but I was told that a more "efficient" implementation exists involving std::map, without much clarification on what is more efficient. Namely, one could walk through the input array and store the first occurrence of an element within a map, and for every subsequent occurrence find the distance between that occurrence and the first index of that element in the map. If that distance is less than the current minimum, then we update that minimum.
However, I fail to see in what way this is more "efficient." Time complexity-wise, you would still have to walk through the input array (O(n)), and using std::map::find to identify whether or not an element is the first occurrence or not is also O(n), giving a total complexity of O(n2). Space complexity-wise you have to store a map in addition to the array/vector. What exactly am I missing here?
EDIT: I incorrectly assumed map::find was O(n); insertion and find operations are in fact O(log n), which one can immediately see even assuming basic implementations using something like binary search.
I originally posted a coding solution that was similar to the solution mentioned by grigor. Then I realized there was an obvious optimization that makes the whole thing work in O(N) time for best case and average case.
typedef pair<bool, int> LastPositionFound;
int MinPair(const std::vector<int>& nums)
{
unordered_map<int, LastPositionFound> table; // maps value found in array to the last position that value was seen at.
int best_distance = -1;
for (size_t index = 0; index < nums.size(); index++)
{
int value = nums[index];
LastPositionFound& lpf = table[value]; // returns {false,0} if not found
if (lpf.first)
{
int distance = index - lpf.second;
if ((distance < best_distance) || (best_distance == -1))
{
best_distance = distance;
}
}
// update reference to hash table entry
lpf.first = true;
lpf.second = index;
}
return best_distance;
}
You could map each element to a set of its indices. So you'd have something like a map<int, set<int>> m, and go through your vector: for(int i = 0, i < nums.size(); ++i) m[nums[i]].insert(i). After that you can iterate through the map and if an element has more than one index find the minimum distance between indices. Should be O(nlog(n)).

Find the biggest 3 numbers in a vector

I'm trying to make a function to get the 3 biggest numbers in a vector. For example:
Numbers: 1 6 2 5 3 7 4
Result: 5 6 7
I figured I could sort them DESC, get the 3 numbers at the beggining, and after that resort them ASC, but that would be a waste of memory allocation and execution time. I know there is a simpler solution, but I can't figure it out. And another problem is, what if I have only two numbers...
BTW: I use as compiler BorlandC++ 3.1 (I know, very old, but that's what I'll use at the exam..)
Thanks guys.
LE: If anyone wants to know more about what I'm trying to accomplish, you can check the code:
#include<fstream.h>
#include<conio.h>
int v[1000], n;
ifstream f("bac.in");
void citire();
void afisare_a();
int ultima_cifra(int nr);
void sortare(int asc);
void main() {
clrscr();
citire();
sortare(2);
afisare_a();
getch();
}
void citire() {
f>>n;
for(int i = 0; i < n; i++)
f>>v[i];
f.close();
}
void afisare_a() {
for(int i = 0;i < n; i++)
if(ultima_cifra(v[i]) == 5)
cout<<v[i]<<" ";
}
int ultima_cifra(int nr) {
return nr - 10 * ( nr / 10 );
}
void sortare(int asc) {
int aux, s;
if(asc == 1)
do {
s = 0;
for(int i = 0; i < n-1; i++)
if(v[i] > v[i+1]) {
aux = v[i];
v[i] = v[i+1];
v[i+1] = aux;
s = 1;
}
} while( s == 1);
else
do {
s = 0;
for(int i = 0; i < n-1; i++)
if(v[i] < v[i+1]) {
aux = v[i];
v[i] = v[i+1];
v[i+1] = v[i];
s = 1;
}
} while(s == 1);
}
Citire = Read
Afisare = Display
Ultima Cifra = Last digit of number
Sortare = Bubble Sort
If you were using a modern compiler, you could use std::nth_element to find the top three. As is, you'll have to scan through the array keeping track of the three largest elements seen so far at any given time, and when you get to the end, those will be your answer.
For three elements that's a trivial thing to manage. If you had to do the N largest (or smallest) elements when N might be considerably larger, then you'd almost certainly want to use Hoare's select algorithm, just like std::nth_element does.
You could do this without needing to sort at all, it's doable in O(n) time with linear search and 3 variables keeping your 3 largest numbers (or indexes of your largest numbers if this vector won't change).
Why not just step through it once and keep track of the 3 highest digits encountered?
EDIT: The range for the input is important in how you want to keep track of the 3 highest digits.
Use std::partial_sort to descending sort the first c elements that you care about. It will run in linear time for a given number of desired elements (n log c) time.
If you can't use std::nth_element write your own selection function.
You can read about them here: http://en.wikipedia.org/wiki/Selection_algorithm#Selecting_k_smallest_or_largest_elements
Sort them normally and then iterate from the back using rbegin(), for as many as you wish to extract (no further than rend() of course).
sort will happen in place whether ASC or DESC by the way, so memory is not an issue since your container element is an int, thus has no encapsulated memory of its own to manage.
Yes sorting is good. A especially for long or variable length lists.
Why are you sorting it twice, though? The second sort might actually be very inefficient (depends on the algorithm in use). A reverse would be quicker, but why even do that? If you want them in ascending order at the end, then sort them into ascending order first ( and fetch the numbers from the end)
I think you have the choice between scanning the vector for the three largest elements or sorting it (either using sort in a vector or by copying it into an implicitly sorted container like a set).
If you can control the array filling maybe you could add the numbers ordered and then choose the first 3 (ie), otherwise you can use a binary tree to perform the search or just use a linear search as birryree says...
Thank #nevets1219 for pointing out that the code below only deals with positive numbers.
I haven't tested this code enough, but it's a start:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> nums;
nums.push_back(1);
nums.push_back(6);
nums.push_back(2);
nums.push_back(5);
nums.push_back(3);
nums.push_back(7);
nums.push_back(4);
int first = 0;
int second = 0;
int third = 0;
for (int i = 0; i < nums.size(); i++)
{
if (nums.at(i) > first)
{
third = second;
second = first;
first = nums.at(i);
}
else if (nums.at(i) > second)
{
third = second;
second = nums.at(i);
}
else if (nums.at(i) > third)
{
third = nums.at(i);
}
std::cout << "1st: " << first << " 2nd: " << second << " 3rd: " << third << std::endl;
}
return 0;
}
The following solution finds the three largest numbers in O(n) and preserves their relative order:
std::vector<int>::iterator p = std::max_element(vec.begin(), vec.end());
int x = *p;
*p = std::numeric_limits<int>::min();
std::vector<int>::iterator q = std::max_element(vec.begin(), vec.end());
int y = *q;
*q = std::numeric_limits<int>::min();
int z = *std::max_element(vec.begin(), vec.end());
*q = y; // restore original value
*p = x; // restore original value
A general solution for the top N elements of a vector:
Create an array or vector topElements of length N for your top N elements.
Initialise each element of topElements to the value of your first element in your vector.
Select the next element in the vector, or finish if no elements are left.
If the selected element is greater than topElements[0], replace topElements[0] with the value of the element. Otherwise, go to 3.
Starting with i = 0, swap topElements[i] with topElements[i + 1] if topElements[i] is greater than topElements[i + 1].
While i is less than N, increment i and go to 5.
Go to 3.
This should result in topElements containing your top N elements in reverse order of value - that is, the largest value is in topElements[N - 1].