[C语言]2D-linked list(二维链表)

[C语言]2D-linked list-二维链表


不多BB,直接上图,我们要实现如下的矩阵形状的二维列表

    head -----------+   NULL              NULL
                    |    ^                 ^
                    |    |                 |
                    v    |                 |
                  +---------+         +---------+
    NULL <--------|    1    |<------->|    2    |------> NULL
                  +---------+         +---------+
                       ^                   ^ 
                       |                   |
                       v                   v
                  +---------+         +---------+
    NULL <--------|    3    |<------->|    4    |------> NULL
                  +---------+         +---------+
                       |                 |    ^
                       |                 |    |
                       v                 v    +--------- tail
                      NULL              NULL

Figure 1

头文件

#ifndef _DOUBLL2D_H
#define _DOUBLL2D_H

/* Header file for a 2d doubly linked list. */

#include <stdbool.h>
#include <stddef.h>

/* A list element (doubll2d_elem) has pointers to the four elements around it
   (i.e. left, right, up and down). The pointer should point to NULL if the
   neighbor it points to doesn't exist.

   It also has a pointer to the data (owned by the list element) and the size of
   that data. */

typedef struct doubll2d_elem doubll2d_elem;

struct doubll2d_elem
{
    
    
   doubll2d_elem *left;
   doubll2d_elem *right;
   doubll2d_elem *up;
   doubll2d_elem *down;

   void *data;
   size_t size;
};

typedef struct doubll2d doubll2d;

/*
   You can imagine that our 2D linked list is a matrix, which MUST have
   a shape of rectangular at all time.

   The 2D doubly linked list with 4 elements (2 by 2) is like this:

    head -----------+   NULL              NULL
                    |    ^                 ^
                    |    |                 |
                    v    |                 |
                  +---------+         +---------+
    NULL <--------|    1    |<------->|    2    |------> NULL
                  +---------+         +---------+
                       ^                   ^ 
                       |                   |
                       v                   v
                  +---------+         +---------+
    NULL <--------|    3    |<------->|    4    |------> NULL
                  +---------+         +---------+
                       |                 |    ^
                       |                 |    |
                       v                 v    +--------- tail
                      NULL              NULL

    An empty list looks like this:

    head ------> NULL
    NULL <------ tail

    (If not empty) The head pointer of a list should always point to the
    upper-left most element, and the tail pointer should always point to the
    lower-right most element.

    The dim_row and dim_col stores the dimension of the rows and columns (i.e.
    the number of rows and columns).
*/
struct doubll2d
{
    
    
   doubll2d_elem *head;
   doubll2d_elem *tail;

   size_t dim_row;
   size_t dim_col;
};

/* Initialize a 2D doubly linked list. */
void doubll2d_init(doubll2d *list);

/* Return the upper-left most element of the list.
   Return NULL on error. */
doubll2d_elem *doubll2d_get_head(doubll2d *list);

/* Return the lower-right most element of the list.
   Return NULL on error. */
doubll2d_elem *doubll2d_get_tail(doubll2d *list);

/* Return number of rows in a list.
   Return -1 on error. */
size_t doubll2d_dim_row(doubll2d *list);

/* Return number of columns in a list.
   Return -1 on error. */
size_t doubll2d_dim_col(doubll2d *list);

/* Insert a new row in the list below the row where the given `cursor` locates.
   The given `data` should be **copied** to the newly created elements.
   The `length` is the number of data pointers given to you.
   Return the pointer to the newly created element below the given `cursor`.
   Return NULL on error.

   Remember, our 2D doubly linked list should always be a rectangular. So if
   the `length` is shorter than it should be, abort immediately and return NULL.
   However, it is okay that the `length` is longer than needed. And in this case
   you should make use of the first `doubll.dim_col` items in `data` and leave
   alone the rest.

   If the marco CHECK_LIST is set, your code has to check if the element `cursor` is
   actually a member of the list. If not, abort and return NULL. This check is slow. 
   If the marco CHECK_LIST is not set, your code shall not perform that check
   but rather run very fast. */
doubll2d_elem *doubll2d_insert_row(doubll2d *list, doubll2d_elem *cursor,
                                   void **data, size_t *size, size_t length);

