10.5 双向链表基本运算

//10.5 双向链表基本运算
#include <stdio.h>
#include <stdlib.h>

typedef struct dlnode
{
	char data;             //data 为节点的数据信息
	struct dlnode *prior;  //prior 为指向前驱结点的指针
	struct dlnode *next;   //next  为指向后继节点的指针
}DLNode;                   //双向链表节点类型                 

DLNode * CreateDlinkList() //建立带头节点的双向循环链表
{
	DLNode *head, *s;
	char x;
	head = (DLNode *)malloc(sizeof(DLNode));  //先生成仅含头系欸但的空双向循环链表
	head->prior = head;
	head->next = head;
	
	printf("Input any char string:\n");
	scanf("%c", &x);                          //读入节点数据
	while (x != '\n')
	{
		s = (DLNode *)malloc(sizeof(DLNode)); //生成待插入节点的存储空间
		s->data = x;                          //将读入的数据赋值给待插入节点*s
		s->prior = head;                      //新插入的节点*s其前驱结点为头节点*head
		s->next = head->next;                 //插入后*s的后继节点为头节点*head原来的后继节点
		head->next->prior = s;                //头节点的原后继节点其前驱结点为*s
		head->next = s;                       //头节点此时新的后继节点为*s

		scanf("%c", &x);
	}
	return head;                              //返回头指针
}

DLNode *Get_DLinkList(DLNode *head, int i)
{											  //在单链表head中按序号查找第i个节点
	DLNode *p = head;
	int j = 0;
	while (p->next != head && j < i)          //由第一个数据节点开始查找,j 用于计数
	{
		p = p->next;
		j++;
	}

	if (p->next != head)
	{
		return p;                             //找到则返回指向i 节点的指针值
	}
	else
	{
		return NULL;                          //找不到则返回空值
	}
}

void Insert_DLinkList(DLNode *head, int i, char x)
{                                             //在单链表head 的第i 个位置上插入值为x 的元素
	DLNode *p, *s;
	p = Get_DLinkList(head, i - 1);           //查找第i-1 个节点
	if (p == NULL)
	{
		printf("Error!\n");                   //第i-1 个节点位置不存在而无法插入
	}
	else
	{
		s = (DLNode *)malloc(sizeof(DLNode)); //申请节点空间
		s->data = x;
		s->prior = p;                         //新插入的节点*s其前驱节点为*p
		s->next = p->next;                    //插入后*s 的后继节点为*p 原来的后继节点
		p->next->prior = s;                   //*p 原后继节点此时的前驱结点为*s 
		p->next = s;                          //插入后*p 的后继节点为*s
	}
}

void Del_DLinkList(DLNode *head, int i)      
{                                             //删除单链表head 上的第i个节点
	DLNode *p;
	p = Get_DLinkList(head, i);                  //查找第i 个节点
	if (p == NULL)
	{
		printf("第i 个数据节点不存在!\n");   //待删节点不存在
	}
	else
	{
		p->prior->next = p->next;             //待删节点*p 的前驱结点其后继指针指向*p 的后继节点
		p->next->prior = p->prior;            //待删节点*p 的后继节点其前驱指针指向*p 的前驱结点
		free(p);                              //系统回收*p 节点的存储空间
	}
}

void print1(DLNode *h)                       //后向输出双向循环链表
{
	DLNode *p;
	p = h->next;
	while (p != h)
	{
		printf("%c, ", p->data);
		p = p->next;
	}
	printf("\n");
}

void print2(DLNode *h)                        //前向输出双向循环链表
{
	DLNode *p;
	p = h->prior;
	while (p != h)
	{
		printf("%c, ", p->data);
		p = p->prior;
	}
	printf("\n");
}

int main()
{
	DLNode *h, *p;
	int i;
	char x;

	h = CreateDlinkList();               //建立带头节点的双向循环链表
	printf("Output list for next\n");
	print1(h);                           //后向输出双向循环链表

	printf("Output list for prior\n");   
	print2(h);                           //前向输出双向循环链表

	printf("Input order and search to element:\n");
	scanf("%d", &i);                     //输入要查找元素的序号
	p = Get_DLinkList(h, i);             //按序号在顺序表中查找
	if (p != NULL)
	{
		printf("Element is %c\n", p->data);  //找到则输出该元素的值
	}
	else
	{
		printf("Search fail!\n");            //未找到
	}
	
	printf("Insert a element, Input site and value of element:\n");
	scanf("%d %c", &i, &x);                  //输入要插入元素的位置值i 和元素值x
	Insert_DLinkList(h, i, x);               //在双向循环链表中插入该元素
	print1(h);                               //输出双向循环链表节点信息

	printf("Delete a element, Input site of element:\n");
	scanf("%d", &i);                         //输入要删除元素的位置值i
	Del_DLinkList(h, i);                     //在单链表中删除该位置上的元素
	print1(h);                               //输出双向循环链表节点信息

	printf("Press any key to quit.");
	getchar();                               //接收回车键
	getchar();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值