我学《数据结构与算法》 20155314刘子健
我学《数据结构与算法》
我眼中的数据结构
一句话
组织数据的方式
分类
- 逻辑结构
- 线性结构(一对一)
- 非线性结构
- 集合(无逻辑关系)
- 树(一对多)
- 图(网)(多对多)
- 存储结构(物理结构)
- 顺序
- 链式
- 散列
- 索引
整合起来看就是

基本操作
- 增
- 删
- 查
- 改
我学过的算法
- 排序
- 基于关键字比较
- 插入排序
- 快速排序
- 堆排序
- 归并排序
- 不基于关键字比较
- 计数排序
- 基数排序
- 基于关键字比较
- 查找
- 静态
- 折半查找
- 动态
- 散列查找
- 基于二叉搜索树的查找
- 静态
- 遍历
- 二叉树的遍历
- 先序遍历
- 中序遍历
- 后序遍历
- 图的遍历
- 深度优先
- 广度优先
- 拓扑排序
- 二叉树的遍历
- 优化
- 按问题组织算法
- 最优二叉树——Huffman算法
- 最小生成树
- Prim算法
- Kruskal算法
- 最短路径
- Dijkstra算法
- Floyd算法
- 关键路径
- 按策略组织算法
- 贪心算法
- 动态规划
- 按问题组织算法
- 字符串匹配——KMP算法
- 经典问题
- 背包问题
- 0-1背包问题——动态规划
- 分数背包问题——贪心策略
- N皇后问题——回溯法
- 旅行商问题——动态规划
- 子集和问题
- 回溯法
- 动态规划——转化为0-1背包问题
- 背包问题
整合起来看就是

