数组、链表和树(内核数组和链表实现原理及代码)

本文深入探讨了数据结构中的栈、队列和树的实现,包括数组和链表两种基本存储方式。详细介绍了栈的先进后出原则,链表实现的栈、队列以及树的结构。通过C语言代码展示了数组和链表在实现栈的入栈、出栈、遍历,队列的入队、出队以及树的遍历等操作。同时,文章还讨论了循环链表在队列实现中的应用,以及链表在存储树结构时的优势。此外,补充了数组和链表实现的一般操作,如动态数组的增删查改以及链表的插入、删除等操作。


系统学习完数组和链表后,才了解道其重要性,对于栈和链表以及树等结构,其内核分为数组实现和链表实现两种方式,为防止遗忘,特意整理如下,部分C代码暂时未补全,随后会更新全部,希望大家有问题可以及时评论,共同进步!!!

线性存储

数组实现原理

在这里插入图片描述
栈:先进后出

数组由前向后存储数据,从后向前读取数据,实现栈的要求

链表实现原理

在这里插入图片描述

通过两个指针确定链表的储存内容,Bottom指向栈底,Top指向栈顶,无论是入栈还是出栈,只有Top指针在改变,Bottom指针始终不变。

C语言代码实现

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

typedef struct Node
{
	int data;
	struct Node* pNext;
}NODE, * PNODE;

typedef struct Stack
{
	PNODE pTop;
	PNODE pBottom;
}STACK, * PSTACK;

void init(PSTACK);
void push(PSTACK, int);
void traverse(PSTACK);
bool pop(PSTACK, int*);
void clear(PSTACK pS);

int main(void)
{
	STACK S;
	int val=5;

	init(&S);
	push(&S, 1);
	push(&S, 2);
	push(&S, 3);
	push(&S, 4);
	push(&S, 5);
	traverse(&S);

	pop(&S, &val);
	/*printf("出栈的元素是:%d\n", val);*/
	clear(&S);
	traverse(&S);

	return 0;
}

void init(PSTACK pS)
{
	pS->pTop = (PNODE)malloc(sizeof(NODE));
	if (NULL == pS->pTop)
	{
		printf("动态内存分配失败!\n");
		exit(-1);
	}
	else
	{
		pS->pBottom = pS->pTop;
		pS->pBottom->pNext = NULL;
	}
}

void push(PSTACK pS, int val)
{
	PNODE pNew = (PSTACK)malloc(sizeof(NODE));
	pNew->data = val;
	pNew->pNext = pS->pTop;
	pS->pTop = pNew;

	return;
}

void traverse(PSTACK pS)
{
	PNODE p = pS->pTop;
	
	while (p != pS->pBottom)
	{
		printf("%d  ", p->data);
		p = p->pNext;
	}
	printf("\n");

	return;
}

