系统学习完数组和链表后,才了解道其重要性,对于栈和链表以及树等结构,其内核分为数组实现和链表实现两种方式,为防止遗忘,特意整理如下,部分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;
}
本文深入探讨了数据结构中的栈、队列和树的实现,包括数组和链表两种基本存储方式。详细介绍了栈的先进后出原则,链表实现的栈、队列以及树的结构。通过C语言代码展示了数组和链表在实现栈的入栈、出栈、遍历,队列的入队、出队以及树的遍历等操作。同时,文章还讨论了循环链表在队列实现中的应用,以及链表在存储树结构时的优势。此外,补充了数组和链表实现的一般操作,如动态数组的增删查改以及链表的插入、删除等操作。
5万+

被折叠的 条评论
为什么被折叠?



