数据结构-双链表详解

数据结构-双链表详解

定义结点结构

/** * 定义结点类型结构体 */
typedef struct DNode {
   
	int data;  // 数据域
	struct DNode* prior;  // 指向前驱结点
	struct DNode* next;  // 指向后继结点
}DNode, * DLinkList;

尾插法建立双链表

/** * 尾插法建立双链表 * @param L 引用类型,双链表L * @param n 结点个数 */
void Create_DLinkList(DLinkList& L, int n) {
   
	L = (DLinkList)malloc(sizeof(DNode));
	if (L)
	{
   
		L->prior = NULL;
		L->next = NULL;
	}

	DNode* r, * s;
	r = L;
	for (int i = 0; i < n; ++i) {
   
		s = (DNode*)malloc(sizeof(DNode));
		if (s)
		{
   
			scanf_s("%d", &s->data);
			if (r)  // 与建立单链表类似,但要多加一个指向前驱的指针
			{
   
				r->next = s;
				s->prior = r;
				r = s;
			}
		}
	}
	if (r)
	{
   
		r->next = NULL;
	}
	
}

插入一个结点到双链表中

/** * 插入一个结点到双链表中 * @param L 引用类型,双链表L * @param location 插入结点的位置 * @param elem 插入的元素值 */
int InsertElem_DLinkList(DLinkList& L, int location, int elem) {
   
	DNode* p = L, * s;
	int i = 1;
	while (p->next != NULL && i < location) {
    // 让指针p走到插入位置
		p = p->next;
		++i;
	}
	s = (DNode*)malloc(sizeof(DNode));
	if (s)
	{
   
		s->data = elem;
		if (location >= i + 1) {
   
			return 0;
		}
		else if (p->next == NULL) {
     // 插入位置在结尾要单独处理
			s->next = p->next;
			s->prior = p;
			p->next = s;
			return 1;
		}
		else {
    // 注意插入顺序,1、2步必须在第3步前,要小心指针会丢失
			s->next = p->next;
			p->next->prior = s;
			p->next = s;
			s->prior = p;
			return 1;
		}
	}
	
}

插入操作的代码片段如下:(顺序不唯一,但1、2步必须在第3步前,要小心指针会丢失)

s->next = p->next;
p->next->prior = s;
p->next = s;
s->prior = p;

从双链表中删除一个结点

/** * 从双链表中删除一个结点 * @param L 引用类型,双链表L * @param location 删除结点的位置 * @param elem 返回删除结点的值 */
int DeleteElem_DLinkList(DLinkList& L, int location, int& elem) {
   
	DNode* p = L;
	int i = 0;
	while (p->next != NULL && i < location) {
   
		p = p->next;
		++i;
	}
	if (location >= i + 1) {
   
		return 0;
	}
	else if (p->next == NULL) {
     // 删除尾部元素单独处理
		p->prior->next = p->next;
	}
	else {
     // 要改前驱和后继两个指针
		p->prior->next = p->next;
		p->next->prior = p->prior;
	}
	elem = p->data;
	free(p);
	return 1;
}

按顺序打印双链表

/** * 按顺序打印双链表 * @param L 引用类型,双链表L */
void Print_DLinkList(DLinkList L) {
   
	DNode* p = L;
	while (p->next != NULL) {
   
		p = p->next;
		printf("%d ", p->data);
	}
	printf("\n");
}

按逆序打印双链表

/** * 按逆序打印双链表 * @param L 引用类型,双链表L */
void ReversePrint_DLinkList(DLinkList L) {
   
	DNode* p = L;
	while (p->next != NULL) {
   
		p = p->next;
	}
	while (p != L) {
   
		printf("%d ", p->data);
		p = p->prior;
	}
	printf("\n");
}

双链表的好处之一就是可以通过前驱指针来进行逆序操作

完整测试代码

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
/** * 定义结点类型结构体 */
typedef struct DNode {
   
	int data;  // 数据域
	struct DNode* prior;  // 指向前驱结点
	struct DNode* next;  // 指向后继结点
}DNode, * DLinkList;

