A Star algorithm in C implementation with arrays? - c

I'm new here. I am trying to implement A-Star algorithm in C by myself. I don't know how to use Hashmaps or Lists (but i am open too learn as long as they are simple enough for me) so I use arrays.
The problem is simple: There is a NxN array. You can either go up/down or left/right, no diagonial. Horizontal is better (less cost =5) than vertical movement (high cost=10).
There are some obstacle-cells. Free cells are represented by number 0 in the NxN array, while obstacle cells with the number 9. The obstacle cells occur as a proportion of the area of the table (for example if the table is 10*10 and the independent possibility to have an obstacle in each cell is 0.1, there will be approximately 10 9's in the table.
With the number 1 the starting point is represented and with 2 and 3 the two final goals to go, G1 and G2.
I have tried this below:
#include<stdio.h>
#include <stdlib.h>
int main(void) {
//create a NxN array
int N, sX, sY, g1X,g1Y,g2X,g2Y,i,j,w;
double p;
float r;
printf("Give N\n");
scanf("%d",&N);
printf("Give p\n");
scanf("%lf",&p);
printf("Give S x k y\n");
scanf("%d",&sX);
scanf("%d",&sY);
printf("Give G1 x & y\n");
scanf("%d",&g1X);
scanf("%d",&g1Y);
printf("Give G2 x & y\n");
scanf("%d",&g2X);
scanf("%d",&g2Y);
int table[N][N];
for(i=0; i<N; i++){
for (j=0; j<N; j++){
r=(float)(rand() % 10)/10; // [0,1)
// printf("%f",&r);
if (sX==i && sY==j){
table[i][j]=1;
// printf("1");
}
else if(g1X==i && g1Y==j){
table[i][j]=2;
// printf("2");
}
else if( g2X==i && g2Y==j){
table[i][j]=3;
// printf("3");
}
else if (p>=0 && r<=p){
table[i][j]=9;
// printf("9");
}
else{
table[i][j]=0;
// printf("0");
}
printf("%d ",table[i][j]);
}
printf("\n");
}
// Create the open list
int cX=sX, cY=sY;
while (cX!=g1X && cY!=g1Y)
{
int openList[4][2];
//TOP
if(cX>0 && table[cX-1][cY]!=9){
openList[0][0]=(cX-1);
openList[0][1]=cY;
}
else{
openList[0][0]=-1;
openList[0][1]=-1;
}
//BOTTOM
if(cX+1<N && table[cX+1][cY]!=9 ){
openList[1][0]=(cX+1);
openList[1][1]=cY;
}
else{
openList[1][0]=-1;
openList[1][1]=-1;
}
//RIGHT
if(cY+1<N && table[cX][cY+1]!=9){
openList[2][0]=cX;
openList[2][1]=(cY+1);
}
else{
openList[2][0]=-1;
openList[2][1]=-1;
}
//LEFT
if(cY>0 && table[cX][cY-1]!=9){
openList[3][0]=cX;
openList[3][1]=(cY-1);
}
else{
openList[3][0]=-1;
openList[3][1]=-1;
}
printf("Open List of current cell:%d,%d\n",&cX, &cY);
for (i=0;i<4;i++){
printf("%d , %d\n",openList[i][0],openList[i][1]);
cX=g1X; cY=g2Y;
}
}
return 0;
}
Questions:
I know I didn't yet add the current cell in the open list. I should add it right?
Both the openlist and the closed list should be a Hashmap?
How do you think I should keep a connection with the parent of selected cell?

The open list needs to be a priority queue. That is a queue that allows new entrants to "push in" according to their priority or importance, but we always shrink by taking from the front. Now you can do this naively with an array and sorting on each insertion, but that will be slow. A linked list won't help much (linked lists have very bad cache performance). Really you need a specially-written priority queue which keeps as much as possible together in memory.

Related

Segment Tree to compute frequencies

Is there any way to use a Segment Tree structure to compute the frequency of a given value in an array?
Suppose there is an array A of size N, and every element A[i] of the array contains the value 0, 1 or 2. I want to perform the following operations:
Compute the amount of zeroes in any range [a,b] of the array
Increment (mod 3) every element in in any range [a,b] of the array
Example: If A = [0,1,0,2,0]:
Query[2,4] must return 1 , since there is one 0 in the range [2,4]
Increment[2,4] updates A to [0,2,1,0,0]
This looks really similar to the Range Sum Query problem, which can be solved using Segment Trees (in this case using Lazy Propagation because of range updates), but i had no success adapting my seg tree code to this problem, because if i store the values in the tree like in a normal RSQ, any parent node which contains the value "3" (for example) wouldn't mean nothing, since with this information i can't extract how much zeroes are present in this range.
Thanks in advance!
--
EDIT:
Segment Trees are binary tree structures that store intervals related to an array in its nodes. The leaf nodes store the actual array cells, and each parent node stores a function f(node->left, node->right) of its children. Segment Trees are commonly used to perform Range Sum Queries, in which we want to compute the sum of all elements in a range [a,b] of the array. In this case, the function computed by the parent nodes is the sum of the value in its children nodes. We want to use segtrees to solve the Range Sum Query problem because it allows to solve it in O(log n) (we only need to descend the tree until we find the nodes that are completely covered by our range query), much better than the naive O(n) algorithm.
Since actual array values are stored in the leaves (level L), let the nodes at level L - 1 store how many zeros they contain (which will be a value in the range [0, 2]). Other than that, everything is the same, the rest of the nodes will compute f(node->left, node->right) as node->left + node->right and the count of zeros will be propagated to the root.
After incrementing a range, if that range contained no zeros than nothing needs to be done. If however that range had zeros, then all those zeros will now be ones and the function value of current node (call it F) now becomes just zero. That change in the value now needs to be propagated upwards to the root, each time subtracting F from the function values.
This question can be easily solved using Square root decomposition
First create the new prefix sum array modulo each prefix sum by 3.
Divide the whole array into sqrt(n) blocks . Each block will have counts of number of 0's,1's and 2's. Also create one temporary array which will contain the sum to be added to the elements of the block
Here is the implementation in c++:
#include <bits/stdc++.h>
using namespace std;
#define si(a) scanf("%d",&a)
#define sll(a) scanf("%lld",&a)
#define sl(a) scanf("%ld",&a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%ld\n",a)
#define pll(a) printf("%lld\n",a)
#define sc(a) scanf("%c",&a)
#define pc(a) printf("%c",a)
#define ll long long
#define mod 1000000007
#define w while
#define pb push_back
#define mp make_pair
#define f first
#define s second
#define INF INT_MAX
#define fr(i,a,b) for(int i=a;i<=b;i++)
///////////////////////////////////////////////////////////////
struct block
{
int one;
int two;
int zero;
block()
{
one=two=zero=0;
}
};
ll a[100005],a1[100005];
ll sum[400];
int main()
{
int n,m;
cin>>n>>m;
string s;
cin>>s;
int N=(int)(sqrt(n));
struct block b[N+10];
for(int i=0;i<n;i++)
{
a[i]=s[i]-'0';
a[i]%=3;
a1[i]=a[i];
}
for(int i=1;i<n;i++)
a[i]=(a[i]+a[i-1])%3;
for(int i=0;i<n;i++)
{
if(a[i]==0)
b[i/N].zero++;
else if(a[i]==1)
b[i/N].one++;
else
b[i/N].two++;
}
w(m--)
{
int type;
si(type);
if(type==1)
{
int ind,x;
si(ind);
si(x);
x%=3;
ind--;
int diff=(x-a1[ind]+3)%3;
if(diff==1)
{
int st=ind/N;
int end=(n-1)/N;
int kl=(st+1)*N;
int hj=min(n,kl);
for(int i=st*N;i<hj;i++)
{
a[i]=(a[i]+sum[st])%3;
}
sum[st]=0;
for(int i=ind;i<hj;i++)
{
if(a[i]==0)
b[st].zero--;
else if(a[i]==1)
b[st].one--;
else
b[st].two--;
a[i]=(a[i]+diff)%3;
if(a[i]==0)
b[st].zero++;
else if(a[i]==1)
b[st].one++;
else
b[st].two++;
}
for(int i=st+1;i<=end;i++)
{
int yu=b[i].zero;
b[i].zero=b[i].two;
b[i].two=b[i].one;
b[i].one=yu;
sum[i]=(sum[i]+diff)%3;
}
}
else if(diff==2)
{
int st=ind/N;
int end=(n-1)/N;
int kl=(st+1)*N;
int hj=min(n,kl);
for(int i=st*N;i<hj;i++)
{
a[i]=(a[i]+sum[st])%3;
}
sum[st]=0;
for(int i=ind;i<hj;i++)
{
if(a[i]==0)
b[st].zero--;
else if(a[i]==1)
b[st].one--;
else
b[st].two--;
a[i]=(a[i]+diff)%3;
if(a[i]==0)
b[st].zero++;
else if(a[i]==1)
b[st].one++;
else
b[st].two++;
}
for(int i=st+1;i<=end;i++)
{
int yu=b[i].zero;
b[i].zero=b[i].one;
b[i].one=b[i].two;
b[i].two=yu;
sum[i]=(sum[i]+diff)%3;
}
}
a1[ind]=x%3;
}
else
{
int l,r;
ll x=0,y=0,z=0;
si(l);
si(r);
l--;
r--;
int st=l/N;
int end=r/N;
if(st==end)
{
for(int i=l;i<=r;i++)
{
ll op=(a[i]+sum[i/N])%3;
if(op==0)
x++;
else if(op==1)
y++;
else
z++;
}
}
else
{
for(int i=l;i<(st+1)*N;i++)
{
ll op=(a[i]+sum[i/N])%3;
if(op==0)
x++;
else if(op==1)
y++;
else
z++;
}
for(int i=end*N;i<=r;i++)
{
ll op=(a[i]+sum[i/N])%3;
if(op==0)
x++;
else if(op==1)
y++;
else
z++;
}
for(int i=st+1;i<=end-1;i++)
{
x+=b[i].zero;
y+=b[i].one;
z+=b[i].two;
}
}
ll temp=0;
if(l!=0)
{
temp=(a[l-1]+sum[(l-1)/N])%3;
}
ll ans=(x*(x-1))/2;
ans+=((y*(y-1))/2);
ans+=((z*(z-1))/2);
if(temp==0)
ans+=x;
else if(temp==1)
ans+=y;
else
ans+=z;
pll(ans);
}
}
return 0;
}

What are the possible causes of "Abnormal Program Termination" error in a C Program?

The following code is to find the number of Islands by considering 1 as island and 0 as water in a 2d array. Adjacent 1s belong to the same island and the island can be of any shape.It means
1 0 1
0 1 0
1 0 1
should give the number of islands as 1.This code runs and prints something for a 2 x 2 matrix, but shows "Abnormal termination error" for any higher order matrix.Whats wrong with the code and how to overcome the error? I just tried to make adjacent element zero recursively but ended up in this error.
#include <stdio.h>
#include <conio.h>
int a[10][10],m,n;
int islands=0;
void MakeZero(int,int);
void main()
{
int i,j;
clrscr();
printf("Enter the number of rows and columns :");
scanf("%d%d",&m,&n);
printf("Enter the matrix of 0s and 1s\n");
for(i=0;i<m;i++){
for(j=0;j<n;j++){
scanf("%d",&a[i][j]);
}
}
printf("Input Matrix is :\n");
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%d ",a[i][j]);
}printf("\n");
}
printf("The Number of Islands is :\n");
for(i=0;i<m;i++){
for(j=0;j<n;j++){
if(a[i][j])
{islands++;
MakeZero(i,j); }
}
}
printf("%d",islands);
getch();
}
void MakeZero(int i,int j)
{
if(i>m-1||j>n-1)
return;
else if(i==0&&j==0)
{
if(a[i][j+1]==1)MakeZero(i,j+1);
if(a[i+1][j+1]==1)MakeZero(i+1,j+1);
if(a[i+1][j]==1)MakeZero(i+1,j);
a[i][j+1]=a[i+1][j+1]=a[i+1][j]=0;
}
else if(i==m-1&&j==0)
{
if(a[i-1][j]==1)MakeZero(i-1,j);
if(a[i][j+1]==1)MakeZero(i,j+1);
if(a[i-1][j+1]==1)MakeZero(i-1,j+1);
a[i-1][j]=a[i][j+1]=a[i-1][j+1]=0;
}
else if(i==0&&j==n-1)
{
if(a[i][j-1]==1)MakeZero(i,j-1);
if(a[i+1][j-1]==1)MakeZero(i+1,j-1);
if(a[i+1][j]==1)MakeZero(i+1,j);
a[i][j-1]=a[i+1][j-1]=a[i+1][j]=0;
}
else if(i==m-1&&j==n-1)
{
if(a[i][j-1]==1)MakeZero(i,j-1);
if(a[i-1][j]==1)MakeZero(i-1,j);
if(a[i-1][j-1]==1)MakeZero(i-1,j-1);
a[i][j-1]=a[i-1][j]=a[i-1][j-1]=0;
}
else if(i==0&&(j>0&&j<n-1))
{
if(a[i][j-1]==1)MakeZero(i,j-1);
if(a[i][j+1]==1)MakeZero(i,j+1);
if(a[i+1][j-1]==1)MakeZero(i+1,j-1);
if(a[i+1][j+1]==1)MakeZero(i+1,j+1);
if(a[i+1][j]==1)MakeZero(i+1,j);
a[i][j-1]=a[i][j+1]=a[i+1][j-1]=a[i+1][j+1]=a[i+1][j]=0;
}
else if(i==m-1&&(j>0&&j<n-1))
{
if(a[i][j-1]==1)MakeZero(i,j-1);
if(a[i][j+1]==1)MakeZero(i,j+1);
if(a[i-1][j-1]==1)MakeZero(i-1,j-1);
if(a[i-1][j+1]==1)MakeZero(i-1,j+1);
if(a[i-1][j]==1)MakeZero(i-1,j);
a[i][j-1]=a[i][j+1]=a[i-1][j-1]=a[i-1][j+1]=a[i-1][j]=0;
}
else if(j==0&&(i>0&&i<m-1))
{
if(a[i-1][j]==1)MakeZero(i-1,j);
if(a[i+1][j]==1)MakeZero(i+1,j);
if(a[i-1][j+1]==1)MakeZero(i-1,j+1);
if(a[i+1][j+1]==1)MakeZero(i+1,j+1);
if(a[i][j+1]==1)MakeZero(i,j+1);
a[i-1][j]=a[i+1][j]=a[i-1][j+1]=a[i+1][j+1]=a[i][j+1]=0;
}
else if(j==n-1&&(i>0&&i<m-1))
{
if(a[i-1][j]==1)MakeZero(i-1,j);
if(a[i+1][j]==1)MakeZero(i+1,j);
if(a[i-1][j-1]==1)MakeZero(i-1,j-1);
if(a[i+1][j-1]==1)MakeZero(i+1,j-1);
if(a[i][j-1]==1)MakeZero(i,j-1);
a[i-1][j]=a[i+1][j]=a[i-1][j-1]=a[i+1][j-1]=a[i][j-1]=0;
}
else
{
if(a[i-1][j]==1)MakeZero(i-1,j);
if(a[i+1][j]==1)MakeZero(i+1,j);
if(a[i-1][j-1]==1)MakeZero(i-1,j-1);
if(a[i+1][j-1]==1)MakeZero(i+1,j-1);
if(a[i][j-1]==1)MakeZero(i,j-1);
if(a[i][j+1]==1)MakeZero(i,j+1);
if(a[i-1][j+1]==1)MakeZero(i-1,j+1);
if(a[i+1][j+1]==1)MakeZero(i+1,j+1);
a[i-1][j]=a[i+1][j]=a[i-1][j-1]=a[i+1][j-1]=a[i][j-1]=a[i][j+1]=a[i-1][j+1]=a[i+1][j+1]=0;
}
}
As M Oehm already said the problem is the time you mark a square as zero (or let's say "visited").
Your function MakeZero calls itself whenever it finds a square with a one in at least one of the neighbouring squares. Since you mark the square as 0 after calling MakeZero this results in a stack overflow whenever there are two neighbouring squares containing a 1 within your matrix. Since the first MakeZero finds a neighbouring 1and calls MakeZero which also finds a neighbouring 1and calls MakeZero again ... (you can see this if you look at the call stack from within the debugger).
Another thing about your MakeZero implementation: You are explicitly handling all special cases within MakeZero which make the code quite lengthy and harder to understand. I recommend to modify the function to only check if the input values are valid and the square is a one. If so set the value to zero and call MakeZero for all neighbouring squares (regardless of the current location within the matrix). An implementation would look like the following:
void MakeZero(int i, int j)
{
int x, y;
if ((i >= 0) && (i < m) && /* i index valid? */
(j >= 0) && (j < n) && /* j index valid? */
(a[i][j] == 1)) /* square is an island? */
{
a[i][j] = 0; /* remove 1 from matrix !!! */
/* iterate all surrounding squares */
for (x = (i - 1); x <= (i + 1); x++)
{
for (y = (j - 1); y <= (j + 1); y++)
{
MakeZero(x, y);
}
}
}
}
Your program provokes a stack overflow because your recursive function MakeZero() never reaches the base case. Using the same input example that you provide and just adding a printf ("%d %d\n", i, j); in the last else condition of Makezero, the program will output 1 1 indefinitely and you will never reach the condition (i > m-1 || j > n-1) that stops the program, since the values of m-1 and n-1 are 2 and i = 1 and j = 1 ad eternum.
Suggestion: try to find out what's going on when at least one of the values in the matrix a is 0, because the stack overflow seems to be happening only in this case.

Updating my array board game

So I'm creating a game. It has a 5 by 5 board filled with characters a, b and c. I need to create a function where if the board detects the same letter next to each other, it disappears and the emptied cells are replaced with a new set of letters (a,b,c). So a bit like the candy crush game. I also need to display the number of moves that are made before the game ends. Here's where I am so far
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 10
//creates board and fills in the letters randomly
int board()
{
char grid[MAX][MAX];
char letter[3] = {'a', 'b', 'c'};
int i,j,row,col;
printf("Please enter your grid size: ");
scanf("%d %d", &row, &col);
if(row < 10 && col < 10){
for(i=0; i < MAX; i++){
for(j=0; j < MAX; j++){
grid[i][j] = letter[rand()%3];
}
}
for(i=0; i < MAX; i++){
for(j=0; j < MAX; j++){
printf("%c ", grid[i][j]);
}
printf("\n");
}
}
else{
printf("Board is too big\n");
board();
}
return 0;
}
//the count doesn't quite do what I need it to
int moveCount()
{
char s;
printf("Press s to start: ");
scanf("%c", &s);
if(s == 's' || s == 'S'){
int count;
int max = 10;
for(count=1; count < max; count++)
if(count == max){
-printf("No more moves can be made");
}
else{
printf("Number of moves made: %d\n", count);
}
}
else{
printf("That is not s\n");
moveCount();
}
}
//Trying to check to make sure that n board is always atleast three cells
int inputCheck(){
int n, m;
if(n == 3 || n > 3 && m == 1 || m > 1){
moveCount();
}
}
int main()
{
board();
inputCheck();
}
What's the best way to implement a function that checks if neighbouring cells are the same and then deletes them. I would imagine doing something like if(myArray[0][0] == 'a' && myArray[0][1] == 'a'{do something}...but i don't know if that's the best way or how I would loop that. Also how to correctly implement a count that displays the move made?
I realise this code has a lot of flaws but I'm quite new so go easy please. Thanks for any help or a push in the right direction.
A serious bug here:
int n, m;
if(n == 3 || n > 3 && m == 1 || m > 1){
n and m are used uninitialized.
And you need to #include <stdlib.h> for rand()
In answer to your actual question, something like this would work. This is rather sloppy, but it's my 5 min answer. I assume grid is the actual board, which exists only in your board() function at the moment, so I simply added that as a parameter. AKA You're going to have to make it fit your actual game.
inline int clamp (int v, int min, int max) {
return (v < min) ? min: (v > max) ? max: v;
}
void place (char ltr, int x, int y, char grid[MAX][MAX])
{
grid[y][x] = ltr; // TODO: put bounds checking around x & y
for (int i = clamp(y - 1, 0, MAX); i <= clamp (y + 1, 0, MAX); i++) {
for (int j = clamp(x - 1, 0, MAX); j <= clamp(x + 1, 0, MAX); j++) {
if (i != y || j != x && grid[i][j] == ltr) {
grid[i][j] = '\0'; // TODO: replace null char with desired one.
}
}
}
}
The board function is set up just fine.
As the previous answers said parameters are the best way to check a value if you are going to check them within a different function, if you wish to check them within your function a simple if command would do the trick.
I would not pass an entire array as a parameter, instead I would use a pointer to that specific cell. Then, upon a person choosing a cell they are given a memory address that you could then compare the information stored inside that memory address with the other they are comparing.
Quick Pointer Lesson
- * is used to create a pointer. For instance, char *ch = array; would point to the memory address of the entire array. And then through more research you will be able to go to a specific memory address in a 2-D array, such as your board, see what is at that location and compare it to the contents contained in another memory address within your 2-D array.
Why would you want to to this?
Since this is not Java, we can about memory management in C and using an entire array as a parameter is the easy but more memory costly way of doing it. Plus, pointers are a fundamental element within most programming languages and knowing them well will make you a much better programmer.
Happy Travels!!
Also this will also be easier to go through your board to say, this person chose this address at array[3][2], there are only four memory address they would be choosing from at that point. Which ever way they choose to go, the memory address will be there and you will be able to compare both with minimal system usage and a quick response.

Quicksort sorting issues

This might not be a conventional of doing quicksort.my first try at it.the numbers are not sorted in the way they should be.I have tried to sort a random list of numbers.However i am unable to identify the logical errors even after a strict checking.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int n;
int *expivot;
int *arr;
void quicksort();
void display();
int check();
main()
{
int i;
printf("to continue press 'a' always\n");
while(getch()=='a')
{
printf("Enter the length of list\n");
scanf("%d",&n);
time_t start,end;
double t;
start=clock();
arr=(int *)calloc(n,sizeof(int));
expivot=(int *)calloc(n,sizeof(int));
srand(time(NULL));
for(i=0;i<n;i++)
arr[i]=rand()%RAND_MAX + 1;
printf("\nelements inputted are:");
display();
quicksort();
end=clock();
t=(double)(end-start)/CLOCKS_PER_SEC;
printf("\n\nelements sorted are:");
display();
printf("\ntime take is %.15lf",t);
free(arr);
free(expivot);
}
}
void quicksort()
{
int low,high,temp;
int pivot=rand()%n;//generate random pivot
int store=pivot;
/*location of pivot might change due to swapping,so using store to store pivot location so as to add this to expivot list after running quickort once*/
int flag=1;
if(expivot[pivot]==1) // checks if it's an already used pivot
flag=0;
if(flag==1) //if the pivot is unused
{
low=pivot;
high=pivot;
while(low>0 && expivot[low]==0)
low--;
if(expivot[low]==1)//i
low++;
/*decrements low to a location where a value has been set permanently and then increase by 1,if nothing is set then decrements low to zero*/
/*increments high to a location where a value has been set permanently and then decrease by 1,if nothing is set then increments high to last index*/
while(high<n-1 && expivot[high]==0)
high++;
if(expivot[high]==1)
high--;
while(low<high)
{
if(arr[low]>=arr[pivot] && arr[high]<=arr[pivot])//checks swap possibilty
{
if(low==pivot) //if pivot is to be swapped store new location of pivot
store=high;
else if(high==pivot)
store=low;
temp=arr[low];
arr[low]=arr[high];
arr[high]=temp;
low++;
high--;
}
else
{
if(arr[low]<arr[pivot])
low++;
else if(arr[high]>arr[pivot])
high--;
}
}
expivot[store]=1;
/*final location of pivot,stores info that this location has a permanent value now
and cannot be used as a pivot*/
}
if(check()==1)
quicksort();
}
int check() //checks if there are any unused pivots
{
int i;
for(i=0;i<n;i++)
{
if(expivot[i]==0)
return 1;
}
return 0;
}
void display()
{
int i;
for(i=0;i<n;i++)
printf("%d ",arr[i]);
}
Your method is:
Randomly select a pivot from whole array;
From the pivot, spread a range to both direction, this range will be partitioned by the pivot;
All pivot will be cached in another array (item 5);
The range, mentioned in item 2 above, should apread as large as it can do, but: 1) should not beyond the range of whole array; 2) should not contain another pivot, if it does, stop and shrink one unit;
Partition the range by the pivot it spread from, then cache this pivot;
If all unit in the array has been selected as pivot, sorting is done. If not, repeat as above, over and over again.
There are three problems in your code:
1- "checd()"function should be:
int check() //checks if there are any unused pivots
{
int flag = 0;
int i;
for(i=0;i<n;i++)
{
if(expivot[i]==0)
flag = 1;
}
return flag;
}
You should check all member, see if they ALL satisfy your condition, but not one of them satisfy your condition.
2- While shrink the range, make sure the pivot is between "high" and "low" (equal is well). Keep tracking the index and value of the pivot. The while loop should be:
//"store" is not needed, change it to "pivot", even after this code block.
while(low<high)
{
if(arr[low]>=arr[pivot] && arr[high]<=arr[pivot])//checks swap possibilty
{
if(low==pivot) //if pivot is to be swapped store new location of pivot
pivot=high;
else if(high==pivot)
pivot=low;
temp=arr[low];
arr[low]=arr[high];
arr[high]=temp;
/////////////////////
if (low < pivot)
low++;
if (high > pivot)
high--;
/////////////////////
}
else
{
if(arr[low]<arr[pivot])
low++;
else if(arr[high]>arr[pivot])
high--;
}
}
3- Finally, once you get memory from calloc or malloc, check if it's NULL.
==================================
Additionally, you should make sure all unit in the array can be selected, because the random number in computer is mostly pseudo random number. So, maybe for a certain length, a particular unit cannot be chosen forever.
Quicksort is a Divide and Conquer algorithm. You cannot perform it without using stacks or recursion.
Edit: The function does use recursion (oops!). But this isn't quicksort. If your are changing the method of a standard sorting algorithm, then it is no more that algorithm.

