c语言——数据结构——链式表

链式表是一种常见的数据结构,它通过节点和指针的方式实现元素的存储和连接。

链式表由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。通过节点之间的指针链接,形成一个链式结构,从而实现元素的顺序存储和访问。

相比于顺序表(使用数组实现的线性表),链式表的插入和删除操作更加高效,因为它只需要修改相邻节点的指针,不需要进行元素的移动。但是查找元素的操作相对较慢,需要从头节点开始遍历链表,直到找到目标元素或者到达链表末尾。

链式表常见的类型有单链表、双向链表和循环链表。

  • 单链表:每个节点只包含一个指针,指向下一个节点。链表的头指针指向链表的第一个节点,尾节点的指针为NULL,表示链表的结束。

  • 双向链表:每个节点除了包含指向下一个节点的指针,还包含指向前一个节点的指针。双向链表可以实现前向和后向的遍历。

  • 循环链表:尾节点的指针指向头节点,形成一个环状结构。循环链表可以实现循环遍历。

链式表的常见操作包括:

  • 插入:在指定位置插入一个新节点。
  • 删除:删除指定位置的节点。
  • 查找:根据元素的值或者位置,查找对应的节点。
  • 修改:修改指定位置的节点的值。
  • 遍历:依次访问链表中的每个节点。

链式表的应用广泛,能够灵活地处理动态数据结构的问题。它在各种算法和程序设计中都有重要的应用,例如实现栈、队列、图等数据结构和算法。

 

  1. 定义了头结点类型以及双向链表节点的结构体 DuLNode,并使用 typedef 进行类型别名定义。DuLNode 结构体包含数据域 data,以及指向前驱节点和后继节点的指针域 prior 和 next

  2. LinkListInit 函数用于初始化双向链表,创建一个空的双向链表,通过 L 参数返回链表头结点的指针。

  3. GetElem_L 函数在带头结点的双向链表 L 中查找第 i 个结点,并返回该结点的指针。这个函数通过遍历链表,依次移动到指定位置来实现查找。

  4. ListInsert_L 函数在双向链表 L 的第 i 个位置之前插入新的元素 x。首先使用 GetElem_L 函数找到位置为 i-1 的节点,然后创建新的节点 s,将 s 插入到 i 位置并调整前驱和后继节点的指针指向。

  5. ListDelete_L 函数用于删除双向链表 L 中的第 i 个节点。通过 GetElem_L 找到位置为 i-1 的节点 p,然后将 p 指向的节点 q 的前驱节点的 next 指针指向 q 的后继节点,将 q 的后继节点的 prior 指针指向 p 的前驱节点,最后释放节点 q 的空间。

  6. CreateList_L 函数用于逆序输入 n 个数据元素,创建带头结点的双向链表。首先调用 LinkListInit 初始化链表,然后使用循环逐个创建节点并插入到链表头部。

  7. DispList_L 函数用于输出双向链表的所有元素值。通过遍历链表,依次输出每个节点的数据域。

  8. 在 main 函数中,创建双向链表 L 并调用 CreateList_L 进行初始化。然后分别调用 DispList_L 输出链表元素。接着使用 ListInsert_L 在链表第 6 个位置插入元素 10,并调用 DispList_L 输出链表。最后使用 ListDelete_L 删除链表第 6 个位置的节点,并再次调用 DispList_L 输出链表。

总体来说,这段代码实现了双向链表的基本操作,包括初始化、插入、删除、遍历等。可以通过调用这些函数来对双向链表进行操作。需要注意的是,代码中存在一些潜在的问题,比如没有进行错误处理和内存释放。在实际应用中需要主动处理这些问题。

 

这段代码是一个实现双向链表的程序。下面是代码的分析:

  1. 定义了双向链表节点的数据结构:
typedef struct DuLNode {
    ElemType  data; // 数据域
    struct DuLNode  *prior; //指向前驱的指针域
    struct DuLNode  *next; //指向后继的指针域
} DuLNode, *DuLinkList;

  1. 初始化双向链表:
void LinkListInit(DuLinkList &L) {
    L = new DuLNode; // 创建头结点
    if (!L) exit(OVERFLOW);
    L->next = L->prior = NULL; // 初始化指针域
}

  1. 在双向链表中查找第i个节点:
DuLNode *GetElem_L(DuLinkList L, int i) {
    DuLNode *p;
    p = L->next;
    int j = 1; // 计数器
    while (p != L && j < i) { // 顺指针向后查找,直到p指向第i个元素或p为空
        p = p->next;
        ++j;
    }
    if (j == i) return p; // 第i个元素存在
    else  return NULL; // 第i个元素不存在
}

  1. 在双向链表的第i个位置之前插入元素x:
int ListInsert_L(DuLinkList &L, int i, ElemType x) {
    DuLNode *p, *s;
    p = GetElem_L(L, i - 1);
    if (!p) return ERROR;
    s = new DuLNode; // 生成新结点
    s->data = x;
    if (p->next) {
        p->next->prior = s;
        s->next = p->next;
        s->next->prior = p;
        p->next = s;
    } else { //插入在L尾部的处理
        s->next = p->next;
        p->next = s;
        s->prior = p;
    }
    return OK;
}

  1. 删除双向链表中的第i个节点:
