Hello, I've been struggling to implmenent a 2 way link list. The code runs but when I enter the 2nd element into the list I get a segmentation fault......I cant find my error could anyone take a look?

#include <iostream>

using namespace std;

typedef struct record
{
	int num;
	record *next;
	record *previous;

}NODE;

typedef NODE *nodeptr;

void frontinsert(nodeptr &, int);
void printlist(nodeptr &);
void deleteitem(nodeptr &, int);
void searchitem(nodeptr &, int);

int main()
{
	int item, choice;
	nodeptr head = NULL;


	cout << "Please select an option: \n";
	cout << "Insert select 1\nDelete select 2\nSearch select 3\nQuit select 4\n";
		cin >> choice;


	while (choice != 4)
	{
		switch(choice)
		{
		 case 1: cout << "Enter a number to insert into the list: \n";
		 cin >> item;
	
		frontinsert(head, item);

		cout << "The list is: \n";

		printlist(head);
		 break;

		 case 2: if(head != NULL)

			{
			 cout << "Please enter the item you wish to delete:\n";
				cin >> item;

			 deleteitem(head, item);

				 if (head != NULL)
				{
				cout << "The list is: \n";

				printlist(head);
				 }
    
				 else
					cout << "CANNOT delete, the list is empty\n" << endl;
			}	
		 break;
 
		 case 3: if(head != NULL )
		 {
			  cout << "Please enter the item you wish to search for:\n";
				 cin >> item;

			 searchitem(head, item);
		 }
		 else
			cout << "CANNOT search, the list is empty\n" << endl;
		 break;

		default: cout << "Invalid selection. Please try again\n" << endl;
		}

 cout << "Please select an option: \n";
 cout << "Insert select 1\nDelete select 2\nSearch select 3\nQuit select 4\n";
 cin >> choice;

	}

free(head);
return 0;
}

void frontinsert(nodeptr &h, int d)
{
	 nodeptr p = new NODE;
	nodeptr q;
	 nodeptr r;

	 if (p == NULL)
		cout << "No memory is left" << endl;
	else
	{
	p->num = d;
		if (h == NULL )
		{
		h = p;
		p->previous = NULL;
		p->next = NULL;
		}

		else if (d <= h->num)
		{
		r=h;
		p->next = h;
		r->previous = p;
		h = p;
		p->previous = NULL;
		}
	else
		{
		r = h;
			while(r != NULL && r->num < d)
			{
			q = r;
			r = r->next;
			}

		if(r == NULL)
		{
		p->previous = q;
		q->next = p;
		p->next = NULL;
		}
		else
		{
		p->next = r;
		p->previous = q;
		q->next = p;
		r->previous = p;
		}
	}
	}
}
 


void deleteitem(nodeptr &h,  int d)
{
	nodeptr p;
	nodeptr q;

	if (h != NULL)
	{
		 if (h->num == d && h->next != NULL)
		{

		h = h->next;
		p = h;
		p->previous = NULL;
		}

			else if (h->num == d && h->next != NULL)

			h = NULL;

	else
	{
	p = h;
	q = h->next;
	}

		while (q != NULL && q->num < d)
		{
		p = q;
		q = q->next;
		}


		if (q->num == d && q->next == NULL)
		{
		q = q->next;
		q->previous = p;
		p->next =q;
		}

		else if (q->num == d && q->next != NULL)

		p->next = NULL;

	else
	cout << "Item is not in the list\n" << endl;
     
	}

}



void searchitem(nodeptr &h, int d)
{
	nodeptr q;

	 q = h;

	 while(q != NULL && q-> num != d)
		q = q->next;

		if (q != NULL && q->num == d)
			 cout << "Item is in the list\n";
		 else
		 cout << "Item is not in the list\n";

}

void printlist(nodeptr & h)
{
	 nodeptr currptr = h;

	while(currptr != NULL)
	{
	 cout << currptr->num << endl;
	 currptr = currptr->next;
	}
}

I can't seem to figure out what your insert algorithm is. Can you explain it? I spent about 5 minutes looking at it and it's all a jumble.

A few comments:
--Make liberal use of comments. // for single line comments /* */ for multi-line comments.
--Use good variable names. That means names that tell the reader of the code what you're doing. (Try temporary, current, previous, or temp, cur, prev if you're lazy.)
--Don't assume pointers are NULL. Initialize them when you declare them.

If you use GCC to do your compilation, I'm sure there's a program installed called gdb. It's a wonderful program (IMO) to use once you learn how. It's really really useful for debugging C++ because it will let you know WHERE the program failed and at your request will display a variable's contents before it fails. You need to compile with debug points in:

g++ -g yourprogram.cpp