双链表-C语言

// 双链表

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int ElemType;

/*构建双链表结构体类型*/
typedef struct DNode
{
	ElemType data;  // 数据域
	struct DNode* prior, * next;  // 前驱和后继指针
}DNode;

/*函数声明*/
// 双链表初始化
DNode* initList();
// 输出
void outputList(DNode* dp);
// 通过下标获取结点值 
ElemType getElemByIndex(DNode* dp, int index);
// 通过下标获取结点值 getIndexByElem
int getIndexByElem(DNode* dp, ElemType e);
// 插入值
int insertElem(DNode* dp,int index, ElemType e);
// 删除值
ElemType delElemByIndex(DNode* dp, int index);
// 求表长
int lenList(DNode* dp);

int main(int argc, char** argv)
{
	// code
	int a;
	int index;  // 插入/删除的下标
	ElemType e;  // 要插入/删除的元素
	DNode* dp = NULL;

	// 初始化操作
	while (1)
	{
		printf("\n");
		printf("\n**************************\n");
		printf("==========================\n");
		printf("1. 创建双链表(尾插法)\n");
		printf("2. 查看双链表\n");
		printf("3. 按下标查找结点值\n");
		printf("4. 按值查找下标\n");
		printf("5. 插入结点操作\n");
		printf("6. 删除结点操作\n");
		printf("7. 求表长操作\n");
		printf("0. 退出\n");
		printf("请选择操作:");
		scanf("%d", &a);
		printf("\n==========================\n");
		printf("**************************\n");

		if (a == 0)
		{
			printf("=====程序结束=====\n");
			break;
		}

		switch (a)
		{
		case 1:
			dp = initList();
			break;
		case 2:
			outputList(dp);
			break;
		case 3:
			printf("请输入下标值:");
			scanf("%d", &index);
			e = getElemByIndex(dp, index);
			if (e)
			{
				printf("下标为%d的值为:%d\n", index, e);
			}
			else
			{
				printf("操作失败!!!");
			}
			break;
		case 4:
			printf("请输入查找的值:");
			scanf("%d", &e);
			index = getIndexByElem(dp, e);
			if (index != -1)
			{
				printf("值为%d的下标为:%d\n", e, index);
			}
			else
			{
				printf("操作失败!!!");
			}
			break;
		case 5:
			printf("请输入插入的下标:");
			scanf("%d", &index);
			printf("请输入插入的值:"); 
			scanf("%d", &e);
			index = insertElem(dp, index, e);
			if (!index)
			{
				printf("操作失败!!!");
			}
			break;
		case 6:
			printf("请输入删除的下标:");
			scanf("%d", &index);
			e = delElemByIndex(dp, index);
			printf("删除的值为:%d", e);
			break;

		case 7:
			index = lenList(dp);
			printf("双链表的表长为:%d\n", index);
			break;
		default:
			break;
		}

	}
	system("pause");
	return 0;
}

DNode* initList()
{
	int x;
	DNode* headp = (DNode*)malloc(sizeof(DNode));  // 创建一个头结点
	DNode* tailp = headp;  // 表尾结点,默认指向头结点
	DNode* tempp = NULL;  // 用于临时申请系统空间

	printf("请输入创建单链表的值(以回车间隔):\n");
	for (int i = 0; i < 5; i++)
	{
		scanf("%d", &x);  // 输入新结点值

		tempp = (DNode*)malloc(sizeof(DNode));  // 为新结点申请系统空间
		tempp->data = x;  // 新结点的值
		tailp->next = tempp;  // 上一结点的后继指向新结点
		tempp->prior = tailp;  // 新结点的前驱指向上一结点
		tailp = tempp;  // 指向新结点的表尾
	}
	tailp->next = NULL;
	return headp;
}

void outputList(DNode* dp)
{
	DNode* tempp = dp->next;  // 将头结点的后继赋给tempp

	printf("单链表为:");

	while (tempp)
	{
		printf("%d  ", tempp->data);
		tempp = tempp->next;
	}
}

ElemType getElemByIndex(DNode* dp, int index)
{
	DNode* tempp = dp->next;   // 将头结点的后继赋给tempp
	if (index < 0)
	{
		return NULL;  // 下标无效
	}

	for (int i = 1; i <= index; i++)  // 下标大于0时
	{
		if (tempp)
		{
			tempp = tempp->next;
		}
	}

	if (tempp)
	{
		return tempp->data;
	}
	else
	{
		return NULL;
	}

	
}

int getIndexByElem(DNode* dp, ElemType e)
{
	DNode* tempp = dp->next;  // z指向头结点de后继
	int len = lenList(dp);  // 获取链表的表长
	int i;

	for (i = 0; i < len; i++)
	{
		if (tempp && tempp->data == e)
		{
			return i;
			break;
		}
		tempp = tempp->next;
	}
	return -1;
}

int insertElem(DNode* dp, int index, ElemType e)
{
	DNode* tempp = dp;  // 
	if (index < 0 || index > lenList(dp))
	{
		return 0;   // 下标无效
	}

	for (int i = 0; i < index; i++)
	{
		tempp = tempp->next;  // 获取插入结点位置
	}

	DNode* newp = (DNode*)malloc(sizeof(DNode));  // 申请新的系统空间
	newp->data = e;  // 插入的结点值
	/*// 后插法*/
	// 新结点与后继结点相连
	newp->next = tempp->next;
	if (tempp->next)
	{
		tempp->next->prior = newp;  // 当插在末尾时,不需要此行
	}
	// 前驱结点与新结点相连
	tempp->next = newp;
	newp->prior = tempp;

	//DNode* priorp = tempp->prior;  // 插入结点位置的前驱结点
	 插入结点位置的前驱结点与新结点相连
	//priorp->next = newp;  
	//newp->prior = priorp;  
	 新结点与后继结点相连
	//newp->next = tempp;  
	//tempp->prior = newp;
	return 1;
}

ElemType delElemByIndex(DNode* dp, int index)
{
	DNode* tempp = dp->next;
	if (index < 0 || index > lenList(dp) - 1)
	{
		return NULL;  // 下标无效
	}
	
	for (int i = 0; i < index; i++)
	{
		tempp = tempp->next;
	}

	DNode* delp = tempp;  // 要被删除的结点
	ElemType delElem = delp->data;  // 保留要被删除的值
	DNode* priorp = tempp->prior;  // 被删除结点的前驱结点
	DNode* nextp = tempp->next;  // 被删除结点的后继结点

	// 前驱和后继相连
	priorp->next = nextp;
	if (tempp->next)
	{
		nextp->prior = priorp;  // 删除最后一个时,不需要执行
	}

	free(delp);  // 释放空间
	return delElem;
}

int lenList(DNode* dp)
{
	DNode* tempp = dp->next;
	int i = 0;

	while (tempp)
	{
		tempp = tempp->next;
		i++;
	}
	return i;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值