目录
1. 顺序表(数组 Array)
2. 链表
2.1 单链表(SingleList)
2.2 带头双向循环链表(List)
2.3 顺序表和链表的对比
3. 栈(Stack)
4. 队列(Queue)
5. 树(Tree)
5.1 树的特点
5.2 二叉树:满二叉树和完全二叉树
5.2.1 顺序结构(数组来存储,heap里面讲)
5.2.2 链式结构
6. 堆(Heap)其实是完全二叉树
7. 图(graph)
8. 散列表(Hash)
数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。每一种数据结构都有着独特的数据存储方式。常用的数据结构有:数组,栈,链表,队列,树,图,堆,散列表等,如图所示:
顺序表的接口:
struct SerList//动态顺序表
{
SQDateType *a;
int size;
int capacity;
};
typedef struct SerList SL;
void SeqListPushBack(SL* ps, SQDateType x);
void SeqListPushFront(SL* ps, SQDateType x);
void SeqListPopBack(SL* ps);
void SeqListPopFront(SL* ps);
void SeqListInsert(SL* ps, int pos, SQDateType x);
void SeqListErase(SL* ps, int pos);
int SeqListFind(SL* ps, SQDateType x);
void SeqListModify(SL* ps, int pos, SQDateType x);
顺序表的问题:
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
单链表的接口:
typedef int SLDateType;
typedef struct SListNode
{
SLDateType data;
struct SListNode* next;//注意:这里不能嵌套结构体,只能是地址
}SLTNode;
void SListPrint(SLTNode* phead);
void SListPushBack(SLTNode** pphead, SLDateType x);
void SListPushFront(SLTNode** pphead, SLDateType x);
void SListPopBack(SLTNode** pphead);
void SListPopFront(SLTNode** pphead);
SLTNode* SListFind(SLTNode* phead, SLDateType x);
void SListInsert(SLTNode** pphead, SLTNode* pos, SLDateType x);
void SListErase(SLTNode** pphead, SLTNode* pos);
int SListLen(SLTNode* phead);//求链表的长度
双向循环链表的接口:
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* prev;
struct ListNode* next;
}ListNode;
void ListInit(ListNode** pphead);
void ListDestroy(ListNode* phead);
void ListPushBack(ListNode* phead, LTDataType x);
void ListPushFront(ListNode* phead, LTDataType x);
void ListPopBack(ListNode* phead);
void ListPopFront(ListNode* phead);
void ListPrint(ListNode* phead);
ListNode* ListFind(ListNode* phead, LTDataType x);
void ListInsert(ListNode* phead, ListNode* pos, LTDataType x);
void ListErase(ListNode* phead, ListNode* pos);
顺序表:
链表:
栈的接口(用数组来实现的,也可以用链表):
//栈可以用顺序表(数组)来实现
typedef int STDateType;
typedef struct Stack
{
STDateType* a;
int top;//top用来操作栈顶的数据,top相当于size
int capacity;
}Stack;
void StackInit(Stack* pst);
void StackDestroy(Stack* pst);
void StackPush(Stack* pst, STDateType x);
void StackPop(Stack* pst);
STDateType StackTop(Stack* pst);
bool StackEmpty(Stack* pst);
int StackSize(Stack* pst);
队列的接口:
typedef int QDataType;
// 链式结构:表示队列
typedef struct QListNode
{
struct QListNode* next;
QDataType data;
}QNode;
// 队列可以用链表来实现
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
void QueueInit(Queue* q);// 初始化队列
void QueueDestroy(Queue* q);// 销毁队列
void QueuePush(Queue* q, QDataType data);// 队尾入队列
void QueuePop(Queue* q);// 队头出队列
QDataType QueueFront(Queue* q);// 获取队列头部元素
QDataType QueueBack(Queue* q);// 获取队列队尾元素
int QueueSize(Queue* q);// 获取队列中有效元素个数
bool QueueEmpty(Queue* q);// 检测队列是否为空
树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
在日常的应用中,我们讨论和用的更多的是树的其中一种结构,就是二叉树。
二叉树是树的特殊一种,具有如下特点:
二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。
顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。二叉树顺序存储在 物理上是一个数组,在逻辑上是一颗二叉树。
链式结构接口如下:(包括三种遍历方式:前序遍历、中序遍历、后序遍历,以及层序遍历)
typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);
堆是一种比较特殊的数据结构,可以被看做一棵树的数组对象,具有以下的性质:
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2),满足前者的表达式的成为小顶堆,满足后者表达式的为大顶堆,这两者的结构图可以用完全二叉树排列出来,示例图如下:
堆的接口实现:(向下调整算法、向上调整算法)
typedef int HPDataType;
//用数组来实现堆(堆就是完全二叉树)
typedef struct Heap
{
HPDataType* _a;
int _size;
int _capacity;
}Heap;
void AdjustDown(int* a, int n, int parent);
void AdjustUp(int* a, int child);
// 堆的构建
void HeapCreate(Heap* hp, HPDataType* a, int n);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
int HeapEmpty(Heap* hp);
// 对数组进行堆排序
void HeapSort(int* a, int n);
(待更新……)