/* Insert a new column in the list after the column where the given `cursor`
   locates. The given `data` should be **copied** to the newly created elements.
   The `length` is the number of data pointers given to you.
   Return the pointer to the newly created element after the given `cursor`.
   Return NULL on error.

   Remember, our 2D doubly linked list should always be a rectangular. So if
   the `length` is shorter than it should be, abort immediately and return NULL.
   However, it is okay that the `length` is longer than needed. And in this case
   you should make use of the first `doubll.dim_row` items in `data` and leave
   alone the rest.

   If the marco CHECK_LIST is set, your code has to check if the element `cursor` is
   actually a member of the list. If not, abort and return NULL. This check is slow. 
   If the marco CHECK_LIST is not set, your code shall not perform that check
   but rather run very fast. */
doubll2d_elem *doubll2d_insert_col(doubll2d *list, doubll2d_elem *cursor,
                                   void **data, size_t *size, size_t length);

/* Delete the row where the given `cursor` locates and returns the element above
   the given `cursor`. If the first row is deleted, then return the element
   below the given `cursor`. If the deleted row is the only row in the list,
   return NULL. Return NULL on error.

   If the marco CHECK_LIST is set, your code has to check if the element `cursor` is
   actually a member of the list. If not, abort and return NULL. This check is slow. 
   If the marco CHECK_LIST is not set, your code shall not perform that check
   but rather run very fast. */
doubll2d_elem *doubll2d_delete_row(doubll2d *list, doubll2d_elem *cursor);

/* Delete the column where the given `cursor` locates and returns the element
   before the given `cursor`. If the first column is deleted, then return the
   element after the given `cursor`. If the deleted column is the only column in
   the list, return NULL. Return NULL on error.

   If the marco CHECK_LIST is set, your code has to check if the element `cursor` is
   actually a member of the list. If not, abort and return NULL. This check is slow. 
   If the marco CHECK_LIST is not set, your code shall not perform that check
   but rather run very fast. */
doubll2d_elem *doubll2d_delete_col(doubll2d *list, doubll2d_elem *cursor);

/*  Purge all items from the list. */
void doubll2d_purge(doubll2d *list);

/* Compare function between two list elements. Return true if `a` is less than `b`.
   You could implement your own compare function in your test file. */
typedef bool list_less_func(const doubll2d_elem *a, const doubll2d_elem *b);

/* Use the given `less` function to find the maximum element in the whole list.
   If there are multiple maximum elements, return any one of them.
   When the 2D linked list is empty, return NULL.
 */
doubll2d_elem *doubll2d_find_max(doubll2d *list, list_less_func *less);

/* Use the given `less` function to find the minimum element in the whole list.
   If there are multiple minimum elements, return any one of them.
   When the 2D linked list is empty, return NULL.
 */
doubll2d_elem *doubll2d_find_min(doubll2d *list, list_less_func *less);

#endif /* doubll2d.h */

.C文件

#include "doubll2d.h"
#ifndef CHECK_LIST
#define CHECK_LIST false
#endif 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void doubll2d_init(doubll2d *list)
{
    
    
    list->head = NULL; 
    list->tail = NULL;
    list->dim_col = 0;
    list->dim_row = 0;
}
doubll2d_elem *doubll2d_get_head(doubll2d *list)
{
    
    
    if (list == NULL)
    {
    
    
        return NULL;
    }
    return list->head; 
}

doubll2d_elem *doubll2d_get_tail(doubll2d *list)
{
    
    
    if (list == NULL) 
    {
    
    
        return NULL; 
    }
    return list->tail; 
}

size_t doubll2d_dim_row(doubll2d *list)
{
    
    
    if (list == NULL) 
    {
    
    
        return -1;
    }
    return list->dim_row; 
}

size_t doubll2d_dim_col(doubll2d *list)
{
    
    
    if (list == NULL) 
    {
    
    
        return -1;
    }
    return list->dim_col; 
}

