#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/***********************************************************

This program implements a simple priority queue using a heap.
The items being sorted are records, where each record contains a last name, a 
first name, and an ID number.  The records will be sorted according 
to their ID numbers, from smallest to largest.

A heap (in this context) is a binary tree with the following 
properties:
- The value at a parent node is greater than the value at 
  either child node.
- The heap is implemented using an array. Each element of the
  array is a pointer to a record. 
- For a parent node at index i of the array, the children are 
  found at indices (i*2)+1 and (i*2)+2. All parent nodes
  have two children, except for the very last parent node.
- For a child node at index i of the array, the parent is
  found at index (x-1)/2 (using integer division).

************************************************************/

// This is the declaration of the RECORD type

typedef struct  {
  char *last_name;
  char *first_name;
  long id_number;
} RECORD;


RECORD *read_record();

/* This function reads in the data for a single record from the
   standard input by calling scanf. If scanf succeeds in 
   reading the data, a new RECORD is allocated, populated
   with the data, and a pointer to the record is returned 
*/

RECORD *read_record()
{
  char lastname[100], firstname[100];
  RECORD *p;
  long id;
  int res = scanf("%s %s %ld", lastname, firstname, &id);
  if (res == EOF)   // EOF is -1
    return NULL;
  p = malloc(sizeof(RECORD));
  p->last_name = malloc(strlen(lastname)+1);
  strcpy(p->last_name, lastname);
  p->first_name = malloc(strlen(lastname)+1);
  strcpy(p->first_name, firstname);  
  p->id_number = id;
  return p;
}
    

/*
  These are macros that are convenient for finding the parent,
  left child, and right child of a node at index x of the array.
*/

#define PARENT(x) ((x-1)>>1)
#define LEFT(x) ((x<<1)+1)
#define RIGHT(x) ((x<<1)+2)


// This is the fixed size of the heap array.

#define SIZE 500

// The heap is an array of pointers to records
RECORD *heap[SIZE];

// This is a count of the number of nodes in the head.
// It is also the index of the next available slot in the
// array.

// int heap_count = 0;
extern int heap_count; // in assembly

void heap_swap(int i, int j);

/* 
  This function simply swaps the contents of the heap
  array at indices i and j.  The contents of each 
  element of the array is just a pointer to a record.
*/

void heap_swap(int i, int j) {
  RECORD *temp = heap[i];
  heap[i] = heap[j];
  heap[j] = temp;
}


void sift_up(int i);

/* 
   This is the heap "sift up" function. It starts with a leaf, at array index i, that has just
   been added to the tree and might violate the heap requirement (i.e. the value of the leaf
   may be less than that of its parent). It works by comparing the node at index i to 
   its parent.  If the value of the node is not less than its parent, the heap property
   has been maintained and the function can return.  Otherwise, the values at the node and at its
   parent are swapped, i is set to the index of the parent node (since the value at the parent now 
   may be less than at the grandparent), and the process iterates until either the heap property
   is satisfied or the root (at index 0) is reached.
*/


void sift_up(int i)
{
  while (i != 0) {
    if (heap[i]->id_number >= heap[PARENT(i)]->id_number)   // correct situation, no need to continue
	return;
    // otherwise, need to swap with parent
    heap_swap(i, PARENT(i));
    i = PARENT(i);
  }
}


void sift_down();


/* 
   This function performs the heap "sift down" process, which occurs when
   a new value has been inserted at the root of the tree (i.e. when the 
   existing root is removed and the last leaf in the tree is inserted at
   the root). Starting at the root as the parent node, the values of the 
   two child nodes are compared to each other. Then if the value at the
   parent is greater than the value at the smaller child, the values at
   the parent and the smaller child are swapped, and the process
   continues with the smaller child being considered the parent in the
   next iteration.  The process terminates when a leaf is reached.

   At any point, if the value at the parent is not greater than the 
   smaller child, the heap property has been preserved and the function
   can return. If a parent ony has one child (which must be the left 
   child), then the left child is considered the smaller child.
*/


void sift_down()
{
  int i = 0;
  int last_parent = PARENT(heap_count - 1);
  int min_child;
  
  while (i <= last_parent) {
    if ((RIGHT(i) >= heap_count) ||
	(heap[LEFT(i)]->id_number <= heap[RIGHT(i)]->id_number))
      min_child = LEFT(i);
    else
      min_child = RIGHT(i);
    if (heap[i]->id_number > heap[min_child]->id_number) {
      heap_swap(i, min_child);
      i = min_child;
    }
    else // done sifting down
      return;
  }
}



void heap_insert(RECORD *p);

/*
   This function inserts a new record into the 
   heap. It does so by adding a pointer to the 
   record at index heap_count (the first open
   slot) in the array and then calling
   sift_up(), above, to restore the heap property.
*/


