数据结构--双链表,循环链表,静态链表代码(王道书上代码手敲!!!)c++

目录

1.带头结点的双链表的初始化,判断链表是否为空,前插,后插,按位序插,删除后继节点,按位查找,按之查找,清空链表,销毁链表,遍历打印列表操作

2. 循环单链表初始化,判空,判断是否为尾节点

3.循环双链表初始化,判空,判断是否为尾节点,插入,删除后继元素,打印链表内容操作

4.静态链表的初始化,查找空节点,按位查找,按位插入,按位删除,遍历打印操作


注意!!!以下代码是在c++环境中写的c代码,用了c++代码的&

1.带头结点的双链表的初始化,判断链表是否为空,前插,后插,按位序插,删除后继节点,按位查找,按之查找,清空链表,销毁链表,遍历打印列表操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//带头结点的双链表
//定义结构体
typedef struct DNode {
	int data;
	struct  DNode* prior, * next;
}DNode,*DLinklist;

//添加函数原型的声明
bool InitDLinkList(DLinklist& L);
bool Empty(DLinklist L);
bool InsertNextDNode(DNode* p, DNode* s);
bool  InsertPriorDNode(DNode* p, DNode* s);
bool InsertDNode(DLinklist& L, int i, DNode* s);
void PrintDList(DNode* L);
bool DeleteNextDNode(DNode* p);
DNode* GetElem(DLinklist L, int i);
DNode* LocateElem(DLinklist L, int e);
void ClearDList(DLinklist& L);
void DestroyDList(DLinklist& L);

//初始化双链表
bool InitDLinkList(DLinklist &L) {
	L = (DNode*)malloc(sizeof(DNode));		//申请了一片空间做为头节点,并且头指针L指向这个节点
	if (L == NULL) {
		printf("内存分配失败");
		return false;
	}
	L->prior = NULL;							//头结点的前向指针永远指向NULL
	L->next = NULL;								//头结点的下一个节点暂时还没有节点
	return true;
}

//判断链表是否为空
bool Empty(DLinklist L) {
	if (L->next == NULL)
		return true;
	else
		return false;
}

//后插操作,在p节点后插入s节点
bool InsertNextDNode(DNode *p,DNode *s) {
	if (p == NULL || s == NULL)		//非法参数
		return false;
	s->next=p->next;
	if(p->next!=NULL)	//如果p不是最后一个节点
		p->next->prior = s;
	s->prior = p;
	p->next = s;
	return true;
}

//双链表的前插操作,在p节点前插入节点s
bool  InsertPriorDNode(DNode *p,DNode *s) {
	if (p == NULL || s == NULL)				//非法参数
		return false;
	DNode* q = p->prior;	//找到p的前一个结点,在他后面进行后插
	InsertNextDNode(q, s);
	return true;
}

//实现按位序插入,实现逻辑,找到当前位序的前一个节点,在其后进行后插
bool InsertDNode(DLinklist &L, int i, DNode* s) {
	DNode *p= GetElem(L, (i - 1));
	//进行后插
	InsertNextDNode(p, s);
	return true;
}

// 打印双链表
void PrintDList(DNode* L) {
	DNode* p = L->next;		// 跳过头节点
	while (p != NULL) {
		printf("%d\n", p->data);
		p = p->next;
	}
	printf("NULL\n");
}

//删除p节点后的后继节点
bool DeleteNextDNode(DNode* p) {
	if (p == NULL || p->next == NULL)
		return false;
	DNode* q = p->next;
	p->next = q->next;
	if (q->next != NULL)
		q->next->prior = p;
	free(q);
	return true;
}

//按位查询双链表,查询第i个位置的节点,并返回该节点
DNode* GetElem(DLinklist L,int i) {
	DNode* p = L;
	int j = 0;
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	if (p == NULL) // 如果p为空,说明i值过大
		return NULL;
	return p;
}

//按值查找
DNode* LocateElem(DLinklist L,int e) {
	DNode* p = L->next;			//聪第一个结点开始遍历,因为头结点的数据为NULL,无意义。
	while (p != NULL && p->data!=e) {
		p = p->next;
	}
	return p;
}

//清空双链表
void ClearDList(DLinklist &L) {
	while (L->next != NULL) {
		DeleteNextDNode(L);
	}
}

//销毁双链表
void DestroyDList(DLinklist &L) {
	ClearDList(L);
	free(L);		//释放头结点
	L = NULL;		//头指针指向NULL,使其链表结构彻底销毁
}