bool check(doubll2d *list, doubll2d_elem *cursor) /*gurantee list and cursor to be not empty*/
{
    
    
    doubll2d_elem *p = list->head; 
    doubll2d_elem *this_row = list->head;
    size_t i = 0;
    size_t j = 0;
    if (CHECK_LIST) 
    {
    
    
        for (i = 0; i < list->dim_row; i++) 
        {
    
    
            for (j = 0; j < list->dim_col; j++)
            {
    
    
                if (j == list->dim_col - 1 && i != list->dim_row - 1)
                    this_row = p->down;
                if (i % 2 == 0)
                {
    
    
                    if (cursor == p)
                        return true; 
                    p = p->right;
                }
                else
                {
    
    
                    if (cursor == p)
                        return true; 
                    p = p->left;
                }
            }
            p = this_row; 
        }
        return false;
    }
    return true; 
}
bool set_list(doubll2d *list, void **data, size_t *size) /*call only when the list is empty and cursor is NULL*/
{
    
    
    if (list->dim_col == 0 || list->dim_row == 0) /*empty list*/
    {
    
    
        doubll2d_elem *first = malloc(sizeof(doubll2d_elem));
        list->dim_col = 1;
        list->dim_row = 1;                     
        first->data = (void *)malloc(size[0]); 
        memcpy(first->data, data[0], size[0]);
        first->size = size[0]; 
        first->left = NULL;    
        first->right = NULL;
        first->up = NULL; 
        first->down = NULL;
        list->head = first;
        list->tail = first; 
        return true;
    }
    return false; /*not empty*/
}

doubll2d_elem *doubll2d_insert_row(doubll2d *list, doubll2d_elem *cursor, void **data, size_t *size, size_t length)
{
    
    
    doubll2d_elem *result; 
    size_t i = 0;
    bool tag = true;
    if(list==NULL)return NULL;/*first list==NULL second list not NULL but cursor NULL third list not NULL cursor not NULL*/
    if(list->head==NULL&&cursor!=NULL)return NULL;
    if(list->head==NULL&&cursor==NULL)
    {
    
    
        set_list(list,data,size);
        return list->head;
    }
    if (!check(list,cursor))return NULL; 
    if (cursor->down == NULL)tag = false;
    if (length < list->dim_col) return NULL;      
    if (length >= list->dim_col) 
    {
    
    
        doubll2d_elem *this_row = cursor;
        while (this_row->left != NULL) 
        {
    
    
            this_row = this_row->left; /*reach top*/
        }
        for (i = 0; i < list->dim_col; i++)
        {
    
    
            doubll2d_elem *ptr = malloc(sizeof(doubll2d_elem));
            ptr->data = (void *)malloc(size[i]);
            ptr->size = size[i];                
            memcpy(ptr->data, data[i], size[i]); 
            if (!tag)                            /*cursor is the last col*/
            {
    
    
                this_row->down = ptr;
                ptr->up = this_row; /*left right complete*/
                ptr->down = NULL;  
            }
            else
            {
    
    
                this_row->down->up = ptr;   
                ptr->down = this_row->down; 
                this_row->down = ptr;
                ptr->up = this_row; /*left right complete*/
            }
            if (i != list->dim_col - 1)
                this_row = this_row->right; 
        }
        this_row->down->right = NULL; 
        result = this_row;            
        i = 0;
        for (i = 0; i < list->dim_col; i++) 
        {
    
    
            if (this_row->left != NULL)
            {
    
    
                this_row->down->left = this_row->left->down; /*error,1x1 ,this_col->up=NULL*/
                this_row->left->down->right = this_row->down;
            }
            else
            {
    
    
                this_row->down->left = NULL;
            }
            if (i != list->dim_col - 1)
                this_row = this_row->left; 
        }
        this_row->down->left = NULL; 
    }
    if (!tag)
        list->tail = result->down; 
    list->dim_row += 1;            
    return cursor->down;           
}