bool is_empty(PSTACK pS)
{
	if (pS->pBottom == pS->pTop)
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool pop(PSTACK pS, int* pVal)
{
	if (is_empty(pS))
	{
		return false;
	}
	else
	{
		PNODE r = pS->pTop;
		pVal = pS->pTop->data;
		pS->pTop = r->pNext;
		free(r);
		r = NULL;

		return true;
	}
}

void clear(PSTACK pS)
{
	if (is_empty(pS))
	{
		return;
	}
	else
	{
		while(pS->pTop != pS->pBottom)
		{
			PNODE r = pS->pTop;
			pS->pTop = pS->pTop->pNext;
			free(r);
			r = NULL;
		}
	}
}

队列

数组实现原理

在这里插入图片描述

从数组的后方入队,从前方出队。
问题:出队后前部空间释放后,无法入队,整体操作在向后方移动,造成前方资源浪费,后方资源不足
解决方法:通过采用循环链式结构,保证数组合理利用。

C语言代码实现

//循环链表,数组实现
#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>

typedef struct Queue
{
	int* pBase;
	int front;
	int rear;
}QUEUE;

void init(QUEUE*);
bool en_queue(QUEUE*, int val);
void traverse_queue(QUEUE*);
bool out_queue(QUEUE*, int*);

int main()
{
	QUEUE Q;
	int val;

	init(&Q);
	en_queue(&Q, 1);
	en_queue(&Q, 2);
	en_queue(&Q, 3);
	en_queue(&Q, 4);
	en_queue(&Q, 5);
	en_queue(&Q, 6);
	en_queue(&Q, 7);
	traverse_queue(&Q);

	out_queue(&Q, &val);
	printf("出队的元素为:%d\n", val);
	traverse_queue(&Q);
		
	return 0;
}

void init(QUEUE* pQ)
{
	pQ->pBase = (int*)malloc(sizeof(int) * 6);
	pQ->front = 0;
	pQ->rear = 0;
}

bool full_queue(QUEUE* pQ)
{
	if (pQ->front == (pQ->rear + 1) % 6)
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool en_queue(QUEUE* pQ, int val)
{
	if (full_queue(pQ))
	{
		return false;
	}
	else
	{
		pQ->pBase[pQ->rear] = val;
		pQ->rear = (pQ->rear + 1) % 6;

		return true;
	}
}

void traverse_queue(QUEUE* pQ)
{
	int i = pQ->front;
	while (i != pQ->rear)
	{
		printf("%d  ", pQ->pBase[i]);
		i = (i + 1) % 6;
	}
	printf("\n");
}

bool emput_queue(QUEUE* pQ)
{
	if (pQ->front == pQ->rear)
	{
		return true;
	}
	else
	{
		return false;
	}
}


bool out_queue(QUEUE* pQ, int* pVal)
{
	if (emput_queue(pQ))
	{
		return false;
	}
	else
	{
		*pVal = pQ->pBase[pQ->front];
		pQ->front = (pQ->front + 1) % 6;

		return true;
	}
}

链表实现原理

在这里插入图片描述

通过两个指针pHead和pTail,可实现入队和出队操作,同时也避免了出现队满现象,使用时利用动态指针操作,实时使用和释放。

C++代码实现

#include <iostream>
using namespace std;

typedef struct node
{
	int data;
	struct node* pNext;
}NODE, *PNODE;

class Queue
{
public:
	Queue()
	{
		this->pHead = this->pTail = new NODE; // 初始化
		this->pHead->pNext = NULL;
	}
	
	//链式存储不用判断是否为满!
	void InQueue(int val)
	{
		PNODE pNew = new NODE;

		pNew->data = val;
		pNew->pNext = NULL;

		pTail->pNext = pNew;  //链表链接
		pTail = pNew; // 指针下移

		return;
	}

	bool Empty()const
	{
		if (this->pHead == pTail)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	int OutQueue()
	{
		if (Empty())
		{
			cout << "队列为空,无法出队!" << endl;
		}
		else
		{
			PNODE pTemp = pHead->pNext;
			pHead->pNext = pTemp->pNext;
			int val = pTemp->data;
			delete pTemp;
			pTemp = NULL;
			
			if (NULL == pHead->pNext) //如果队列为空
			{
				pTail = pHead;//尾指针也指向无用的头结点
			}
			return val;
		}
	}

	//遍历队列
	void Travers(void)const
	{
		PNODE pTemp = pHead->pNext;

		while (pTemp != NULL)
		{
			cout << pTemp->data << " ";
			pTemp = pTemp->pNext;
		}
		cout << endl;
	}

	void Clear()
	{
		while (!this->Empty())
		{
			OutQueue();
		}
	}

	~Queue()
	{
		this->Clear();
		delete pHead;
	}

private:
	PNODE pHead;
	PNODE pTail;
};

int main()
{
	Queue Q;
	for (int i = 0; i < 5; i++)
	{
		Q.InQueue(i + 1);
	}
	Q.Travers();

	Q.OutQueue();
	Q.OutQueue();
	Q.Travers();


	system("pause");

	return 0;
}

非线性结构

数组实现原理

在这里插入图片描述

一般采用完全二叉树,如上图所示,存在特定的规律进行一维数组的存储

链表实现原理

在这里插入图片描述

首先,必须要明确排序的方式:先序,中序,后序。其次,根据排列方式,我们可以通过该方式实现对树的内容实现

C语言代码实现

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

struct BTNode
{
	int data;
	struct BTNode* pLchild;
	struct BTNode* pRchild;
};

struct BTNode* CreateBTree(void);
void PreTraverseBTree(struct BTNode* pT);
void InTraverseBTree(struct BTNode* pT);

int main(void)
{
	struct BTNode* pT = CreateBTree();
	//PreTraverseBTree(pT);
	InTraverseBTree(pT);
	//PostTraverseBTree(pT);

	return 0;
}

struct BTNode* CreateBTree(void)
{
	struct BTNode* pA = (struct BTNode*)malloc(sizeof(struct BTNode));
	struct BTNode* pB = (struct BTNode*)malloc(sizeof(struct BTNode));
	struct BTNode* pC = (struct BTNode*)malloc(sizeof(struct BTNode));
	struct BTNode* pD = (struct BTNode*)malloc(sizeof(struct BTNode));
	struct BTNode* pE = (struct BTNode*)malloc(sizeof(struct BTNode));

	pA->data = 'A';
	pB->data = 'B';
	pC->data = 'C';
	pD->data = 'D';
	pE->data = 'E';

	pA->pLchild = pB;
	pA->pRchild = pC;
	pB->pLchild = pB->pRchild = NULL;
	pC->pLchild = pD;
	pC->pRchild = NULL;
	pD->pLchild = NULL;
	pD->pRchild = pE;
	pE->pLchild = pE->pRchild = NULL;

	return pA;
}

void PreTraverseBTree(struct BTNode* pT)
{
	if (NULL != pT)
	{
		printf("%c\n", pT->data);
		if (NULL != pT->pLchild)
		{
			PreTraverseBTree(pT->pLchild);
		}
		if (NULL != pT->pRchild)
		{
			PreTraverseBTree(pT->pRchild);
		}
	}
}

void InTraverseBTree(struct BTNode* pT)
{
	if (NULL != pT)
	{
		if (NULL != pT->pLchild)
		{
			InTraverseBTree(pT->pLchild);
		}

		printf("%c\n", pT->data);

		if (NULL != pT->pRchild)
		{
			InTraverseBTree(pT->pRchild);
		}
	}
}

void ProTraverseBTree(struct BTNode* pT)
{
	if (NULL != pT)
	{
		if (NULL != pT->pLchild)
		{
			ProTraverseBTree(pT->pLchild);
		}

		if (NULL != pT->pRchild)
		{
			ProTraverseBTree(pT->pRchild);
		}

		printf("%c\n", pT->data);
	}
}

补充

数组C语言实现代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#include <stdlib.h> 

struct Arr
{
	int len; //数组的长度
	int cnt; //有效位数
	int * pBase;// 指针
};

void init_arr(struct Arr* pArr);
void append_arr(struct Arr* pArr);
void insert_arr(struct Arr* pArr);
void delete_arr(struct Arr* pArr);
void get(struct Arr* pArr);
bool is_empty(struct Arr* pArr);
bool is_full(struct Arr* pArr);
void sort_arr(struct Arr* pArr);
void show_arr(struct Arr* pArr);
void inversion_arr(struct Arr* pArr);

int main()
{
	struct Arr arr;

	init_arr(&arr);
	append_arr(&arr);
	append_arr(&arr);
	append_arr(&arr);
	//append_arr(&arr);
	show_arr(&arr);
	//insert_arr(&arr);
	//delete_arr(&arr);
	//sort_arr(&arr);
	inversion_arr(&arr);

	return 0;
}

void init_arr(struct Arr * pArr)
{
	int length;

	printf("请输入需要开辟数组的总长度:");
	scanf_s("%d", &length);
	
	pArr->pBase = (int*)malloc(sizeof(int) * length);
	if (NULL == pArr->pBase)
	{
		printf("动态内存分配失败!\n");
		exit(-1);
	}
	else 
	{
		pArr->len = length;
		pArr->cnt = 0;
	}
	return;
}

bool is_empty(struct Arr* pArr)
{
	if (0 == pArr->cnt)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void show_arr(struct Arr* pArr)
{
	if (is_empty(pArr))
	{
		printf("数组为空!");
	}
	else
	{
		for (int i = 0; i < pArr->cnt; i++)
		{
			printf("%d  ", pArr->pBase[i]);
		}
		printf("\n");
	}
}

bool is_full(struct Arr* pArr)
{
	if (pArr->cnt == pArr->len)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void append_arr(struct Arr* pArr)
{
	int val;

	if (is_full(pArr))
	{
		printf("数组已满,添加失败!\n");
	}
	else
	{
		printf("请输入添加的元素:");
		scanf_s("%d", &val);
		
		pArr->pBase[pArr->cnt] = val;
		pArr->cnt++;
	}
}

void insert_arr(struct Arr* pArr)
{
	int pos;
	int val;

	if (is_full(pArr))
	{
		printf("插入失败,数组已满!\n");
	}
	else
	{
		printf("请输入元素插入的位置(默认从1开始):");
		scanf_s("%d", &pos);
		
		if (pos<1 || pos>pArr->len)
		{
			printf("插入失败,输入有误!\n");
		}
		else
		{
			printf("请输入插入的元素:");
			scanf_s("%d", &val);

			for (int i = pArr->cnt; i > pos - 1; i--)
			{
				pArr->pBase[i] = pArr->pBase[i - 1];
			}

			pArr->pBase[pos - 1] = val;
			pArr->cnt++;

			printf("添加后的数组为:\n");
			show_arr(pArr);
		}
	}
}

void delete_arr(struct Arr* pArr)
{
	int pos;

	if (is_empty(pArr))
	{
		printf("删除失败,数组为空!\n");
	}
	else
	{
		printf("请输入删除元素的位置(默认从1开始):");
		scanf_s("%d", &pos);

		if (pos<1 || pos>pArr->cnt)
		{
			printf("删除失败,输入有误!");
		}
		else
		{
			for (int i = pos; i < pArr->cnt; i++)
			{
				pArr->pBase[i - 1] = pArr->pBase[i];
			}
			pArr->cnt--;

			printf("删除后的数组排序为:");
			show_arr(pArr);
		}
	}
}
void get(struct Arr* pArr)
{
	int pos;

	printf("请输入元素的位置:(默认从1开始):");
	scanf_s("%d", &pos);

	if (pos<1 || pos>pArr->cnt)
	{
		printf("获取,输入有误!\n");
	}
	else
	{
		printf("该位置的元素为:%d\n", pArr->pBase[pos - 1]);
	}
}

void sort_arr(struct Arr* pArr)
{
	int temp;

	for (int i = 0; i < pArr->cnt-1; i++)
	{
		for (int j = 0; j < pArr->cnt - 1 - i; j++)
		{
			if (pArr->pBase[j] > pArr->pBase[j + 1])
			{
				temp = pArr->pBase[i];
				pArr->pBase[i] = pArr->pBase[i + 1];
				pArr->pBase[i + 1] = temp;
			}
		}
	}

	printf("排序后的结果为:\n");
	show_arr(pArr);
}

void inversion_arr(struct Arr* pArr)
{
	int i = 0;
	int j = pArr->cnt-1;
	int temp;

	while (i < j)
	{
		temp = pArr->pBase[i];
		pArr->pBase[i] = pArr->pBase[j];
		pArr->pBase[j] = temp;
		i++;
		j--;
	}

	printf("数组倒置后的结果为:\n");
	show_arr(pArr);
}

链表C语言实现代码

#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>

typedef struct Node
{
	int data; //数据域
	struct  Node* pNext; //指针域
}NODE, *PNODE;

PNODE create_list();
void traverse_list(PNODE pHead);
bool is_empty(PNODE pHead);
int length_list(PNODE);
bool insert_list(PNODE, int, int);
bool delete_list(PNODE, int, int*);
void sort_list(PNODE);

int main()
{
	PNODE pHead = NULL;
	int val;

	pHead = create_list();
	traverse_list(pHead);
	/*int len = length_list(pHead);
	printf("链表的长度是%d\n", len);*/
	//sort_list(pHead);
	
	if (!insert_list(pHead, 1, 3))
	{
		printf("失败!");
	}
	traverse_list(pHead);

	delete_list(pHead, 2, &val);
	printf("删除的元素为:%d", val);

	return 0;
}

PNODE create_list(void)
{
	int len;
	int i;
	int val;

	PNODE pHead = (PNODE)malloc(sizeof(NODE));
	PNODE pTail = pHead;
	pTail->pNext = NULL;

	if (NULL == pHead)
	{
		printf("分配失败,程序终止!\n");
		exit(-1);
	}

	printf("请输入您需要生成的链表节点的个数:len = ");
	scanf_s("%d", &len);

	for (i = 0; i < len; i++)
	{
		printf("请输入第%d个节点的值:", i+1);
		scanf_s("%d", &val);

		PNODE pNew = (PNODE)malloc(sizeof(NODE));
		if (NULL == pNew)
		{
			printf("分配失败,程序终止!\n");
			exit(-1);
		}

		pNew->data = val;
		pTail->pNext = pNew;
		pNew->pNext = NULL;
		pTail = pNew;
	}
	return pHead;
}

void traverse_list(PNODE pHead)
{
	PNODE p = pHead->pNext;
	
	while (NULL != p)
	{
		printf("%d  ", p->data);
		p = p->pNext;
	}
	printf("\n");

	return;
}

bool is_empty(PNODE pHead)
{
	if (NULL == pHead->pNext)
	{
		return true;
	}
	else
	{
		return false;
	}	
}

int length_list(PNODE pHead)
{
	PNODE p = pHead->pNext;
	int len = 0;

	while (NULL != p)
	{
		len++;
		p = p->pNext;
	}
	return len;
}

void sort_list(PNODE pHead)
{
	int i, j, t;
	PNODE p, q;

	for (i = 0, p=pHead->pNext; i < length_list(pHead) - 1; i++, p=p->pNext)
	{
		for (j = i + 1, q = p->pNext; j < length_list(pHead); j++, q = q->pNext)
		{
			if (p->data > q->data)
			{
				t = p->data;
				p->data = q->data;
				q->data = t;
			}
		}
	}
}

bool insert_list(PNODE pHead, int pos, int val)
{
	int i = 0;
	PNODE p = pHead;
	
	//将指针位置定到pos前
	while (NULL != p && i < pos - 1)
	{
		p = p->pNext;
		++i;
	}

	//检查指针位置是否合适
	if (i > pos - 1 || NULL == p)
	{
		return false;
	}

	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if (NULL == pNew)
	{
		printf("动态分配内存失败!\n");
		exit(-1);
	}
	pNew->data = val;
	PNODE q = p->pNext;
	p->pNext = pNew;
	pNew->pNext = q;

	return true;
}

bool delete_list(PNODE pHead, int pos, int* pVal)
{
	int i = 0;
	PNODE p = pHead;

	//将指针位置定到pos前
	while (NULL != p->pNext && i < pos - 1)
	{
		p = p->pNext;
		++i;
	}

	//检查指针位置是否合适
	if (i > pos - 1 || NULL == p->pNext)
	{
		return false;
	}

	PNODE q = p->pNext;
	*pVal = q->data;

	p->pNext = p->pNext->pNext;
	free(q);
	q = NULL;

	return true;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Fighting_1997

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

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

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

打赏作者

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

抵扣说明:

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

余额充值