C语言实现
数据结构(存储结构)
- 线性表
-
顺序表
define LIST_INIT_SIZE 80 //线性表存储空间的初始分配量
define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef int ElemType;
typedef struct {
ElemType *elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList; //顺序表 -
单链表
typedef int ElemType;
typedef struct LNode {
ElemType data; //数据域
struct LNode next; //指针域
}LNode,LinkList;
LinkList L; //L为单链表的头指针
-
- 栈(先进后出)
-
顺序栈
define STACK_INIT_SIZE 100 //最大栈长度
typedef int ElemType;
typedef struct {
ElemType *base; //栈底指针
ElemType *top; //栈顶指针
int stacksize;
}SqStack; -
链栈
define STACK_INIT_SIZE 100
typedef int ElemType;
typedef struct Node {
ElemType data;
struct Node next;
}LinkStack;
-
- 队列(先进先出)
-
循环队列
define MAXQSIZE 100 //最大队列长度
typedef int ElemType;
typedef struct {
ElemType *base; //动态分配存储空间
int front; //头指针,若队列不空,指向队列头元素
int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
int queuesize;
}SqQueue; -
链队列
typedef int QElemType;
typedef struct QNode { //结点类型
QElemType data;
struct QNode next;
}QNode,QueuePtr;
typedef struct { //链队列类型
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
-
- 树
-
二叉链表
typedef int ElemType;
typedef struct BiTNode { //结点结构
ElemType data;
struct BiTNode lchild,rchild; //左右孩子指针
}BiTNode,*BiTree;
BiTree T; //二叉链表的根指针 -
B树
define m 3 // B树的阶,此设为4
typedef int KeyType;
typedef struct {
KeyType key;
char data;
}Record;
typedef struct BTNode {
int keynum; //结点中关键字个数,结点大小
struct BTNode *parent; //指向双亲结点的指针
KeyType key[m+1]; //关键字向量(0号单元不用)
struct BTNode *ptr[m+1]; //子树指针向量
Record recptr[m+1]; //记录指针向量(0号单元不用)
}BTNode,BTree; //B树结点和B树的类型
typedef struct {
BTNode *pt; //指向找到的结点的指针
int i; //1..m,在结点中的关键字序号
int tag; //标志查找成功(=1)或失败(=0)
} Result; //在B树的查找结果类型
-
- 图
-
邻接矩阵
define MAX_VERTEX_NUM 100
typedef char VertexType;
typedef int EdgeType;
typedef enum
{
DG,UDG
}GraphKind;
typedef struct { //图的定义
VertexType vexs[MAX_VERTEX_NUM]; //存储顶点信息
EdgeType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵,存储边的信息
int vexnum,arcnum; //顶点数,边数
GraphKind kind; //图的种类标志
}MGraph; -
邻接表
define MAX_VERTEX_NUM 100
typedef char VertexType;
typedef enum
{
DG,UDG
}GraphKind;
typedef struct ArcNode { //边的结点结构
int adjvex; //该边所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
}ArcNode;
typedef struct VNode { //顶点的顶点结构
VertexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附于该顶点的边
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct { //图的定义
AdjList vertices;
int vexnum,arcnum; //顶点数,边数
GraphKind kind; //图的种类标志
}ALGraph;
-
算法
-
排序算法
include <stdio.h>
include <stdlib.h>
define N 5
void BubbleSort(int a[]);
void SelectionSort(int a[]);
void InsertionSort(int a[]);
void QSort(int a[],int s,int t);
int Partition(int R[],int low,int high);
void CountingSort(int a[],int k);
int max(int a[]);
void HeapSort(int a[]);
void MaxHeapify(int a[],int s,int m);
void BuildMaxHeap(int a[]);
void MergeSort(int a[],int s,int t);
void Merge(int a[],int i,int m,int n);
void main()
{
int i,j,temp;
int a[N],b[N];
printf("请输入%d个整数:",N);
for(i=0;i<N;i++)
{
scanf("%d",&a[i]);
}
BubbleSort(a); //冒泡排序
/for(i=0;i<N;i++) //冒泡排序
{
for(j=0;j<N;j++)
{
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}///冒泡排序
SelectionSort(a);
//InsertionSort(a); //插入排序
/for(i=0,j=1;i<N,j<N+1;i++,j++) //将下标改为从1开始
{
b[j]=a[i];
}
QSort(b,1,N);
for(i=1;i<N+1;i++)
{
printf("%d ",b[i]);
}/ //快速排序
//CountingSort(a,max(a)); //计数排序
//HeapSort(a); //堆排序
/for(i=0,j=1;i<N,j<N+1;i++,j++) //将下标改为从1开始
{
b[j]=a[i];
}
MergeSort(b,1,N);
for(i=1,j=0;i<N+1,j<N;i++,j++) //将数组下标还原为从0开始
{
a[j]=b[i];
}/ //归并排序
for(i=0;i<N;i++)
{
printf("%d ",a[i]);
}
}void BubbleSort(int a[]) //冒泡排序
{
int i,j,temp;
for(i=0;i<N-1;i++)
{
for(j=i+1;j<N;j++)
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
}void SelectionSort(int a[]) //选择排序
{
int i,j,k,temp;
for(i=0;i<N-1;i++)
{
k=i; //从下标为0处开始记录
for(j=i+1;j<N;j++)
{
if(a[j]<a[k])
{
k=j; //记录最小数下标位置
}
}
if(k!=i) //优化处理:若最小数所在的下标位置不在下标位置i,则交换
{
temp=a[k];
a[k]=a[i];
a[i]=temp;
}
}
}void InsertionSort(int a[]) //插入排序
{
int i,j,b[N];
for(i=0,j=1;i<N,j<N+1;i++,j++) //将下标改为从1开始,便于设置监视哨a[0]
{
b[j]=a[i];
}
for(i=2;i<=N;i++)
{
if(b[i]<b[i-1])
{
b[0]=b[i]; //复制为监视哨
for(j=i-1;b[0]<b[j];j--)
{
b[j+1]=b[j];
}
b[j+1]=b[0];
}
}
for(i=1,j=0;i<N+1,j<N;i++,j++) //将数组下标还原为从0开始
{
a[j]=b[i];
}
}void QSort(int a[],int s,int t) //快速排序
{
int pivotloc;
if(s<t-1) //长度大于1
{
pivotloc=Partition(a,s,t); //对a[]进行一次划分
QSort(a,s,pivotloc-1); //对左子序列递归排序,pivotloc是轴位置
QSort(a,pivotloc+1,t); //对右子序列递归排序
}}
int Partition(int R[],int low,int high)
{
int pivotkey;
R[0]=R[low];
pivotkey=R[low]; //"轴"
while (low<high)
{
while (low<high&&R[high]>=pivotkey)
high--;
R[low]=R[high];
while (low<high&&R[low]<=pivotkey)
++low;
R[high]=R[low];
}
R[low]=R[0];
return low;
}void CountingSort(int a[],int k) //计数排序
{
int i,j;
int C[N]; //引入索引数组C
int R[N]; //新建存储数组R
for(i=0;i<=k;i++)
{
C[i]=0; //初始化数组c
}
for(i=0;i<N;i++)
{
C[a[i]]++; //c[i]中存值等于i的元素个数
}
for(i=1;i<=k;i++)
{
C[i]=C[i]+C[i-1]; //c[i]中存值小于等于i的元素个数
}
for(j=N-1;j>=0;j--)
{
R[C[a[j]]]=a[j];
C[a[j]]--; //下一个值为a[j]的元素被放到a[j]的前一个位置
}
for(i=0;i<N;i++)
{
a[i]=R[i+1];
}
}
int max(int a[])
{
int i;
int max;
max = a[0];
for(i=1;i<N;i++)
{
if (max<a[i])
max=a[i];
}
return max;
}void HeapSort(int a[]) //堆排序
{
int temp,i;
BuildMaxHeap(a); //建大顶堆
for(i=N;i>1;i--)
{
temp=a[0]; //将堆顶元素和当前未经排序子序列a[0...i-1]中最后一个元素交换
a[0]=a[i-1];
a[i-1]=temp;
MaxHeapify(a,0,i-2); //调整a[0...i-2]使其成为大顶堆
}
}
void MaxHeapify(int a[],int s,int m) //维护堆的性质
{
int rc,j;
rc=a[s]; //暂存a[s]
for(j=2s;j<=m;j=2)
{
if(j<m&&a[j]<a[j+1]) j++; //左右"孩子"之间先进行相互比较,令j指示较大的关键字所在位置
if(rc>=a[j]) break; //再作"根"和"孩子"之间比较,若">="成立,则说明已找到rc的插入位置s,不需继续向下调整
a[s]=a[j];
s=j; //否则关键字上移,仍需继续向下调整
}
a[s]=rc; //将调整前的堆顶插入到s位置
}
void BuildMaxHeap(int a[]) //建堆
{
int i;
for(i=N/2-1;i>=0;i--)
{
MaxHeapify(a,i,N); //建大顶堆
}
}void MergeSort(int a[],int s,int t) //归并排序
{
int m;
if(s<t)
{
m=(s+t)/2; //分解
MergeSort(a,s,m); //解决
MergeSort(a,m+1,t);
Merge(a,s,m,t); //合并
}
}
void Merge(int a[],int i,int m,int n) //归并有序序列a[i...m]和a[m+1...n]
{
int j,k,p,q;
int R[N];
for(j=i;j<=n;j++)
{
R[j]=a[j]; //复制
}
for(j=m+1,k=i;i<=m&&j<=n;k++)
{
if(R[i]<=R[j]) a[k]=R[i++];
else a[k]=R[j++];
}
if(i<=m)
{
for(p=i,q=k;p<=m,q<=n;p++,q++)
{
a[q]=R[p];
}
}
if(j<=n)
{
for(p=j,q=k;p<=n,q<=n;p++,q++)
{
a[q]=R[p];
}
}
}

浙公网安备 33010602011771号