数据结构(C实现)------- 双向链表

双向链表中的每一个结点都含有两个指针域,一个指针域存放其后继结点的存储地址,另一个指针域则存放其前驱结点的存储地址。

双向链表结点的类型描述:

//双向链表的类型描述
typedef int ElemType;
typedef struct node{
	ElemType data;
	struct node *prior,*next;
}DuLNode,*DuLinkList;

其中,prior域存放的是其前驱结点的存储地址,next域存放的是其后继结点的存储地址。

双向链表有两个特点:一是可以从两个方向搜索某个结点,这使得链表的某些操作(如插入和删除)变得比较简单; 二是无论利用前链还是后链都可以遍历整个双向链表。

双向链表的操作基本和单链表的操作相同;

1. 头插法创建带头结点的双向链表Create_DLinkListF(int n)

//头插法创建带头结点的双向链表
DuLinkList Create_DLinkListF(int n){
	DuLinkList L,p;
	int i = n - 1;
	ElemType x;
	//新建头结点
	L = (DuLinkList)malloc(sizeof(DuLNode));
	L->prior = NULL;
	L->next = NULL;

	//添加第一个结点
	scanf("%d",&x);
	p = (DuLinkList)malloc(sizeof(DuLNode));
	p->data = x;
	L->next = p;
	p->prior = L;
	p->next = NULL;

	//加入其他结点
	while(i > 0){
		scanf("%d",&x);
		p = (DuLinkList)malloc(sizeof(DuLNode));
		p->data = x;

		p->next = L->next;
		L->next->prior = p;
		p->prior = L;
		L->next = p;

		i--;
	}
	return L;
}

2. 尾插法创建带头结点的双向链表Create_DLinkListR(int n)

//尾插法创建带头结点的双向链表
DuLinkList Create_DLinkListR(int n){
	DuLinkList L,p,lastNode;
	int i = n - 1;
	ElemType x;
	//新建头结点
	L = (DuLinkList)malloc(sizeof(DuLNode));
	L->prior = NULL;
	L->next = NULL;

	//添加第一个结点
	scanf("%d",&x);
	p = (DuLinkList)malloc(sizeof(DuLNode));
	p->data = x;
	L->next = p;
	p->prior = L;
	p->next = NULL;

	lastNode = p;
	//加入其他结点
	while(i > 0){
		scanf("%d",&x);
		p = (DuLinkList)malloc(sizeof(DuLNode));
		p->data = x;

		lastNode->next = p;
		p->prior = lastNode;
		p->next = NULL;

		lastNode = p;
		i--;

	}
	return L;

}

3. 在指定结点之前插入新结点Insert_DLinkListBefore(DuLinkList p,ElemType x)

//在指定结点之前插入新结点
void Insert_DLinkListBefore(DuLinkList p,ElemType x){
	DuLinkList newNode;
	//判断结点p之前的结点的合法性:
	if(p->prior == NULL)
		printf("结点不合法,不能在该结点之前插入结点\n");
	else{
		newNode = (DuLinkList)malloc(sizeof(DuLNode));
		newNode->data = x;

		newNode->next = p;
		p->prior->next = newNode;
		newNode->prior = p->prior;
		p->prior = newNode;
	}
}

4. 在指定结点之后插入新结点Insert_DLinkListAfter(DuLinkList p,ElemType x)

//在指定结点之后插入新结点
void Insert_DLinkListAfter(DuLinkList p,ElemType x){

	DuLinkList newNode;
	newNode = (DuLinkList)malloc(sizeof(DuLNode));
	newNode->data = x;

	//当插入位置是最后一个结点之后时
	if(p->next == NULL){
		p->next = newNode;
		newNode->prior = p;
		newNode->next = NULL;
	}
	else{
		newNode->next = p->next;
		p->next->prior = newNode;
		p->next = newNode;
		newNode->prior = p;
	}
}

5. 删除指定结点Delete_DLinkList(DuLinkList p)

//删除指定结点
void Delete_DLinkList(DuLinkList p){
	//如果删除的是最后一个元素
	if(p->next == NULL)
		p->prior->next = NULL;

	else{
		p->prior->next = p->next;
		p->next->prior = p->prior;

	}
	free(p);
}

6. 后链输出双向链表Print_DLinkListN(DuLinkList L)

//后链输出双向链表
void Print_DLinkListN(DuLinkList p){

	while(p != NULL){
		printf("%d\t",p->data);
		p = p->next;
	}
	printf("\n");

}

7.前链输出双向链表Print_DLinkListP(DuLinkList p)

//前链输出双向链表
void Print_DLinkListP(DuLinkList p){

	while(p != NULL){
		printf("%d\t",p->data);
		p = p-prior;
	}
	printf("\n");
}

至于双向链表的其他操作,如定位,和单链表的操作类同,不再赘述。

时间: 2024-12-15 06:52:53

数据结构(C实现)------- 双向链表的相关文章

Linux 内核数据结构:Linux 双向链表