int main() {
	DLinklist L;
	InitDLinkList(L);
	
	//检查双链表是否为空
	printf("当前双链表是否为空:%s\n",Empty(L)?"是":"否");

	// 验证后插操作
	DNode* node1 = (DNode*)malloc(sizeof(DNode));
	node1->data = 1;
	InsertNextDNode(L, node1);
	printf("后插节点1后双链表的内容:\n");
	PrintDList(L);

	// 验证按位序插入操作
	DNode* node2 = (DNode*)malloc(sizeof(DNode));
	node2->data = 2;
	InsertDNode(L, 2, node2);
	printf("按位序插入节点2后双链表的内容:\n");
	PrintDList(L);

	// 验证前插操作
	DNode* node3 = (DNode*)malloc(sizeof(DNode));
	node3->data = 3;
	InsertPriorDNode(node2, node3);
	printf("前插节点3后双链表的内容:\n");
	PrintDList(L);

	// 验证按值查找操作
	int value = 2;
	DNode* result = LocateElem(L, value);
	if (result != NULL) {
		printf("找到值为%d的节点地址为:%d\n", value,result);
	}
	else {
		printf("未找到值为%d的节点\n", value);
	}

	// 清空双链表
	ClearDList(L);
	printf("清空双链表后:\n");
	PrintDList(L);

	// 销毁双链表
	DestroyDList(L);
	if (L == NULL) {
		printf("双链表已销毁\n");
	}
	else {
		printf("双链表销毁失败\n");
	}

	return 0;
}

结果:

2. 循环单链表初始化,判空,判断是否为尾节点

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//循环单链表
//定义单链表结构体
typedef struct LNode {
	int data;
	struct LNode* next;
}LNode,*LinkList;

//添加函数原型的声明
bool InitList(LinkList& L);
bool Empty(LinkList L);
bool IsTail(LinkList L, LNode* p);

//链表初始化
bool InitList(LinkList &L) {
	//关于链表初始化是否需要将data设置为空的说法,回答如下:
	//主要是确保链表存在并且指针正确设置。
	//即头结点已经被分配内存并且 next 指针指向自己(循环链表)或 NULL(普通链表)。不需要设置data域为空
	L = (LNode*)malloc(sizeof(LNode));
	if (L == NULL)
		return false;
	L->next = L;
	return true;
}

//链表判空操作,判断链表是否为空
bool Empty(LinkList L) {
	if (L->next == L)
		return true;
	else
		return false;
}

//判断节点p是否为尾节点
bool IsTail(LinkList L,LNode *p) {
	if (p->next == L)
		return true;
	else
		return false;
}

int  main() {
	LinkList L;	//定义一个单链表
	InitList(L);
	
	//判空操作验证
	printf("该循环链表是否为空:%s\n", Empty(L) ? "是" : "否");

	//是否为尾节点验证
	LNode *p= (LNode*)malloc(sizeof(LNode));
	L->next = p;
	p->next = L;
	printf("该节点是否为尾节点:%s\n", IsTail(L,p) ? "是" : "否");

	return 0;
}

结果:

3.循环双链表初始化,判空,判断是否为尾节点,插入,删除后继元素,打印链表内容操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>

//循环双链表
//定义单链表结构体
typedef struct LNode {
	int data;
	struct LNode *next,*prior;
}DNode, *DLinkList;

//函数原型的声明
bool InitDLinkList(DLinkList& L);
bool Empty(DLinkList L);
bool IsTail(DLinkList L, DNode* p);
bool InsertNextDNode(DNode* p, DNode* s);
bool DeleteDNode(LNode* p);
void PrintList(DLinkList L);

//初始化双链表
bool InitDLinkList(DLinkList &L) {
	L = (DNode*)malloc(sizeof(DNode));
	if (L == NULL)
		return false;
	L->next = L;
	L->prior = L;
	return true;
}

//判空操作
bool Empty(DLinkList L) {
	if (L->next == L)
		return true;
	else
		return false;
}

//判断节点p是否为尾节点
bool IsTail(DLinkList L, DNode *p) {
	if (p->next == L)
		return true;
	else
		return false;
}

//插入节点,在p节点后插入s节点
bool InsertNextDNode(DNode* p, DNode* s) {
	if (p == NULL || s == NULL) {
		return false;  // 如果 p 或 s 为空,则插入失败
	}
	p->next->prior = s;
	s->next=p->next;
	p->next = s;
	s->prior = p;
	return true;
}

//删除p节点的后继节点q
bool DeleteDNode(LNode *p) {
	if (p == NULL || p->next == NULL)
		return false;
	DNode* q = p->next;
	p->next = q->next;
	q->next->prior = p;
	free(q);
	return true;
}