doubll2d_elem *doubll2d_insert_col(doubll2d *list, doubll2d_elem *cursor, void **data, size_t *size, size_t length)
{
    
    
    doubll2d_elem *result; 
    size_t i = 0;
    bool tag = true; 
    if(list==NULL)return NULL;/*first list==NULL second list not NULL but cursor NULL third list not NULL cursor not NULL*/
    if(list->head==NULL&&cursor!=NULL)return NULL;
    if(list->head==NULL&&cursor==NULL)
    {
    
    
        set_list(list,data,size);
        return list->head;
    }
    if (!check(list,cursor))return NULL; 
    if (cursor->right == NULL)tag = false;
    if (length < list->dim_row)
    {
    
    
        return NULL;
    }            
    if (length >= list->dim_row) 
    {
    
    
        doubll2d_elem *this_col = cursor;
        while (this_col->up != NULL) 
        {
    
    
            this_col = this_col->up; /*reach top*/
        }
        for (i = 0; i < list->dim_row; i++)
        {
    
    
            doubll2d_elem *ptr = malloc(sizeof(doubll2d_elem)); 
            ptr->data = (void *)malloc(size[i]);
            ptr->size = size[i];                
            memcpy(ptr->data, data[i], size[i]); 
            if (!tag)                            /*cursor is the last col*/
            {
    
    
                this_col->right = ptr;
                ptr->left = this_col; /*left right complete*/
                ptr->right = NULL;    
            }
            else
            {
    
    
                this_col->right->left = ptr; 
                ptr->right = this_col->right; 
                this_col->right = ptr;
                ptr->left = this_col; /*left right complete*/
            }
            if (i != list->dim_row - 1)
                this_col = this_col->down; 
        }
        this_col->right->down = NULL; 
        result = this_col;           
        i = 0;
        for (i = 0; i < list->dim_row; i++) 
        {
    
    
            if (this_col->up != NULL)
            {
    
    
                this_col->right->up = this_col->up->right; /*error,1x1 ,this_col->up=NULL*/
                this_col->up->right->down = this_col->right;
            }
            else
            {
    
    
                this_col->right->up = NULL;
            }
            if (i != list->dim_row - 1)
                this_col = this_col->up; 
        }
        this_col->right->up = NULL; 
    }
    if (!tag)
        list->tail = result->right;
    list->dim_col += 1;             
    return cursor->right;           
}

doubll2d_elem *doubll2d_delete_row(doubll2d *list, doubll2d_elem *cursor) 
{
    
    
    size_t i = 0;
    if(list==NULL||cursor==NULL)return NULL;/*first list==NULL second list not NULL but cursor NULL third list not NULL cursor not NULL*/
    if(list->head==NULL)return NULL;
    if (!check(list,cursor))return NULL; 
    if (cursor->up == NULL && cursor->down == NULL) /*only one row*/
    {
    
    
        doubll2d_elem *this_row = cursor;
        this_row = list->head;
        for (i = 0; i < list->dim_col; i++) 
        {
    
    
            free(this_row->data);
            if (i != list->dim_col - 1)
            {
    
                                
                this_row = this_row->right; 
                free(this_row->left);
            }
            else 
            {
    
    
                free(this_row); 
            }
        }
        list->dim_col = 0; 
        list->dim_row = 0;
        list->head = NULL;
        list->tail = NULL; 
        return NULL;
    }
    else if (cursor->down == NULL) /*list->tail change*/
    {
    
    
        doubll2d_elem *this_row = cursor;
        doubll2d_elem *result = cursor->up;
        while (this_row->left != NULL)
        {
    
    
            this_row = this_row->left; /*obtain head of this row*/
        }
        for (i = 0; i < list->dim_col; i++)
        {
    
    
            this_row->up->down = NULL;
            free(this_row->data);      
            if (i != list->dim_col - 1) 
            {
    
    
                this_row = this_row->right; 
                free(this_row->left);
            }
            else
            {
    
    
                list->tail = this_row->up; 
                free(this_row);
            }
        }
        list->dim_row -= 1; 
        return result;     
    }
    else if (cursor->up == NULL) /*return below element,list head change*/
    {
    
    
        doubll2d_elem *this_row = cursor; 
        doubll2d_elem *result = cursor->down;
        while (this_row->left != NULL) 
        {
    
    
            this_row = this_row->left; 
        }
        list->head = this_row->down;
        for (i = 0; i < list->dim_col; i++) 
        {
    
    
            this_row->down->up = NULL;
            free(this_row->data);       
            if (i != list->dim_col - 1) 
            {
    
    
                this_row = this_row->right;
                free(this_row->left); 
            }
            else
            {
    
    
                free(this_row); 
            }
        }
        list->dim_row -= 1; 
        return result;
    }
    else
    {
    
    
        doubll2d_elem *this_row = cursor;   
        doubll2d_elem *result = cursor->up; 
        while (this_row->left != NULL)
        {
    
    
            this_row = this_row->left; 
        }
        for (i = 0; i < list->dim_col; i++) 
        {
    
    
            this_row->down->up = this_row->up;
            this_row->up->down = this_row->down; 
            free(this_row->data);
            if (i != list->dim_col - 1) 
            {
    
    
                this_row = this_row->right; 
                free(this_row->left);       
            }
            else
            {
    
    
                free(this_row); 
            }
        }
        list->dim_row -= 1; 
        return result;      
    }
}

