数据结构个人笔记 第7课 双向链表

本文详细介绍了双向链表的概念,包括其结构和基本操作。在双向链表中,每个节点包含指向前一个节点和后一个节点的指针。文章提供了创建双向链表的示例代码,包括初始化、显示链表、添加元素、删除节点、查找元素和修改元素等操作。此外,还特别强调了在添加和删除操作中更新节点指针的重要性。
摘要由CSDN通过智能技术生成

双向链表

双向链表的结构
双向链表也即有两个指针的链表,分别指向前一个结点和后一个结点
当然此处的双向是指各节点之间的逻辑关系是双向的,但通常头指针只设置一个,除非实际情况需要。

双向链表中各节点包含以下3部分信息:

  1. 指针域:用于指向当前节点的直接前驱结点
  2. 数据域:用于存储数据元素
  3. 指针域:用于指向当前节点的直接后继节点

双向链表节点构成

双向链表的创建

#include<stdio.h>
#include<stdlib.h>

typedef struct line{
	struct line * prior;
	int data;
	struct line * next;
};

line* initLine(line * head){
	head = (line*)malloc(sizeof(line));
	head -> prior = NULL;
	head -> next = NULL;
	head -> data = 1;
	line * list = head;
	for(int i = 2;i <= 5;i++){
		line * body = (line*)malloc(sizeof(line));
		body ->prior = NULL;
		body ->next = NULL;
		body ->data = i;
		
		list ->next = body;
		body ->prior = list;
		list = list ->next;
	}
	return head;
}

void display(line * head){
	line * temp = head;
	while(temp){
		if(temp -> next == NULL){
			printf("%d\n",temp -> data);
		}
		else{
			printf("%d <->",temp -> data);
		}
		temp = temp -> next;
	}
}

int main(){
	line * head = NULL;
	head = initLine(head);
	display(head);
	printf("链表中的第四个节点的直接前趋是:%d",head -> next -> next -> next-> prior -> data);
	return 0;
}

双向链表的基本操作

双向链表中添加元素

分为三种情况:添加在表头、添加在表中、添加在表最后
不同与之前学的几种表,这里双向链表三种情况必须分开讨论

  1. 当添加元素在表头时,原来的第一个元素的前驱指向添加元素,添加元素的前驱指向NULL,后驱指向原来的第一个元素,并且头指针要从指向原来的第一个元素改成指向添加的元素添加元素到表头
  2. 当添加元素在表的中间位置时,同单链表添加数据,需要新节点先与其直接后继节点建立双层逻辑关系,然后新节点的直接前驱节点与之建立双层逻辑关系
    添加到表中时
  3. 当添加元素到表尾,需先找到双链表中最后一个节点,让新节点与最后一个节点进行双层逻辑关系
    添加到表尾时
line* addLine(line * head,int data,int add){
	line * temp = head;//新建数据域为num的节点 
	temp -> data = data;
	temp -> prior = NULL;
	temp -> next = NULL; 
	//插入到链表头的情况 
	if(add == 1){
		temp -> next = head;
		head -> prior = temp;
		head = temp;
	}else{//插入到表中的情况 
		line * body = head;
		//找到要插入位置的前一个结点
		for(int i = 1;i < add-1;i++){
			body = body -> next;
		} 
		if(body->next == NULL){//是最后一个节点 
			body -> next = temp;
			temp -> prior = body;
		}else{//并不是最后一个节点 
			body -> next ->prior = temp;
			temp -> next = body -> next;
			body -> next = temp;
			temp -> prior = body;
		}
	}
	return head;
}

需要注意的是,这里已经改变了head所指向的空间,所以在主函数中调用时,需要用head=addLine()接收一下,否则如果添加元素在表头时,会读取不到添加的元素

双向链表删除节点

删除节点时,先遍历链表,找到要删除的节点,然后将该节点从表中摘除即可
删除节点

line * delLine(line * head,int del){
	line * temp = head;
	if(del == 1){
		head = head -> next;
		head -> prior = NULL;
		free(temp);
	}
	else{
		for(int i = 1;i <del; i++){
			temp = temp -> next;
			if(temp -> next == NULL){
				printf("已经循环到最后一个数了,后面已经没有数据了\n");
				temp -> prior -> next = NULL;
				free(temp);
				return head;
			}
		}
			temp -> prior -> next = temp -> next;
			temp -> next -> prior = temp -> prior;
			free(temp);
	}
	return head;
} 

双向表查找元素

通过遍历链表,找到想要找到的元素的位置

int searchLine(line * head , int data){
	line * temp = head;
	int num=1;
	while(data == temp -> data){
		temp = temp -> next;
		num ++; 
	}
	return num;
}

双向表修改元素

通过遍历链表,找到想要修改的元素,再替换他的值

line * changeLine(line * head , int data , int num){
	line * temp = head;
	for(int i = 1; i<num;i++){
		temp = temp -> next;
	}
	temp -> data = data;
	return head;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值