Q:

Добавление, просмотр и удаление элементов в двусвязном списке

Добрый день! Нужны 3 функции функции:  которая добавляет элемент в начало двусвязного списка, функция вывода списка с начала и функция удаления элементов с конца. С горем пополам написал первые две, но неизменно выдает ошибку: при попытке вывода списка выводит только первый элемент, а дальше работа программы прекращается. Надеюсь на вашу помощь. 
struct list // Объявление структуры
{ 
int x;
struct list *next;
struct list *prev;
};

struct list *add_list(int info, struct list*head) // Добавление элемента
{
struct list*data;
data = (struct list*)malloc(sizeof(struct list));
data->x = info;

if (head == NULL)
{
    head = data;
    head->prev = NULL;
}

else
{
    head->prev = data;
}
return head;
}

void show_list(struct list*head) // Просмотр списка
{
  while (head != NULL)
  {
     printf("%d\n", head->x);
     head = head->next;
  }
}

A:

Если вы создаете двусвязный список и собираетесь добавлять элементы в начало списка и удалять их в конце списка, то вам нужно поддерживать два указателя: один - на начало списка, а другой - на конец списка. Иначе код будет неэффективным.
В связи с этим вам следует объявить две структуры. Одна структура будет определять узел списка, а другая структура - сам список.
Например,
struct node
{ 
    int value;
    struct node *next;
    struct node *prev;
};

struct list
{ 
    struct node *head;
    struct node *tail;
};

Тогда в main вы можете определить объект списка, например, следующим образом:
struct list list = { NULL, NULL };

Добавление элемента в начало списка можно определить следующим образом:
void add_node( struct list *list, int value )
{
    struct node *tmp = ( struct node * )malloc( sizeof( struct node ) );

    if ( tmp )
    {
        tmp->value = value;
        tmp->next  = list->head;
        tmp->prev  = NULL;

        if ( list->head ) list->head->prev = tmp;

        list->head = tmp;
        if ( !list->tail ) list->tail = tmp;
    }
}

Удаление элементов в конце списка может выглядеть следующим образом:
void delete_node( struct list *list )
{
    if ( list->tail )
    {
        struct node *tmp = list->tail;

        list->tail = list->tail->prev;

        if ( list->tail ) list->tail->next = NULL;
        else list->head = NULL;

        free( tmp );
    }
}

Вот демонстрационная программа
#include <stdio.h>
#include <stdlib.h>

struct node
{ 
    int value;
    struct node *next;
    struct node *prev;
};

struct list
{ 
    struct node *head;
    struct node *tail;
};

void add_node( struct list *list, int value )
{
    struct node *tmp = ( struct node * )malloc( sizeof( struct node ) );

    if ( tmp )
    {
        tmp->value = value;
        tmp->next  = list->head;
        tmp->prev  = NULL;

        if ( list->head ) list->head->prev = tmp;

        list->head = tmp;
        if ( !list->tail ) list->tail = tmp;
    }
}

void delete_node( struct list *list )
{
    if ( list->tail )
    {
        struct node *tmp = list->tail;

        list->tail = list->tail->prev;

        if ( list->tail ) list->tail->next = NULL;
        else list->head = NULL;

        free( tmp );
    }
}

void show_list( struct list *list )
{
    for ( struct node *current = list->head; current; current = current->next )
    {
        printf( "%d ", current->value );
    }
}

void show_reversed_list( struct list *list )
{
    for ( struct node *current = list->tail; current; current = current->prev )
    {
        printf( "%d ", current->value );
    }
}

int main( void )
{
    const int N = 10;

    struct list list = { NULL, NULL };

    for ( int i = 0; i < N; i++ )
    {
        add_node( &list, i );
        show_list( &list );
        printf( "\n" );
    }

    for ( int i = 0; i < N; i++ )
    {
        show_reversed_list( &list );
        delete_node( &list );
        printf( "\n" );
    }
}

Ее вывод на консоль:
0 
1 0 
2 1 0 
3 2 1 0 
4 3 2 1 0 
5 4 3 2 1 0 
6 5 4 3 2 1 0 
7 6 5 4 3 2 1 0 
8 7 6 5 4 3 2 1 0 
9 8 7 6 5 4 3 2 1 0 
0 1 2 3 4 5 6 7 8 9 
1 2 3 4 5 6 7 8 9 
2 3 4 5 6 7 8 9 
3 4 5 6 7 8 9 
4 5 6 7 8 9 
5 6 7 8 9 
6 7 8 9 
7 8 9 
8 9 
9 