doubll2d_elem *doubll2d_delete_col(doubll2d *list, doubll2d_elem *cursor) 
{
    
    
    size_t i = 0;
    if(list==NULL||cursor==NULL)return NULL;/*first list==NULL second list not NULL but cursor NULL third list not NULL cursor not NULL*/
    if(list->head==NULL)return NULLif (!check(list,cursor))return NULL; 
    if (cursor->left == NULL && cursor->right == NULL) /*only one row*/
    {
    
    
        doubll2d_elem *this_col = cursor;
        this_col = list->head;
        for (i = 0; i < list->dim_row; i++) 
        {
    
    
            free(this_col->data);
            if (i != list->dim_row - 1)
            {
    
                                  
                this_col = this_col->down; 
                free(this_col->up);
            }
            else 
            {
    
    
                free(this_col); 
            }
        }
        list->dim_col = 0; 
        list->dim_row = 0;
        list->head = NULL;
        list->tail = NULL; 
        return NULL;
    }
    else if (cursor->right == NULL) /*list->tail change*/
    {
    
    
        doubll2d_elem *this_col = cursor; 
        doubll2d_elem *result = cursor->left;
        while (this_col->up != NULL)
        {
    
    
            this_col = this_col->up; /*obtain head of this row*/
        }
        for (i = 0; i < list->dim_row; i++)
        {
    
    
            this_col->left->right = NULL;
            free(this_col->data);       
            if (i != list->dim_row - 1) 
            {
    
    
                this_col = this_col->down; 
                free(this_col->up);
            }
            else
            {
    
    
                list->tail = this_col->left; 
                free(this_col);
            }
        }
        list->dim_col -= 1; 
        return result;     
    }
    else if (cursor->left == NULL) /*return below element,list head change*/
    {
    
    
        doubll2d_elem *this_col = cursor; 
        doubll2d_elem *result = cursor->right;
        while (this_col->up != NULL) 
        {
    
    
            this_col = this_col->up; 
        }
        list->head = this_col->right;
        for (i = 0; i < list->dim_row; i++) 
        {
    
    
            this_col->right->left = NULL;
            free(this_col->data);       
            if (i != list->dim_row - 1)
            {
    
    
                this_col = this_col->down;
                free(this_col->up); 
            }
            else
            {
    
    
                free(this_col); 
            }
        }
        list->dim_col -= 1; 
        return result;
    }
    else
    {
    
    
        doubll2d_elem *this_col = cursor;   
        doubll2d_elem *result = cursor->left;
        while (this_col->up != NULL)
        {
    
    
            this_col = this_col->up; 
        }
        for (i = 0; i < list->dim_row; i++) 
        {
    
    
            this_col->right->left = this_col->left;
            this_col->left->right = this_col->right; 
            free(this_col->data);
            if (i != list->dim_row - 1) 
            {
    
    
                this_col = this_col->down; 
                free(this_col->up);        
            }
            else
            {
    
    
                free(this_col); 
            }
        }
        list->dim_col -= 1; 
        return result;      
    }
}

void doubll2d_purge(doubll2d *list) 
{
    
    
    doubll2d_elem *p;        /*move through operation*/
    doubll2d_elem *next_row;
    size_t i = 0;
    size_t j = 0;
    if(list==NULL||list->head==NULL)return ;
    p = list->head; 
    for (i = 0; i < list->dim_row; i++)
    {
    
    
        for (j = 0; j < list->dim_col; j++) 
        {
    
    
            if (j == list->dim_col - 1 && i != list->dim_row - 1)
            {
    
    
                next_row = p->down; 
            }
            if (j != list->dim_col - 1) 
            {
    
    
                if (i % 2 == 0)
                {
    
    
                    free(p->data); 
                    p = p->right;
                    free(p->left); 
                }
                else
                {
    
    
                    free(p->data); 
                    p = p->left;
                    free(p->right); 
                }
            }
            else
            {
    
    
                free(p->data); 
                free(p);       
            }
        }
        p = next_row;
    }
    list->head = NULL; 
    list->tail = NULL; 
    list->dim_col = 0; 
    list->dim_row = 0;
}