/** * 尾插法建立双链表 * @param L 引用类型,双链表L * @param n 结点个数 */
void Create_DLinkList(DLinkList& L, int n) {
   
	L = (DLinkList)malloc(sizeof(DNode));
	if (L)
	{
   
		L->prior = NULL;
		L->next = NULL;
	}

	DNode* r, * s;
	r = L;
	for (int i = 0; i < n; ++i) {
   
		s = (DNode*)malloc(sizeof(DNode));
		if (s)
		{
   
			scanf_s("%d", &s->data);
			if (r)  // 与建立单链表类似,但要多加一个指向前驱的指针
			{
   
				r->next = s;
				s->prior = r;
				r = s;
			}
		}
	}
	if (r)
	{
   
		r->next = NULL;
	}
	
}

/** * 插入一个结点到双链表中 * @param L 引用类型,双链表L * @param location 插入结点的位置 * @param elem 插入的元素值 */
int InsertElem_DLinkList(DLinkList& L, int location, int elem) {
   
	DNode* p = L, * s;
	int i = 1;
	while (p->next != NULL && i < location) {
    // 让指针p走到插入位置
		p = p->next;
		++i;
	}
	s = (DNode*)malloc(sizeof(DNode));
	if (s)
	{
   
		s->data = elem;
		if (location >= i + 1) {
   
			return 0;
		}
		else if (p->next == NULL) {
     // 插入位置在结尾要单独处理
			s->next = p->next;
			s->prior = p;
			p->next = s;
			return 1;
		}
		else {
    // 注意插入顺序,1、2步必须在3、4步前面,指针会丢失
			s->next = p->next;
			p->next->prior = s;
			p->next = s;
			s->prior = p;
			return 1;
		}
	}
	
}

/** * 从双链表中删除一个结点 * @param L 引用类型,双链表L * @param location 删除结点的位置 * @param elem 返回删除结点的值 */
int DeleteElem_DLinkList(DLinkList& L, int location, int& elem) {
   
	DNode* p = L;
	int i = 0;
	while (p->next != NULL && i < location) {
   
		p = p->next;
		++i;
	}
	if (location >= i + 1) {
   
		return 0;
	}
	else if (p->next == NULL) {
     // 删除尾部元素单独处理
		p->prior->next = p->next;
	}
	else {
     // 要改前驱和后继两个指针
		p->prior->next = p->next;
		p->next->prior = p->prior;
	}
	elem = p->data;
	free(p);
	return 1;
}

/** * 按顺序打印双链表 * @param L 引用类型,双链表L */
void Print_DLinkList(DLinkList L) {
   
	DNode* p = L;
	while (p->next != NULL) {
   
		p = p->next;
		printf("%d ", p->data);
	}
	printf("\n");
}

/** * 按逆序打印双链表 * @param L 引用类型,双链表L */
void ReversePrint_DLinkList(DLinkList L) {
   
	DNode* p = L;
	while (p->next != NULL) {
   
		p = p->next;
	}
	while (p != L) {
   
		printf("%d ", p->data);
		p = p->prior;
	}
	printf("\n");
}

int main() {
   
	DLinkList L;
	int n;
	scanf_s("%d", &n);
	Create_DLinkList(L, n);
	Print_DLinkList(L);
	ReversePrint_DLinkList(L);

	int location, elem;
	scanf_s("%d %d", &location, &elem);
	if (InsertElem_DLinkList(L, location, elem)) {
   
		Print_DLinkList(L);
		ReversePrint_DLinkList(L);
	}
	else {
   
		printf("插入失败\n");
	}

	scanf_s("%d", &location);
	if (DeleteElem_DLinkList(L, location, elem)) {
   
		Print_DLinkList(L);
		ReversePrint_DLinkList(L);
		printf("删除的元素为%d\n", elem);
	}
	else {
   
		printf("删除失败:\n");
	}
	return 0;
}

创作不易,喜欢的话加个关注点个赞,谢谢谢谢谢谢!

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务