双向循环链表 (只需要一个 head 节点), 从头尾部 删除 插入 数据都比较方便

Posted 皮特99

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双向循环链表 (只需要一个 head 节点), 从头尾部 删除 插入 数据都比较方便相关的知识,希望对你有一定的参考价值。

#include "common.h"

#define nullptr 0
#define maxmemsize 21

typedef struct memNode {
	int data;
	int next;
}memNode;

typedef struct memlinklist
{
	memNode memory[maxmemsize];
	int freep;
	int headp;
}memlinklist;
static memlinklist mMemorylink;

int allocate_node()
{
	int addr = mMemorylink.freep;
	mMemorylink.freep = mMemorylink.memory[mMemorylink.freep].next;
	return addr;
}

void free_node(int memidx)
{
	mMemorylink.memory[memidx].next = mMemorylink.freep;
	mMemorylink.freep = memidx;
}

typedef struct LinkNode
{
	int id;
	int data;
	int memidx;
	LinkNode *prev;
	LinkNode *next;
}LinkNode;

static LinkNode g_n_mem[maxmemsize];

typedef struct Queue
{
	LinkNode *head; //只需要一个 head 实现双向循环链表
	int size;
}Queue;

typedef struct memHeap
{
	int heap[maxmemsize];
	int tail;
}memHeap;

static LinkNode * my_allocate(memHeap *mMemHeap) // 循环内存也可以通过 g_n_mem[g_n_mem_cnt++ % maxmemsize] 实现
{
	if (mMemHeap->tail <= 0)
		return nullptr;
	return &g_n_mem[mMemHeap->heap[--mMemHeap->tail]];
}

static void my_free(memHeap *mMemHeap, int memidx)
{
	mMemHeap->heap[mMemHeap->tail++] = memidx;
}
static void init_queue(Queue **queue, memHeap *mMemHeap)
{
	if ((*queue) == nullptr)
	{
		(*queue) = new Queue;
	}

	Queue *Q = (*queue);
	Q->head = my_allocate(mMemHeap);
	Q->head->prev = Q->head->next = Q->head;
	Q->size = 0;
}

static void en_queue_head(Queue* Q, LinkNode *pNode)
{
	pNode->next = Q->head->next;
	pNode->prev = Q->head;
	Q->head->next->prev = pNode;
	Q->head->next = pNode;
	Q->size++;
}

static void en_queue_tail(Queue* Q, LinkNode *pNode)
{
	pNode->next = Q->head;
	pNode->prev = Q->head->prev;
	Q->head->prev->next = pNode;
	Q->head->prev = pNode;
	Q->size++;
}

static LinkNode * de_queue_head(Queue* Q, memHeap *mMemHeap)
{
	if (Q->size <= 0)
		return nullptr;

	LinkNode *pNode = Q->head->next;
	pNode->next->prev = Q->head;
	Q->head->next = pNode->next;
	Q->size--;
	mMemHeap->heap[mMemHeap->tail++] = pNode->memidx;
	return pNode;
}

static LinkNode * de_queue_tail(Queue* Q, memHeap *mMemHeap)
{
	if (Q->size <= 0)
		return nullptr;

	LinkNode * pNode = Q->head->prev;
	pNode->prev->next = Q->head;
	Q->head->prev = pNode->prev;
	Q->size--;
	my_free(mMemHeap, pNode->memidx);
	return pNode;
}

static LinkNode * delete_key(Queue* Q, memHeap *mMemHeap, int key)
{
	if (Q->size <= 0)
		return nullptr;

	LinkNode * pNode = Q->head->next;
	while (pNode != Q->head)
	{
		if (pNode->data == key)
		{
			pNode->prev->next = pNode->next;
			pNode->next->prev = pNode->prev;
			Q->size--;
			break;
		}
		pNode = pNode->next;
	}

	my_free(mMemHeap, pNode->memidx);
	return pNode;
}

static void clear_queue(Queue* Q, memHeap *mMemHeap)
{
	if (Q->size <= 0)
		return;

	LinkNode * pNode = Q->head->next;
	while (pNode != Q->head)
	{
		my_free(mMemHeap, pNode->memidx);
		pNode = pNode->next;
	}

	Q->head->prev = Q->head->next = Q->head;
}
static void display_queue(Queue* Q)
{
	if (Q->size <= 0)
	{
		LOGE("Q is null, return");
		return;
	}
	LinkNode *pNode = Q->head->next;
	//for (register int i = 0; i < Q->size; i++)
	while (pNode != Q->head)
	{
		printf("[%d %d] ", pNode->id, pNode->data);
		pNode = pNode->next;
	}
	printf("\\n\\n");
}

static void init_doule_list(Queue *Q, memHeap *mMemHeap, int num)
{
	srand((int)time(0));
	for (register int i = 0; i < num; i++)
	{
		LinkNode *pNode = my_allocate(mMemHeap);
		pNode->id = i;
		pNode->data = i + 100;; //次关键字
		//pNode->data = 1 + rand() % (100 - 10 + 1) + 10;
		printf("[%d %d] ", pNode->id, pNode->data);

		//虽然进队函数不同,但下面两个生成的链表最终包含的数据是一样的
		//en_queue_head(Q, pNode);
		en_queue_tail(Q, pNode);

	}
	printf("\\n\\n");
}

static void init_memory(memHeap **mMemHeap)
{
	*mMemHeap = new memHeap;
	(*mMemHeap)->tail = maxmemsize; // 0 ~ maxmemsize-1
	for (register int i = 0; i < maxmemsize; i++)
	{
		g_n_mem[i].memidx = i;
		(*mMemHeap)->heap[i] = i;
	}
}

extern void test_one_head_double_list()
{
	static memHeap *mMemHeap;
	init_memory(&mMemHeap);

	static Queue *mQ;
	init_queue(&mQ, mMemHeap);
	init_doule_list(mQ, mMemHeap, 20);
	display_queue(mQ);

	LOGE("dequeue from head : ");
	while (mQ->size > 0)
	{
		LinkNode *pNode = de_queue_head(mQ, mMemHeap);
		printf("[%d %d] memidx= %d Q size = %d tail= %d\\n", pNode->id, pNode->data, pNode->memidx, mQ->size, mMemHeap->tail);
		pNode->prev = pNode->next = nullptr;
	}
	LOGE("\\n");

	clear_queue(mQ, mMemHeap);
	init_doule_list(mQ, mMemHeap, 20);
	display_queue(mQ);
	delete_key(mQ, mMemHeap, 110); //delete the node who\'s data == 20
	display_queue(mQ);
	LOGE("dequeue from tail : ");
	while (mQ->size > 0)
	{
		LinkNode *	pNode = de_queue_tail(mQ, mMemHeap);
		printf("[%d %d] memidx= %d Q size = %d tail= %d\\n", pNode->id, pNode->data, pNode->memidx, mQ->size, mMemHeap->tail);
		pNode->prev = pNode->next = nullptr;
	}
	LOGE("\\n");

	display_queue(mQ);

	delete mMemHeap;
	mMemHeap = nullptr;
	delete mQ;
	mQ = nullptr;
}

  

以上是关于双向循环链表 (只需要一个 head 节点), 从头尾部 删除 插入 数据都比较方便的主要内容,如果未能解决你的问题,请参考以下文章

数据结构循环链表&&双向链表详解和代码实例

C语言教程“双向循环链表”学习总结及其代码实现

双向循环链表实现

双向循环链表实现

双向循环链表实现

双向循环链表实现