Linux 内核提供一套双向链表的实现,你可以在 include/linux/list.h 中找到.我们以双向链表着手开始介绍 Linux 内核中的数据结构 ,因为这个是在 Linux 内核中使用最为广泛的数据结构,具体你可以 查看 这里. 首先让我们看一下主要的结构体: struct list_head { struct list_head *next, *prev; }; 你可以看到其与常见的结构体实现有显著不同,比如 glib 中所使用到的双向链表实现. struct GList { gp

数据结构 链表_双向链表的实现与分析

双向链表的实现与分析 双向链表的组成 :1.数据成员:2.指向下一个元素的next指针:3.指向前一个元素的prev指针. 数据结构DListElmt:代表双向链表中的单个元素(节点). 数据结构DList:代表双向链表数据结构,该结构的成员同前面介绍的单链表相似. 示例1:双向链表抽象数据类型的头文件 /*dlist.h*/ #ifndef DLIST_H #define DLIST_H /*定义双向链表中的元素*/ typedef struct DListLemt_ { void *data

不会C和cpp也能学数据结构——JavaScript实现双向链表

本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文链接 http://www.cnblogs.com/tdws/ 下午分享了JavaScript实现单向链表,晚上就来补充下双向链表吧.对链表的实现不是很了解的可以移步:http://www.cnblogs.com/tdws/p/6033209.html 双向链表与链表的不同之处主要在于他的双向查找.因为在这种结构中我们设计了每个节点的prev(向上查找)的引用或指针和next(向下查找)的引用或指针.得益于这种结构你能做到正向和反向的查

数据结构笔记4双向链表

#include<stdio.h>#include<malloc.h>#include<conio.h>#define OK 1#define ERROR -1#define OVERFLOW -2#define ENDFlAG 0//双向链表节点 struct DNode{ int data; struct DNode *prior,*next;}DNode,*DLinkList;//初始化以及建立,采用尾插法,返回1 int InitLinkList_Asighme

14. C#数据结构与算法 -- 双向链表

首先,明白什么是双向链表.所谓双向链表是如果希望找直接前驱结点和直接后继结点的时间复杂度都是 O(1),那么,需要在结点中设两个引用域,一个保存直接前驱结点的地址,叫 prev,一个直接后继结点的地址,叫 next,这样的链表就是双向链表(Doubly Linked List).双向链表的结点结构示意图如图所示. 双向链表结点的定义与单链表的结点的定义很相似, ,只是双向链表多了一个字段 prev.其实,双向链表更像是一根链条一样,你连我,我连你,不清楚,请看图. 双向链表结点类的实现如下所示

数据结构 链表_双向链表的接口定义

双向链表介绍 双向链表中的每一个元素都由3部分组成:除了数据成员.next指针外,每个元素还包含一个指向其前驱元素的指针,称为prev指针.双向链表的组成是这样的:将一些元素链接在一起,使得每个元素的next指针都指向其后继的元素,而每个元素的prev指针都指向其前驱元素. 为了标识链表的头和尾,将第一个元素的prev指针和最后一个元素的next指针设置为NULL. 要反向遍历整个双向链表,使用prev指针以从尾到头的顺序连续访问各个元素.当我们知道某个元素存储在链表在的某处时,我们可以选择按何

【数据结构】循环链表&amp;&amp;双向链表详解和代码实例

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 循环链表 1.1 什么是循环链表? 前面介绍了单链表,相信大家还记得相关的概念.其实循环链表跟单链表也没有差别很多,只是在某些细节上的处理方式会稍稍不同. 在此之前,大家可以先思考一个问题:单链表中,要找到其中某个节点只需要从头节点开始遍历链表即可,但是有些时候我们的想法是,能不能从任意节点开始遍历,也能找到我们需要的那个节点呢? 其实啊,这个实现也很简单自然,把整个链表串成一个环问题就迎刃而解了.所以,关于循环链表,

数据结构--循环链表与双向链表

一.循环链表 A.循环链表的介绍a.概念上1.任意数据元素都有一个前驱和一个后继2.所有数据元素的关系构成一个逻辑上的环b.实现上1.循环链表是一种特殊的单链表2.尾节点的指针域保存了首结点的地址关系图如下.循环链表的继承层次结构 二.循环链表的实现思路 A.思路1.通过模板定义CircleList类,继承自LinkList类2.定义内部函数last_to_first();用于将单链表首尾相连 Node* last()const//尾节点 { return this->position(this

数据结构--stack 基于双向链表实现(超简单版)

1 package cn.it.struct; 2 3 public class MyStack<T> { 4 private int top=-1; 5 6 private Node<T> current; 7 8 9 private class Node<T>{ 10 private T data; 11 12 private Node<T> next; 13 14 private Node<T> pre; 15 16 } 17 18 //初

双向链表(c语言版)

为了得到一个简洁的C语言实现的双向链表,本篇参照数据结构书籍对双向链表的做了一些修改,内容有: 1.合并分离的头文件和实现文件,认识更为直观: 2.修改函数名和变量名,更贴近自身的理解: 3.删除了返回首节点.尾节点等功能更为单一的函数,留下其主干. 实现思路: 1.定义一个双向链表 2.进行初始化工作:调用initList(),构造一个空的双向链表 3.执行增删改查等操作(节点操作) *插入时注意:封装成节点 1 /*双向链表实现代码*/ 2 #include<malloc.h> 3 #in