doubll2d_elem *doubll2d_find_max(doubll2d *list, list_less_func *less) 
{
    
    
    doubll2d_elem *max; 
    doubll2d_elem *p;
    doubll2d_elem *next_row; 
    size_t i = 0;
    size_t j = 0;
    if (list == NULL||list->head==NULL)return NULL;
    max = list->head; 
    p = list->head;
    next_row = list->head;            
    for (i = 0; i < list->dim_row; i++) 
    {
    
    
        for (j = 0; j < list->dim_col; j++) 
        {
    
    
            if (j == list->dim_col - 1 && i != list->dim_row - 1)
            {
    
    
                next_row = p->down; 
            }
            if (less(max, p)) 
            {
    
    
                max = p; 
            }
            if (i % 2 == 0) 
            {
    
    
                p = p->right; 
            }
            else
            {
    
    
                p = p->left;
            }
        }
        p = next_row; 
    }
    return max;
}

doubll2d_elem *doubll2d_find_min(doubll2d *list, list_less_func *less)
{
    
    
    doubll2d_elem *min; 
    doubll2d_elem *p;
    doubll2d_elem *next_row; 
    size_t i = 0;
    size_t j = 0;
    if (list == NULL||list->head==NULL)return NULL;
    min = list->head; 
    p = list->head;   
    next_row = list->head;
    for (i = 0; i < list->dim_row; i++) 
    {
    
    
        for (j = 0; j < list->dim_col; j++) 
        {
    
    
            if (j == list->dim_col - 1 && i != list->dim_row - 1) 
            {
    
    
                next_row = p->down;
            }
            if (less(p, min)) 
            {
    
    
                min = p; 
            }
            if (i % 2 == 0) 
            {
    
    
                p = p->right; 
            }
            else
            {
    
     
                p = p->right;
            }
        }
        p = next_row; 
    }
    return min; 
}

调试Main函数

1.人工输入调试

#include "doubll2d.c"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
bool less(const void *a, const void *b) {
    
    
    if (*((int *)a) < *((int *)b)) {
    
    
        return 1;
    } else {
    
    
        return 0;
    }
}

void travel(doubll2d *list) {
    
    
    doubll2d_elem *temp = list->head;
    unsigned int row_num, col_num;

    for (row_num = 1; row_num <= list->dim_row; ++row_num) {
    
    
        for (col_num = 1; col_num <= list->dim_col; ++col_num) {
    
    
            printf("%d ", *((int *)temp->data));

            if (col_num == list->dim_col && row_num == list->dim_row) {
    
    
                return;
            } else if (col_num == list->dim_col && row_num != list->dim_row) {
    
    
                temp = temp->down;
                while (temp->left != NULL) temp = temp->left;
            } else {
    
    
                temp = temp->right;
            }
        }
        printf("\n");
    }
}


int main() {
    
    
    int** test_data = (int **)malloc(10 * sizeof(int *));
    int i;
    int input = 1;

    doubll2d test_list;
    size_t* size = (size_t *)malloc(10*sizeof(size_t));
    for (int cnt = 0; cnt <=9 ; cnt++)
    {
    
    
        size[cnt] = sizeof(int);
    }

    srand((unsigned)time(NULL));
    for (i = 0; i < 10; i++) {
    
    
        test_data[i] = (int *)malloc(sizeof(int));
        test_data[i][0] = rand()%1000;
        printf("%d ",test_data[i][0]);
    }
    printf("\n\n");

    doubll2d_init(&test_list);

    while (input != 0) {
    
    
        scanf("%d", &input);
        if (input == 1) doubll2d_insert_row(&test_list, test_list.head, (void **)test_data, size, 10);
        else if (input == 2) doubll2d_insert_row(&test_list, test_list.tail, (void **)test_data, size, 10);
        else if (input == 3) doubll2d_insert_col(&test_list, test_list.head, (void **)test_data, size, 10);
        else if (input == 4) doubll2d_insert_col(&test_list, test_list.tail, (void **)test_data, size, 10);
        else if (input == 5) doubll2d_delete_row(&test_list, test_list.head);
        else if (input == 6) doubll2d_delete_row(&test_list, test_list.tail);
        else if (input == 7) doubll2d_delete_col(&test_list, test_list.head);
        else if (input == 8) doubll2d_delete_col(&test_list, test_list.tail);
        else if (input == 9) doubll2d_purge(&test_list);
        travel(&test_list);
        printf("\nsize: %lu, %lu\n", test_list.dim_row, test_list.dim_col);
        printf("\nover!\n\n");
    }

    return 0;
}

大家可以自己调试玩一下

653 386 205 325 642 51 325 345 299 353 