int ListDelete_L(DuLinkList &L, int i) {
    DuLNode *p, *q;
    p = GetElem_L(L, i - 1);
    if (!p) return ERROR; //删除位置不合理
    if (p->next->next) {
        q = p->next;
        q->next->prior = p;
        p->next = q->next;  //删除并释放结点
    } else { //删除尾部结点
        q = p->next;
        p->next = NULL;
        q->prior = NULL;
    }
    delete q;
    return OK;
}

  1. 创建双向链表:
void CreateList_L(DuLinkList &L, int n) {
    DuLNode *p;
    LinkListInit(L); //建立空表
    for (int i = n; i > 0; --i) {
        p = new DuLNode; //新增结点
        scanf("%d", &p->data);  //输入元素值
        p->next = L->next;
        p->prior = L;
        L->next = p;
    }
}

  1. 输出双向链表中的元素:
void DispList_L(DuLinkList L) {
    DuLNode *p;
    for (p = L->next; p; p = p->next) printf("%d ", p->data);
    printf("\n");
}

  1. 主函数:
int main() {
    DuLinkList L;
    DuLNode *p;
    CreateList_L(L, 5);
    DispList_L(L);
    ListInsert_L(L, 6, 10);
    DispList_L(L);
    ListDelete_L(L, 6);
    DispList_L(L);
    return 0;
}

主函数中演示了创建一个双向链表,插入元素和删除元素。在输出结果时,双向链表的元素将会逐个打印到控制台。

完整代码

双向链表

# include <stdlib.h>
# include <stdio.h>
# define  OK 1
# define  OVERFLOW -1
# define  ERROR 0
typedef int ElemType;/
typedef struct DuLNode {
	ElemType  data; // 数据域
	struct DuLNode  *prior; //指向前驱的指针域
	struct DuLNode  *next; //指向后继的指针域
}DuLNode,*DuLinkList;
void LinkListInit(DuLinkList &L){
	L=new DuLNode;
	if(!L)exit(OVERFLOW);
	L->next=L->prior=NULL;
}
DuLNode *GetElem_L(DuLinkList L,int i){//在带头结点的双向链表L中查找第i个结点,找到返回该结点,否则返回空
	DuLNode *p;
	p=L->next;
	int j=1;  //p指向第一个结点,j为计数器
	while(p!=L&&j<i){p=p->next; ++j;}  //顺指针向后查找,直到p指向第i个元素或p为空
	if(j==i)return p;  //第i个元素存在
	else  return NULL; //第i个元素不存在
}

int ListInsert_L(DuLinkList &L,int i,ElemType x){//在双向链表L中第i个位置之前插入元素x
	DuLNode *p,*s;
	p=GetElem_L(L,i-1);
	if(!p)return ERROR;
	s=new DuLNode; //生成新结点
	s->data=x; 
	if(p->next){
		p->next->prior=s;
		s->next=p->next;
		s->next->prior=p;   
		p->next=s; 		
	}
	else{//插入在L尾部的处理
		s->next=p->next;
		p->next=s;
		s->prior=p;
	}
	return OK;
}
int ListDelete_L(DuLinkList &L,int i){
	DuLNode *p,*q;
	p=GetElem_L(L,i-1);
	if(!p)return ERROR;  //删除位置不合理
	if(p->next->next){
		q=p->next;
		q->next->prior=p;
		p->next=q->next;  //删除并释放结点
		
	}
	else{//删除尾部结点
		q=p->next;
		p->next=NULL;
		q->prior=NULL;
		
	}
	delete q;
	return OK;
}
void CreateList_L(DuLinkList &L,int n) {//逆序输入n个数据元素,建立带头结点的双向链表
	DuLNode *p;	
	LinkListInit(L); //建立空表
	for(int i=n; i>0; --i){
		p=new DuLNode;//新增结点
		scanf("%d",&p->data);  //输入元素值
		p->next=L->next;
		p->prior=L;
		L->next=p;
	}
}
void DispList_L(DuLinkList L) {
	DuLNode *p;	
	for(p=L->next;p;p=p->next)printf("%d ",p->data);
	printf("\n");
}
//void CreateList_L(DuLinkList &L,int n){
//	DuLNode *p,*r;
//	LinkListInit(L); //建立空表
//	r=L;  //r始终指向表尾结点
//	for(int i=1; i<=n; i++){
//		p=new DuLNode;
//		scanf("%d",&p->data);  //输入元素值
//		r->next=p;  //插入到表尾
//		r=p;
//	}
//	r->next=NULL;
//}

int main(){
	DuLinkList L;	
	DuLNode *p;
	CreateList_L(L,5);
	DispList_L(L);
//	p=GetElem_L(L,3);
//	if(p!=NULL)printf("%d\n",p->data);
	ListInsert_L(L,6,10);
	DispList_L(L);
	ListDelete_L(L,6);
	DispList_L(L);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张謹礧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值