讨论/综合讨论/关于在C语言中使用常用数据结构的问题/
关于在C语言中使用常用数据结构的问题

C语言的标准库并没有提供诸如链表之类的容器,做题的时候需要用到,如果按照具体问题具体分析的方法进行手写会导致程序不结构化、变得复杂难懂(比如为了实现一个链表弄得提交代码的主函数里一堆malloc和free)。我的做法是自己在本地实现一些例程,然后做题用到的时候拷贝进solution里。求教除了这样外还有什么更好的方法吗?
举例说明,以下是我在[https://leetcode-cn.com/problems/number-of-connected-components-in-an-undirected-graph/](323. 无向图中连通分量的数目)中的提交。我用双向链表来实现BFS中用到的队列。我把我自己写的双向链表实现直接拷贝进去了。

#define EOL NULL
typedef int ListElementType;
typedef struct _My_ListNode{
	ListElementType element;
	struct _My_ListNode *next;
	struct _My_ListNode *prev;
} MyListNode, *Position;

typedef struct _List_Record{
	MyListNode firstDummy;
	MyListNode lastDummy;
	int size;
} *List;

List List_Create(void);
void List_Delete(List L);
bool List_IsEmpty(List L);
void List_InsertIntoFirst(List L, ListElementType X);
ListElementType List_DeleteLastElement(List L);
ListElementType List_Retrieve(Position P);
Position List_FirstPosition(List L);
Position List_PositionAdvance(List L, Position P);
/*以上是关于链表的声明*/
void BFS(List *G, int n, int source, bool *color);

int countComponents(int n, int **edges, int edgesSize, int *edgesColSize)
{
    if(n == 0) return 0;
    bool color[n];
    int i, ans = 0;
    List AdjL[n];
    for(i = 0; i < n; i++){
        color[i] = 0;
        AdjL[i] = List_Create();
    }
    for(i = 0; i < edgesSize; i++){
        List_InsertIntoFirst(AdjL[edges[i][0]], edges[i][1]);
        List_InsertIntoFirst(AdjL[edges[i][1]], edges[i][0]);
    }
    for(i = 0; i < n; i++){
        if(!color[i]){
            ans++;
            BFS(AdjL, n, i, color);
        }
    }
    for(i = 0; i < n; i++)
        List_Delete(AdjL[i]);
    return ans;
}

void BFS(List *G, int n, int source, bool *color)
{
    int u, v;
    List queue = List_Create();
    Position P;
    color[source] = 1;
    List_InsertIntoFirst(queue, source);
    while(!List_IsEmpty(queue)){
        u = List_DeleteLastElement(queue);
        P = List_FirstPosition(G[u]);
        while(P != EOL){
            v = List_Retrieve(P);
            P = List_PositionAdvance(G[u], P);
            if(!color[v]){
                color[v] = 1;
                List_InsertIntoFirst(queue, v);
            }
        }
    }
    List_Delete(queue);
    return;
}

/*List routines*/
List List_Create(void)
{
	List L = malloc(sizeof(struct _List_Record));
	L->size = 0;
	L->firstDummy.prev = NULL;
	L->firstDummy.next = &(L->lastDummy);
	L->lastDummy.next = NULL;
	L->lastDummy.prev = &(L->firstDummy);
	return L;
}

void List_Delete(List L)
{
	MyListNode *p = L->firstDummy.next, tmp;
	while(p != &(L->lastDummy)){
		p = p->next;
		free(p->prev);
	}
	free(L);
	return;
}

bool List_IsEmpty(List L)
{
	return L->size == 0;
}

void List_InsertIntoFirst(List L, ListElementType X)
{
	MyListNode *tmp = L->firstDummy.next;
	L->firstDummy.next = malloc(sizeof(MyListNode));
	L->firstDummy.next->prev = &(L->firstDummy);
	L->firstDummy.next->next = tmp;
	tmp->prev = L->firstDummy.next;
	L->firstDummy.next->element = X;
	L->size++;
	return;
}

ListElementType List_DeleteLastElement(List L)
{
	ListElementType ret = L->lastDummy.prev->element;
	L->lastDummy.prev = L->lastDummy.prev->prev;
	free(L->lastDummy.prev->next);
	L->lastDummy.prev->next = &(L->lastDummy);
	L->size--;
	return ret;
}

ListElementType List_Retrieve(Position P)
{
	return P->element;
}

Position List_PositionAdvance(List L, Position P)
{
	P = P->next;
	return (P != &(L->lastDummy)) ? P : EOL;
}

Position List_FirstPosition(List L)
{
	return (L->size != 0) ? L->firstDummy.next : EOL;
}

作为新手见笑了,虚心学习。

展开讨论
#define mian main发起于 2019-08-27

可以参考 C++的list库