1
653 
size: 1, 1

over!

1
653 
653 
size: 2, 1

over!

3
653 653 
653 386 
size: 2, 2

over!

3
653 653 653 
653 386 386 
size: 2, 3

over!

4
653 653 653 653 
653 386 386 386 
size: 2, 4

over!

5
653 386 386 386 
size: 1, 4

over!

6

size: 0, 0

over!

2.生成Testcase

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "doubll2d.c"
void List2D_PrintList(doubll2d* list);
void List2D_PrintChain(doubll2d_elem* chain);
void List2D_Free(doubll2d* list);
void Data_shift(int shift);
void Data_free();

bool lessThan(doubll2d_elem* a, doubll2d_elem* b);

#define N 1010
doubll2d list;
void* data[N];
size_t size[N];

int main()
{
    
    
	/* 初始化 data */
	int i; doubll2d_elem* result;
	for (i = 0; i < N; ++i) data[i] = NULL;
	data[0] = malloc(sizeof(int)); size[0] = sizeof(int); *((int*)(data[0])) = 0;
	data[1] = malloc(sizeof(int)); size[1] = sizeof(int); *((int*)(data[1])) = 1;
	data[2] = malloc(sizeof(int)); size[2] = sizeof(int); *((int*)(data[2])) = 2;
	data[3] = malloc(sizeof(int)); size[3] = sizeof(int); *((int*)(data[3])) = 3;
	data[4] = malloc(sizeof(int)); size[4] = sizeof(int); *((int*)(data[4])) = 4;
	data[5] = malloc(sizeof(int)); size[5] = sizeof(int); *((int*)(data[5])) = 5;
	/* 初始化 list */
	doubll2d_init(&list);
	/* test row */
	result = doubll2d_insert_row(&list, NULL, data, size, 2); Data_shift(10); 
	result = doubll2d_insert_row(&list, list.head, data, size, 2); Data_shift(10); 
	result = doubll2d_insert_row(&list, list.head, data, size, 2); Data_shift(10); 
	/* test col */
	result = doubll2d_insert_col(&list, list.tail, data, size, 4); Data_shift(10); 
	result = doubll2d_insert_col(&list, list.head, data, size, 4); Data_shift(10); 
	result = doubll2d_insert_row(&list, list.head, data, size, 4); Data_shift(10); 
	result = doubll2d_insert_col(&list, list.head->right, data, size, 4); Data_shift(10); 
	result = doubll2d_delete_row(&list, list.head->down); Data_shift(10); 
	result = doubll2d_insert_row(&list, list.tail->left, data, size, 4); Data_shift(10); 
	result = doubll2d_insert_row(&list, list.tail->up, data, size, 4); Data_shift(10); 
	result = doubll2d_insert_col(&list, list.tail->left, data, size, 5); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_insert_col(&list, list.tail, data, size, 6); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_insert_row(&list, list.tail, data, size, 6); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_insert_col(&list, list.tail, data, size, 6); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_insert_row(&list, list.tail, data, size, 6); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_insert_col(&list, list.tail, data, size, 6); Data_shift(10); List2D_PrintList(&list);
	// printf("max value = %d\n", *((int*)(doubll2d_find_max(&list, lessThan)->data))); /* max = 155*/
	// printf("min value = %d\n", *((int*)(doubll2d_find_min(&list, lessThan)->data))); /* min = 0*/
	result = doubll2d_delete_row(&list, list.head->right->right->down->down); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_col(&list, list.head); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_row(&list, list.tail); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_col(&list, list.tail); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_row(&list, list.head); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_col(&list, list.tail->left); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_row(&list, list.head->right); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_col(&list, list.tail); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_row(&list, list.head); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_row(&list, list.tail); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_row(&list, list.tail); Data_shift(10); List2D_PrintList(&list);
	result = doubll2d_delete_col(&list, list.head); Data_shift(10); List2D_PrintList(&list);
	printf("cursor address = %p\n", (void*)result); /*result = NULL*/
	doubll2d_purge(&list);
	List2D_Free(&list);
	Data_free();
	return 0;
}

void List2D_Free(doubll2d* list)
{
    
    
	doubll2d_elem* itBegin, * it;
	if (list == NULL) return;
	itBegin = list->head, it = itBegin;
	while (itBegin != NULL)
	{
    
    
		itBegin = itBegin->down;
		while (it != NULL)
		{
    
    
			doubll2d_elem* freed = it; it = it->right;
			free(freed->data);
			free(freed);
		}
		it = itBegin;
	}
}

