欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【C语言】双向循环链表

程序员文章站 2024-03-22 11:29:07
...

一.头文件

#ifndef _COMMON_H_
#define  _COMMON_H_

// 用到的头文件
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <malloc.h>
#define ElemType int
#include <vld.h> // 用于内存泄漏
#pragma warning(disable :4996)

#endif

二.函数实现

#ifndef __DCLIST_H__
#define __DCLIST_H__
#include "Common.h"

typedef struct DCListNode
{
	ElemType data;
	DCListNode *prev;
	DCListNode *next;
}DCListNode;

typedef DCListNode* DCList;


void DCListInit(DCList *phead);
void DCListPushBack(DCList* phead, ElemType x);
void DCListNodeShow(DCList phead);
void DCListPushFront(DCList *phead, ElemType x);
void DCListNodePopBack(DCList* phead);
void DCListNodePopFront(DCList* phead);
void DCListByVal(DCList* phead,ElemType x);
void DCListEraseVal(DCList phead, ElemType x);
DCListNode* DCListFind(DCList phead,ElemType x);
size_t DCListLength(DCList phead);
void DCListSort(DCList phead);
void DCListReverse(DCList phead);
void DCListClear(DCList* phead);

size_t DCListFront(DCList phead);
size_t DCListBack(DCList phead);

void DCListDestory(DCList* phead);

//////////////////////////
DCListNode* DCListBuyNode(ElemType v = ElemType())
{
	DCListNode* _s = (DCListNode*)malloc(sizeof(DCListNode));
	assert(_s != NULL);
	_s->data = v;
	_s->next = _s->prev = _s;
	return _s;
}

void DCListInit(DCList *phead)
{
	*phead = DCListBuyNode();
}

void DCListPushBack(DCList* phead, ElemType x)
{
	DCListNode* s = DCListBuyNode(x);
	DCListNode* head = *phead;

	s->prev = head->prev;
	s->next = head;
	head->prev->next = s;
	head->prev = s;
}

void DCListNodeShow(DCList phead)
{
	DCListNode* p = phead->next;
	while (p != phead)
	{
		printf("%d->", p->data);
		p = p->next;
	}
	printf("Over.\n");
}

void DCListPushFront(DCList *phead, ElemType x)
{
	DCListNode* s = DCListBuyNode(x);
	DCListNode* head = *phead;

	s->next = head->next;
	s->prev = head;
	head->next = s;
	s->next->prev = s;
}

void DCListNodePopBack(DCList* phead)
{
	assert(phead != NULL);
	DCListNode* p = (*phead)->prev;
	DCListNode* head = *phead;

	if (head->next == head)
		return;

	p->prev->next = head;
	head->prev = p->prev;

	free(p);
}


void DCListNodePopFront(DCList* phead)
{
	assert(phead != NULL);
	DCListNode* p = (*phead)->next;
	DCListNode* head = *phead;

	if (head->next == head)
		return;

	p->next->prev = head;
	head->next = p->next;

	free(p);
}

void DCListEraseVal(DCList phead, ElemType x)
{
	assert(phead != NULL);
	DCListNode* p = DCListFind(phead, x);

	if (p == NULL)
		return;
	p->prev->next = p->next;
	p->next->prev = p->prev;

	free(p);
}

DCListNode* DCListFind(DCList phead,ElemType x)
{
	DCListNode* p = phead->next;
	while (p != phead && p->data != x)
		p = p->next;

	if (p == phead)
		return NULL;
	return p;
}

size_t DCListLength(DCList phead)
{
	assert(phead != NULL);
	size_t count = 0;
	DCListNode* p = phead->next;
	while (p != phead)
	{
		count++;
		p = p->next;
	}
	return count;
}

size_t DCListFront(DCList phead)
{
	assert(phead != NULL);
	assert(phead->next != phead);
	return phead->next->data;
}
size_t DCListBack(DCList phead)
{
	assert(phead != NULL);
	assert(phead->next != phead);
	return phead->prev->data;
}


void DCListClear(DCList* phead)
{
	assert(phead != NULL);
	DCListNode* cur = (*phead)->next;
	DCListNode* head = *phead;

	while (cur != *phead)
	{
		DCListNode* prev = cur;
		cur = cur->next;
		free(prev);
	}
	head->prev = head->next = head;
}

void DCListDestory(DCList* phead)
{
	assert(phead != NULL);
	DCListClear(phead);
	free(*phead);
	*phead = NULL;
}

void DCListSort(DCList phead)
{
	assert(phead != NULL);
	if (DCListLength(phead) == 1)
		return;
	DCListNode* p = phead->next;
	DCListNode* q = p->next;

	p->next = phead;
	phead->prev = p;

	while (q != phead)
	{
		p = q;
		q = q->next;

		DCListNode* tmp = phead->next ;
		while (tmp != phead && p->data > tmp->data )
			tmp = tmp->next;

		p->prev = tmp->prev;
		p->next = tmp;
		p->prev->next = p;
		p->next->prev = p;
	}
}