// 打印链表内容
void PrintList(DLinkList L) {
	DNode* p = L->next;
	while (p != L) {
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

int  main() {
	DLinkList L;
	InitDLinkList(L);

	// 判空操作验证
	printf("该循环双链表是否为空:%s\n", Empty(L) ? "是" : "否");

	// 插入节点测试
	DNode* node1 = (DNode*)malloc(sizeof(DNode));
	node1->data = 1;
	InsertNextDNode(L, node1);

	DNode* node2 = (DNode*)malloc(sizeof(DNode));
	node2->data = 2;
	InsertNextDNode(node1, node2);

	DNode* node3 = (DNode*)malloc(sizeof(DNode));
	node3->data = 3;
	InsertNextDNode(node2, node3);

	// 打印链表内容验证插入操作
	printf("链表内容: ");
	PrintList(L);

	// 是否为尾节点验证
	printf("node3 是否为尾节点:%s\n", IsTail(L, node3) ? "是" : "否");

	// 删除节点测试
	DeleteDNode(node1); // 删除 node1 的后继节点 node2

	// 打印链表内容验证删除操作
	printf("删除 node2 后链表内容: ");
	PrintList(L);

	// 释放内存
	free(node1);
	free(node3);
	free(L);

	return 0;
}

结果:

4.静态链表的初始化,查找空节点,按位查找,按位插入,按位删除,遍历打印操作

代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
#define MaxSize 10

// 静态链表定义
typedef struct {
    int data;       // 存储数据元素
    int next;       // 下一个元素的数组下标
} SLinkList[MaxSize];

//函数原型声明
bool InitSList(SLinkList& s);
int FindFreeNode(SLinkList s);
int FindLocate(SLinkList s, int i);
bool Insert(SLinkList& s, int i, int e);
int DeleteSNode(SLinkList& s, int i);
void PrintList(SLinkList s);

// 初始化链表
bool InitSList(SLinkList& s) {
    if (s == NULL)
        return false;
    s[0].next = -1;  // 头节点,next指向-1表示空链表
    for (int i = 1; i < MaxSize; i++) {
        s[i].next = -2;  // -2表示空闲节点
    }
    return true;
}

// 找到第一个空闲的元素,并返回它的下标
int FindFreeNode(SLinkList s) {
    for (int i = 0; i < MaxSize; i++) {
        if (s[i].next == -2) {
            return i;
        }
    }
    return -1;  // 没有空闲节点
}

// 找到位序为i的元素,并返回它的下标
int FindLocate(SLinkList s, int i) {
    int pos = 0;  // 指向头节点
    for (int j = 0; j < i && pos != -1; j++) {
        pos = s[pos].next;
    }
    return pos;
}

// 按位插入,在位序为i的位置插入值为e的节点
bool Insert(SLinkList& s, int i, int e) {
    if (i < 1 || i > MaxSize - 1) return false;  // 插入位置无效

    int prev = FindLocate(s, i - 1);  // 找到位序i-1的位置
    if (prev == -1) return false;  // 插入位置无效

    int freeNode = FindFreeNode(s);  // 找到一个空闲节点
    if (freeNode == -1) return false;  // 没有空闲节点

    s[freeNode].data = e;
    s[freeNode].next = s[prev].next;
    s[prev].next = freeNode;

    return true;
}

// 删除位序为i的节点,并返回删除节点的值
int DeleteSNode(SLinkList& s, int i) {
    if (i < 1 || i >= MaxSize) return -1;  // 删除位置无效

    int prev = FindLocate(s, i - 1);  // 找到位序i-1的位置
    if (prev == -1 || s[prev].next == -1) return -1;  // 删除位置无效

    int delNode = s[prev].next;  // 要删除的节点
    int e = s[delNode].data;  // 获取删除节点的数据
    s[prev].next = s[delNode].next;  // 跳过要删除的节点
    s[delNode].next = -2;  // 将删除的节点标记为空闲节点

    return e;
}

// 打印链表中的元素
void PrintList(SLinkList s) {
    int pos = s[0].next;  // 从头节点的下一个节点开始
    while (pos != -1) {
        printf("%d -> ", s[pos].data);
        pos = s[pos].next;
    }
    printf("NULL\n");
}

int main() {
    SLinkList s;
    if (InitSList(s)) {
        Insert(s, 1, 10);
        Insert(s, 2, 20);
        Insert(s, 1, 5);
        printf("初始链表: ");
        PrintList(s);

        int deletedValue = DeleteSNode(s, 2);
        printf("删除位序为2的节点后: ");
        PrintList(s);
        printf("删除的值: %d\n", deletedValue);
    }
    else {
        printf("链表初始化失败\n");
    }

    return 0;
}

 结果:

 结束~


有收获的宝宝留个赞赞再走吧~ 

不胜感激~

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值