void List2D_PrintList(doubll2d* list)
{
    
    
	doubll2d_elem** rowBuffer; doubll2d_elem* itBegin, * it;
	if (list == NULL || list->head == NULL || list->tail == NULL) {
    
     printf("Empty\n\n"); return; }
	printf("---------------------------------------------------------------\n");
	printf("ROW = %ld    COL = %ld\n", (long unsigned int)list->dim_row, (long unsigned int)list->dim_col);
	rowBuffer = malloc(sizeof(doubll2d_elem*) * list->dim_col);
	itBegin = list->head; it = itBegin;
	while (true)
	{
    
    
		size_t i = 0;
		itBegin = itBegin->down;
		while (it != NULL)
		{
    
    
			rowBuffer[i++] = it;
			it = it->right;
		}
		for (i = 0; i < list->dim_col; ++i) {
    
     printf("p=%p   ", (void*)rowBuffer[i]); } putchar('\n');
		for (i = 0; i < list->dim_col; ++i) {
    
     printf("v=%d          ", *((int*)(rowBuffer[i]->data))); } putchar('\n');
		for (i = 0; i < list->dim_col; ++i) {
    
     printf("s=%ld          ", (unsigned long int)rowBuffer[i]->size); } putchar('\n');
		for (i = 0; i < list->dim_col; ++i) {
    
     printf("u=%p   ", (void*)rowBuffer[i]->up); } putchar('\n');
		for (i = 0; i < list->dim_col; ++i) {
    
     printf("d=%p   ", (void*)rowBuffer[i]->down); } putchar('\n');
		for (i = 0; i < list->dim_col; ++i) {
    
     printf("l=%p   ", (void*)rowBuffer[i]->left); } putchar('\n');
		for (i = 0; i < list->dim_col; ++i) {
    
     printf("r=%p   ", (void*)rowBuffer[i]->right); } putchar('\n');
		if (itBegin == NULL) break;
		else {
    
     it = itBegin; putchar('\n'); }
	}
	free(rowBuffer);
	printf("---------------------------------------------------------------\n");
	putchar('\n'); putchar('\n');
}


void List2D_PrintChain(doubll2d_elem* chain)
{
    
    
	doubll2d_elem* it;
	for (it = chain; it != NULL; it = it->right) {
    
     printf("p=%p   ", (void*)it); } putchar('\n');
	for (it = chain; it != NULL; it = it->right) {
    
     printf("v=%d          ", *((int*)(it->data))); } putchar('\n');
	for (it = chain; it != NULL; it = it->right) {
    
     printf("s=%ld          ", (long unsigned int)it->size); } putchar('\n');
	for (it = chain; it != NULL; it = it->right) {
    
     printf("l=%p   ", (void*)it->left); } putchar('\n');
	for (it = chain; it != NULL; it = it->right) {
    
     printf("r=%p   ", (void*)it->right); } putchar('\n');
	putchar('\n');
}

bool lessThan(doubll2d_elem* a, doubll2d_elem* b)
{
    
    
	return *((int*)(a->data)) < *((int*)(b->data));
}

void Data_shift(int shift)
{
    
    
	for (int i = 0; i < 6; ++i)
	{
    
    
		*((int*)(data[i])) += shift;
	}
}

void Data_free()
{
    
    
	int i;
	for (i = 0; i < N; ++i)
	{
    
    
		if (data[i] != NULL)
			free(data[i]);
	}
}

请务必看一眼

这个二维链表的实现对于输入比较随意所以判断较多,并且输入种类复杂,各位可以各取所需,对函数的输入和判断进行删减。然后没有实现在(i,j)处插入元素的命令,因为在该链表下,无法做到单独删除(要保证二维链表的矩阵形状),两种testcase都非常有意思,他们蕴含思想不同,我认为比二维链表的实现更加具有含金量,学会自己写testcase,生成它们来检测代码进行DEBUG,是一种非常重要的能力,需要考察到很多边际条件并进行分类,然后逻辑上,每个边际在判断条件下也有不同的优先级。与各位共勉(感谢我的hxd,wyh和cyf对于main函数的贡献)

猜你喜欢

转载自blog.csdn.net/Cplus_ruler/article/details/115056411