void DCListByVal(DCList* phead, ElemType x)
{
	assert(phead != NULL);
	DCListNode *s = DCListBuyNode(x);
	DCListNode* p = (*phead)->next;
	while (p != *phead && x > p->data)
		p = p->next;

	s->prev = p->prev;
	s->next = p;
	s->prev->next = s;
	s->next->prev = s; 
}

void DCListReverse(DCList phead)
{
	assert(phead != NULL);
	DCListNode* p = phead->next;
	DCListNode* q = p->next;

	p->next = phead;
	phead->prev = p;

	while (q != phead)
	{
		p = q;
		q = q->next;
		
		p->next = phead->next;
		p->prev = phead;
		p->prev->next = p;
		p->next->prev = p;
	}
}


#endif

三.测试函数

#include "dclist.h"
#pragma warning(disable :4996)

int main()
{
	DCList list;
	DCListInit(&list);
	DCListNode* p = NULL;

	ElemType item;
	//int pos;
	int select = 1;
	bool flag = true;
	// 棋盘
	while (select)
	{
		printf("********************************************\n");
		printf("**** [1] push_back      [2] push_front  ****\n");
		printf("**** [3] show_list      [0] quit_system ****\n");
		printf("**** [4] pop_back       [5] pop_front   ****\n");
		printf("**** [6] insert_pos     [7] insert_val  ****\n");
		printf("**** [8] erase_pos      [9] erase_val   ****\n");
		printf("**** [10] find          [11] length     ****\n");
		printf("**** [12] capcity       [13] sort       ****\n");
		printf("**** [14] reverse       [15] clear      ****\n");
		printf("**** [16] front         [17] back       ****\n");
		printf("**** [18] binary_find   [19] erase_all  ****\n");
		printf("********************************************\n");
		printf("请选择:>");
		scanf("%d", &select);
		if (select == 0)
			break;
		switch (select)
		{
		case 1:
			printf("请输入你要插入的数字<以-1结束>:");
			while (scanf("%d", &item), item != -1)
			{
				DCListPushBack(&list, item);
			}
			printf("头部插入成功......\n");
			break;
		case 2:
			printf("请输入你要插入的数字<以-1结束>:");
			while (scanf("%d", &item), item != -1)
			{
				DCListPushFront(&list, item);
			}
			printf("尾部插入成功......\n");
			break;
		case 3:
			DCListNodeShow(list);
			break;
		case 4:
			DCListNodePopBack(&list);
			printf("尾部删除成功......\n");
			break;
		case 5:
			DCListNodePopFront(&list);
			printf("头部删除成功......\n");
			break;
		case 6:
			//printf("请输入要插入的位置:>");
			//scanf("%d", &pos);
			//printf("清输入要插入的数字:>");
			//scanf("%d", &item);
			////flag = SeqListInsertByPos(&list, pos, item);
			////if (flag)
			//	printf("插入数据成功......\n");
			////else
			//	printf("插入数据失败......\n");
			break;
		case 7:
			printf("请输入需要插入的数字:>");
			scanf("%d", &item);
			DCListSort(list);
			DCListByVal(&list,item);
			printf("任意位置的插入成功......\n");
			break;
		case 8:
			//printf("请输入你要删除的位置:>");
			//scanf("%d", &pos);
			////flag = SeqListEraseByPos(&list, pos);
			//if (flag)
			//	printf("删除自定位置元素成功......\n");
			//else
			//	printf("删除自定位置元素失败......\n");
			break;
		case 9:
			printf("请输入要删除的元素:>");
			scanf("%d", &item);
			DCListEraseVal(list, item);
			printf("删除指定元素成功......\n");

			break;
		case 10:
			printf("请输入要查找的数字:>");
			scanf("%d", &item);
			p = DCListFind(list, item);
			if (p == NULL)
				printf("查找失败.....\n");
			else
				printf("查找成功.....\n");
			break;
		case 11:
			printf("DCList length = %d\n", DCListLength(list));
			break;
		case 12:
			//printf("SeqList capacity = %d\n",DCListCapacity(&list));
			break;
		case 13:
			DCListSort(list);
			printf("链表排序成功.....\n");
			break;
		case 14:
			DCListReverse(list);
			printf("转置成功......\n");
			break;
		case 15:
			DCListClear(&list);
			printf("清除数据成功.......\n");
			break;
		case 16:
			printf("表头元素为:%d\n", DCListFront(list));
			break;
		case 17:
			printf("表尾元素为:%d\n", DCListBack(list));
			break;
		case 19:
			printf("请输入要删除的元素:>");
			scanf("%d", &item);
			//SListEraseValAll(&list, item);
			printf("删除指定元素成功......\n");
			break;
		default :
			printf("输入错误,请重新出入......\n");
			break;
		}
	}
	DCListDestory(&list);

	return 0;
}
相关标签: 双向循环链表