带头双向循环链表的的基本操作

我最近在学习数据结构中的链表中的一些收获,如下所示。

1.引入我们的头文件,函数申明,及实现;

#pragma once
#include<stdio.h>
#include<assert.h>
#include<malloc.h>
#include<stdbool.h>
#define DCList_ElemType int
typedef struct DCListNode
{
	DCList_ElemType data;
	struct DCListNode* prev;
	struct DCListNode* next;
}DCListNode;

typedef DCListNode* DCList;

//函数申明
void DCListInit(DCList* ph);
void DCListPushBack(DCList ph, DCList_ElemType x);
void DCListPushFront(DCList ph, DCList_ElemType x);
void DCListPopBack(DCList ph);
void DCListPopFront(DCList ph);
DCListNode* DCListFind(DCList ph, DCList_ElemType x);
void DCListDeleteByVal(DCList ph, DCList_ElemType x);
int  DCListLength(DCList ph);
void DCListInsertByVal(DCList ph, DCList_ElemType x);
void DCListClear(DCList ph);
void DCListReverse(DCList ph);
void DCListShow(DCList ph);
void DCListDestroy(DCList* ph);


//函数实现

void DCListInit(DCList* ph)
{
	assert(ph != NULL);
	(*ph) = (DCListNode*)malloc(sizeof(DCListNode));
	assert(*ph != NULL);
	(*ph)->next = (*ph)->prev = (*ph);
}

void DCListPushBack(DCList ph, DCList_ElemType x)
{
	DCListNode* s = (DCListNode*)malloc(sizeof(DCListNode));
	assert(s != NULL);
	s->data = x;

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

void DCListPushFront(DCList ph, DCList_ElemType x)
{
	DCListNode* s = (DCListNode*)malloc(sizeof(DCListNode));
	assert(s != NULL);
	s->data = x;

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

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

int  DCListLength(DCList ph)
{
	DCListNode* p = ph->next;
	DCList_ElemType count = 0;

	while (p != ph)
	{
		++count;
		p = p->next;
	}
	return count;
}

void DCListPopBack(DCList ph)
{
	assert(ph != NULL);
	DCListNode* p = ph->prev;

	ph->prev = ph->prev->prev;
	ph->prev->next = ph;
	free(p);
}

void DCListPopFront(DCList ph)
{
	assert(ph != NULL);
	DCListNode* p = ph->next;

	ph->next = ph->next->next;
	ph->next->prev = ph;
	free(p);
}

void DCListInsertByVal(DCList ph, DCList_ElemType x)
{
	assert(ph != NULL);
	DCListNode* s = (DCListNode*)malloc(sizeof(DCListNode));
	assert(s != NULL);
	s->data = x;
	DCListNode* p = ph->next;

	while (p != ph && p->data < x)
		p = p->next;
		
	s->next = p;
	s->prev = p->prev;
	s->prev->next = s;
	p->prev = s;
}

void DCListDeleteByVal(DCList ph, DCList_ElemType x)
{
	assert(ph != NULL);
	DCListNode* p = DCListFind(ph, x);

	if (p != NULL)
	{
		p->prev->next = p->next;
		p->next->prev = p->prev;
		free(p);
	}
}

DCListNode* DCListFind(DCList ph, DCList_ElemType x)
{
	
	assert(ph != NULL);
	DCListNode* p = ph->next;

	while (p != ph)
	{
		if (p->data == x)
			return p;

		p = p->next;
	}
	return NULL;
}

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

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

}

//有问题的
/*void DCListClear(DCList ph)
{
	assert(ph != NULL);
	DCListNode* p = NULL; //只是申请了指针节点
	p = ph->next;
	
	while (p != ph)
	{
		DCListNode* q = p; 
		p = p->next;       //p非链式结构,后面没有节点,指向非法故产生警告
		free(p);
	}
	
}*/

void DCListClear(DCList ph)
{
	assert(ph != NULL);
	DCListNode* p = NULL;
	p = ph->next;

	while (p != ph)
	{
		DCListNode* q = p;
		p->prev->next = p->next;
		p->next->prev = p->prev;
		p = p->next;
		free(q);
	}

}

void DCListDestroy(DCList* ph)
{
	assert(ph != NULL);
	DCListClear(*ph);
	free(*ph);
	*ph = NULL;
}

2.主函数对链表功能的调用。

#include"DcList.h"
int main()
{
	DCList mylist;
	DCListInit(&mylist);
	int Select = 0;
	int pos = 0;
	int x = 0;
	DCListNode* p = NULL;
	while (1)
	{
		printf("**************************************\n");
		printf("*[1]  PushBack     [2]  PushFront    *\n");
		printf("*[3]  ShowList     [4]  Length       *\n");
		printf("*[5]  PopBack      [6]  PopFront     *\n");
		printf("*[7]  Insert_Val   [8]  Delate_Val   *\n");
		printf("*[9]  Find         [10] Reverse      *\n");
		printf("*[11]              [12] Clear        *\n");
		printf("**********[0] Quit System*************\n\n");
		printf("请选择\n");
		scanf_s("%d", &Select);
		if (Select == 0)
		{
			printf("已经退出\n");
			return 0;
		}
		switch (Select)
		{
		case 1:
			printf("请输入要尾插数据(以-1结束)\n");
			while (scanf_s("%d", &x), x != -1)
			{
				DCListPushBack(mylist, x);
			}
			break;
		case 2:
			printf("请输入要头插数据(以-1结束)\n");
			while (scanf_s("%d", &x), x != -1)
			{
				DCListPushFront(mylist, x);
			}
			break;
		case 3:
			
			printf("显示链表\n");
			DCListShow(mylist);
			break;
		case 4:
			x = DCListLength(mylist);
			printf("链表长度为%d\n", x);
			break;
		case 5:
			DCListPopBack(mylist);
			break;
		case 6:
			DCListPopFront(mylist);
			break;
		case 7:
			printf("输入你想插入的值\n");
			scanf_s("%d", &x);
			DCListInsertByVal(mylist, x);
			break;
		case 8:
			printf("输入你想删除的值\n");
			scanf_s("%d", &x);
			DCListDeleteByVal(mylist, x);
			break;
		case 9:
			printf("输入你想查找的值\n");
			scanf_s("%d", &x);
			 p = DCListFind(mylist, x);
			 if (p == NULL)
			 {
				 printf("没有该值\n");
				 break;
			 }
			 printf("你想查找的值的地址\n");
			printf("%p\n", &p);
			break;
		case 10:
			DCListReverse(mylist);
			printf("链表的逆置已完成\n");
			break;
		case 11:
			printf("空操作\n");
			break;
		case 12:
			DCListClear(mylist);
			break;
		default:
			break;
		}

	}
	DCListDestroy(&mylist);
}

感谢大家观看!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值