NxN matrix determinant recursion issue

im currently trying to write a program to find the determinant for an NxN matrix but im having an issue with recursion for N larger than 2. Basically from what i can tell, it isn't doing it, it just runs the function once as using my debug option shows that the function runs through the columns but the order never goes down, and it then gives me zero for my determinant no matter what. Ive tried looking all over the place for any idea as to what im doing wrong but i cant seem to find any answers, ive even found examples which do basically the same thing as me and using them gives me zero no matter what as well, so im very confused :(. id be very grateful if someone could have a quick look through my code and tell me where im being an idiot! (sorry about the formatting, it looks ok in my editor but i cant seem to get the hang of it on here)
Code:
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
double det(double **mat, int order);
int main (int argc, char* argv[])
{
FILE* input;
int row,column,N;
double **matrix;
N=3;
matrix=(double**)malloc(N*sizeof(double));
input=fopen("matrix.dat", "r");
if(input !=(FILE*) NULL)
{
for(row=0; row<N; row++)
{
matrix[row]=(double*)malloc(N*sizeof(double));
}
for(row=0; row<N; row++)
{
printf("| ");
for(column=0; column<N; column++)
{
fscanf(input,"%lf ", &matrix[row][column]);
printf("%g ", matrix[row][column]);
}
if(row != (N/2))
{
printf("|\n");
}
else
{
printf("|= %lf \n", det(matrix, N) );
}
}
return(EXIT_SUCCESS);
}
else
{
printf("*********************ERROR*********************\n");
printf("** Cannot open input file 'matrix.dat' make **\n");
printf("** sure file is present in working directory **\n");
printf("***********************************************\n");
return(EXIT_FAILURE);
}
}
double det(double **mat, int order)
{
int debug;
double cofact[order], determinant, **temp;
determinant = 0;
debug=0;
if(order==1)
{
determinant=mat[0][0];
if(debug==1)
{
printf("order 1 if\n");
}
}
else if(order==2)
{
determinant= ((mat[0][0]*mat[1][1])-(mat[0][1]*mat[1][0]));
if(debug==1)
{
printf("order 2 if\n");
}
}
else
{
int column, rowtemp, coltemp, colread;
for (column=0; column<order; column++)
{
/* Now create an array of size N-1 to store temporary data used for calculating minors */
temp= malloc((order-1)*sizeof(*temp));
for(rowtemp=0; rowtemp<(order-1); rowtemp++)
{
/* Now asign each element in the array temp as an array of size N-1 itself */
temp[rowtemp]=malloc((order-1)*sizeof(double));
}
for(rowtemp=1; rowtemp<order; rowtemp++)
{
/* We now have our empty array, and will now fill it by assinging row and collumn values from the original mat with the aprroriate elements excluded */
coltemp=0;
for(colread=0; colread<order; colread++)
{
/* When the collumn of temp is equal to the collumn of the matrix, this indicates this row should be exlcuded and is skiped over */
if(colread==column)
{
continue;
}
temp[rowtemp-1][coltemp] = mat[rowtemp][colread];
coltemp++;
}
}
if(debug==1)
{
printf("column =%d, order=%d\n", column, order);
}
determinant+=(mat[0][column]*(1 - 2*(column & 1))*det(temp, order-1));
}
}
return(determinant);
}
temp= (double **)malloc((order-1)*sizeof(double));
This will not cause a crash as long as sizeof(double*) <= sizeof(double), which is the case on the usual 32 or 64-bit systems, but it is conceptually wrong. You are allocating space for an array of double*, so the factor should be sizeof(double*) or, better since it is invariant when the type changes, sizeof *temp,
temp = malloc((order-1) * sizeof *temp);
(And you don't need to cast the result of malloc in C, it is even better not to, since the cast could hide errors like forgetting to #include <stdlib.h>.)
The same holds for the allocation
matrix=(double**)malloc(N*sizeof(double));
in main.
In the calculation of the determinant,
for(coltemp=0; coltemp<order; coltemp++)
{
for(colread=0; colread<order; colread++)
{
/* When the collumn of temp is equal to the collumn of the matrix, this indicates this row should be exlcuded and is skiped over */
if(colread==column)
{
continue;
}
temp[rowtemp-1][coltemp] = mat[rowtemp][colread];
coltemp++;
}
}
You are looping twice through the columns, once for coltemp == 0, and then in the inner loop, coltemp is incremented order-1 times, so the inner loop runs a second time with coltemp == order-1 at the start. Then coltemp is again incremented multiple times in the loop, and you're writing out of bounds of the allocated memory.
The outer loop should be removed, coltemp = 0; and the inner loop are what you need.
pow(-1,column))
is not a good way to determine a sign.
(1 - 2*(column & 1))
is faster than a call to pow.
Finally, in main
for(row=0; row<N; row++)
{
printf("| ");
for(column=0; column<N; column++)
{
fscanf(input,"%lf ", &matrix[row][column]);
printf("%g ", matrix[row][column]);
}
if(row != (N/2))
{
printf("|\n");
}
else
{
printf("|= %lf \n", det(matrix, N) );
}
}
You are printing the determinant at row N/2, which looks nice, but at that time, you have not yet scanned in the entire matrix, so rows N/2 + 1 to N-1 contain uninitialised data, which is not unlikely to be all zeros. If you change the if (row != N/2) to if (row != N-1), it will work, however, the proper way to handle it is to separate the scanning of the matrix from the computation and the printing. These are all independent operations that should be handled in their own separate functions.

Resources