void heap_insert(RECORD *p)
{
  if (heap_count >= SIZE) {
    printf("Error: Heap is full\n");
    exit(1);
  }
  heap[heap_count] = p;
  sift_up(heap_count);
  heap_count++;
}


RECORD *heap_remove();

/* 
    This function removes the smallest  value in the heap, i.e.
    the value at the root node (at array index 0), and returns 
    that smallest value (which is a pointer to a record).
    Before returning, it writes the value of the last
    leaf (at index heap_count-1 of the array) into to the 
    root node and then calls    sift_down(), above, to 
    restore the heap property.
*/

RECORD *heap_remove()  
{
  if (heap_count <= 0) {
    printf("Error: Heap is empty\n");
    exit(1);
  }
  RECORD *result = heap[0];
  heap_count--;
  heap[0] = heap[heap_count];
  sift_down();
  return result;
}



/* 

   This is the main function, which repeatedly calls read_record and
   heap_insert to insert pointers to records into the heap. Once
   all the data has been read, it repeatedly calls heap_remove()
   to print out the records in sorted order, according the ID number
*/

int main() {

  RECORD *temp = malloc(sizeof(RECORD));
  printf("sizeof(CELL) = %ld\n", sizeof(RECORD));
  printf("Offset of lastname = %ld\n", (void *) &(temp->last_name) - (void *) temp);
  printf("Offset of firstname = %ld\n", (void *) &(temp->first_name) - (void *) temp);
  printf("Offset of idnumber = %ld\n", (void *) &(temp->id_number) - (void *) temp);
  

  RECORD *p = NULL;
  p = read_record();
  while (p != NULL) {
    heap_insert(p);
    p = read_record();
  }
  
  printf("Sorted\n------\n");
  while (heap_count != 0) {
    p = heap_remove();
    printf("%ld: %s, %s\n", p->id_number, p->last_name, p->first_name);
  }
}


 

C Language online compiler

Write, Run & Share C Language code online using OneCompiler's C online compiler for free. It's one of the robust, feature-rich online compilers for C language, running the latest C version which is C18. Getting started with the OneCompiler's C editor is really simple and pretty fast. The editor shows sample boilerplate code when you choose language as 'C' and start coding!

Read inputs from stdin

OneCompiler's C online editor supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample C program which takes name as input and print your name with hello.

#include <stdio.h>
int main()
{
    char name[50];
    printf("Enter name:");
    scanf("%s", name);
    printf("Hello %s \n" , name );
    return 0;
    
}

About C

C language is one of the most popular general-purpose programming language developed by Dennis Ritchie at Bell laboratories for UNIX operating system. The initial release of C Language was in the year 1972. Most of the desktop operating systems are written in C Language.

Key features:

  • Structured Programming
  • Popular system programming language
  • UNIX, MySQL and Oracle are completely written in C.
  • Supports variety of platforms
  • Efficient and also handle low-level activities.
  • As fast as assembly language and hence used as system development language.

Syntax help

Loops

1. If-Else:

When ever you want to perform a set of operations based on a condition if-else is used.

if(conditional-expression) {
   // code
} else {
   // code
}

You can also use if-else for nested Ifs and if-else-if ladder when multiple conditions are to be performed on a single variable.

2. Switch:

Switch is an alternative to if-else-if ladder.

switch(conditional-expression) {    
case value1:    
 // code    
 break;  // optional  
case value2:    
 // code    
 break;  // optional  
...    
    
default:     
 // code to be executed when all the above cases are not matched;    
} 

3. For:

For loop is used to iterate a set of statements based on a condition.

for(Initialization; Condition; Increment/decrement){  
  // code  
} 

4. While:

While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.

while(condition) {  
 // code 
}  

5. Do-While:

Do-while is also used to iterate a set of statements based on a condition. It is mostly used when you need to execute the statements atleast once.

do {
  // code 
} while (condition); 

Arrays

Array is a collection of similar data which is stored in continuous memory addresses. Array values can be fetched using index. Index starts from 0 to size-1.

Syntax

One dimentional Array:

data-type array-name[size];

Two dimensional array:

data-type array-name[size][size];

Functions

Function is a sub-routine which contains set of statements. Usually functions are written when multiple calls are required to same set of statements which increases re-usuability and modularity.

Two types of functions are present in C

  1. Library Functions:

Library functions are the in-built functions which are declared in header files like printf(),scanf(),puts(),gets() etc.,

  1. User defined functions:

User defined functions are the ones which are written by the programmer based on the requirement.

How to declare a Function

return_type function_name(parameters);

How to call a Function

function_name (parameters)

How to define a Function

return_type function_name(parameters) {  
  //code
}