数据结构(C语言版本)

第1章 绪论

1.常用的数据结构类型:集合、线性、树形、图状。

2.数据结构:
- 逻辑结构:数据元素之间的关系
- 存储结构:数据结构在计算机中的表示。存储结构分为:顺序存储结构和链式存储结构。

3.算法是对特定问题求解步骤的一种描述,算法具有如下特性:有穷性、确定性、可行性、输入、输出。

4.算法的度量:
- 时间复杂度
- 空间复杂度

第二章 线性表

1.线性表的定义:
- 存在唯一一个“第一个”元素
- 存在唯一一个“最后一个”元素
- 除第一个元素外,每一个元素都有且只有一个前驱
- 除最后一个元素外,每个元素都有且只有一个后继

2.线性表合并的方法:
- 将表A中的元素逐个和B中的比较,不同就加入到B中。时间复杂度为O(len(A)*len(B))
- AB是有序排列的前提下,使用两个指针分别指向A和B,将两者较小的元素插入到C中,然后移动较小的指针,直到全部插入到C。时间复杂度为O(len(A)+len(B))

3.线性表的顺序实现:满足LOC(A(i+l))=LOC(A(i))+l,LOC表示元素地址。特点:下标读取快O(1),插入删除O(n)。

#include <stdlib.h>
#ifndef SEQUENCE_LINER_LIST_H
#define SEQUENCE_LINER_LIST_H/*线性表的顺序实现
*/
#define LIST_INIT_SIZE 100  //初始分配量
#define LIST_INCREMENT 10   //增量
#define LIST_TYPE int       //存储类型typedef struct strSequenceLinerList
{LIST_TYPE *elem;        //存储空间基址unsigned int length;    //当前长度unsigned int listSize;  //当前存储容量
}SequnceLinerList;static enum Status
{OK,FAILED,OVERFLOW
};/* 线性表初始化 */
Status initSequenceLinerList(SequnceLinerList& list)
{list.elem = (LIST_TYPE *)malloc(sizeof(LIST_TYPE)*LIST_INIT_SIZE);if (!list.elem){return OVERFLOW;}list.length = 0;list.listSize = LIST_INIT_SIZE;return OK;
}/* 扩展 */
Status resizeSequenceLinerList(SequnceLinerList& list)
{printf("Resize...\n");list.elem = (LIST_TYPE*)realloc(list.elem, sizeof(LIST_TYPE)*(list.listSize + LIST_INCREMENT));if (!list.elem){return OVERFLOW;}list.listSize += LIST_INCREMENT;return OK;
}/* 打印 */
void printSequnceLinerList(SequnceLinerList& list)
{printf("Begin print list...\n");printf("length=%d,listSize=%d.\n",list.length,list.listSize);unsigned int i = 0;for (; i < list.length-1;++i){printf("%d,",list.elem[i]);}printf("%d\n", list.elem[i]);printf("End print list.\n");
}/* 线性表插入:position表示插入的位置,从1开始。第一个元素是list.elem[0] */
Status insertSequenceLinerList(SequnceLinerList& list, unsigned int position, LIST_TYPE value)
{if (position<1 || position>list.length+1){return FAILED;}if (list.length >= list.listSize){Status res = resizeSequenceLinerList(list);if (OK != res){return FAILED;}}LIST_TYPE* p = &list.elem[position -1];LIST_TYPE* q = &list.elem[list.length];for (; p != q; --q){*(p + 1) = *p;}list.length++;*p = value;return OK;
}/* 删除元素 */
Status deleteSequenceLinerList(SequnceLinerList& list, unsigned int position)
{if (position<1 || position>list.length){return FAILED;}LIST_TYPE* p = &list.elem[position - 1];LIST_TYPE* q = &list.elem[list.length - 1];for (; p != q; ++p){*p = *(p+1);}--list.length;return OK;
}/* 查找:第一个值的下标 */
unsigned int findSequenceLinerList(SequnceLinerList& list, int value)
{for (unsigned int i = 0; i < list.length;++i){if (value == list.elem[i]){return i;}}return -1;
}/* 排序(冒泡) */
void sortSequeceLinerList(SequnceLinerList& list)
{unsigned int i = 0;unsigned int j = 0;for (; i < list.length-1;++i){for (j = i + 1; j < list.length; ++j){if (list.elem[i]>list.elem[j]){LIST_TYPE tmp = list.elem[i];list.elem[i] = list.elem[j];list.elem[j] = tmp;}}}
}/* 销毁 */
void destroySequenceLincerList(SequnceLinerList& list)
{delete list.elem;list.elem = NULL;
}#endif

4.线性表的链式实现:通过p=p.next查找具体位置的链表。特点:插入、删除快O(n)。

#include <stdio.h>
#include <stdio.h>
#ifndef LINK_LINER_LIST_H
#define LINK_lINER_LIST_H
#define LINK_LIST_TYPE int/*线性表的链表实现
*/
typedef struct strLinkLinerList
{LINK_LIST_TYPE data;struct strLinkLinerList* pNext;
}LinkLinerList;LinkLinerList* head = NULL;/* 链表初始化 */
Status initLinkLinerList()
{if (NULL == head){head = (LinkLinerList*)malloc(sizeof(LinkLinerList));if (!head){return OVERFLOW;}head->pNext = NULL;return OK;}else{return FAILED;}
}/* 添加元素 */
Status insertLinkLinerList(LINK_LIST_TYPE value)
{if (NULL == head){return FAILED;}LinkLinerList* p = head;while (p->pNext){p = p->pNext;}LinkLinerList* tmp = (LinkLinerList*)malloc(sizeof(LinkLinerList));if (!tmp){return OVERFLOW;}tmp->data = value;tmp->pNext = NULL;p->pNext = tmp;return OK;
}/*打印*/
void printLinkLinerList()
{printf("Begin print...\n");if (NULL == head || NULL == head->pNext){printf("List is null.");}LinkLinerList* p = head->pNext;while (p->pNext){printf("%d,",p->data);p = p->pNext;}printf("%d\n", p->data);printf("End print.\n");
}/* 排序 */
Status sortLinkLinerList()
{if (NULL == head || NULL == head->pNext){return FAILED;}LinkLinerList* p = head->pNext;LinkLinerList* q = p->pNext;while (p){q = p->pNext;while (q){if (p->data > q->data){LINK_LIST_TYPE tmp = p->data;p->data = q->data;q->data = tmp;}q = q->pNext;}p = p->pNext;}return OK;
}/* 长度 */
unsigned int lengthLinkLinerList()
{if (head == NULL || head->pNext == NULL){return 0;}LinkLinerList* p = head->pNext;unsigned int length = 0;while (p){p = p->pNext;length++;}return length;
}/* 删除 */
Status deleteLinkLinerList(unsigned int position)
{if (position > lengthLinkLinerList() || position < 1){return FAILED;}else{LinkLinerList* p = head;LinkLinerList* q = p->pNext;if (NULL == p || NULL == q){return FAILED;}while (--position){p = p->pNext;q = p->pNext;}p->pNext = q->pNext;free(q);return OK;}
}/* 销毁 */
void destroyLinkLinerList()
{if (NULL == head){return;}else{LinkLinerList* p = head->pNext;LinkLinerList* q = p;while (p){p = p->pNext;free(q);q = p;}}
}#endif

上面实现的是线性表的链式结构。此外,线性表通过链表还可以实现:
- 循环列表:表最后的一个节点的指针指向表头
- 双列表:指针可以指向下一个元素或者上一个元素

5.线性表的用途:
- 一元多项式的表示和相加

第3章 栈和队列

1.栈和队列是特殊的线性表。

2.栈是先进后出的线性表,其表示:typedef struct{Type *base;Type *top; int stacksize;}SqStack;其中base始终指向栈底,top随元素的添加一直指向栈顶。可以有顺序实现和链表实现。

3.栈的应用举例:
- 数制转换
- 括号匹配
- 行编辑器帮助处理错误输入
- 迷宫求解
- 表达式求解
- 实现递归

3.队列是先进先出的线性表。可以由链表实现和顺序实现。

第四章 串

1.串是由零到多个字符组成的字符序列。

2.串的模式匹配算法(查找子串):
- 找到主串中第一个等于子串首字符的位置,开始逐步遍历子串和主串:时间复杂度O(n*(m-n+1)),其中m,n是主串、子串长度
- kmp算法:关键是部分匹配值的计算(”部分匹配”的实质是,有时候,字符串头部和尾部会有重复。比如,”ABCDAB”之中有两个”AB”,那么它的”部分匹配值”就是2(”AB”的长度)。搜索词移动的时候,第一个”AB”向后移动4位(字符串长度-部分匹配值),就可以来到第二个”AB”的位置)。时间复杂度O(n+m)。KMP算法仅当子串与主串之间存在很多”部分匹配”的情况下才快的多。详见http://kb.cnblogs.com/page/176818/

第五章 数组和广义表

1.广义表(Lists,又称列表)是一种非线性的数据结构,是线性表的一种推广。即广义表中放松对表元素的原子限制,容许它们具有其自身结构。

第六章 树和二叉树

1.树的相关概念:
- 度:节点的子树数目称之为节点的度。度为0的节点称之为叶子。
- 深度:树中结点的最大层次。

2.二叉树子节点至多有两个,且有左右之分。二叉树有五种基本形态:空、根、右子树为空、左右子树非空、左子树为空。二叉树的性质:
- 第i层有2^(i-1)个节点
- 深度为k的二叉树至多2^k-1个节点
- 终端节点数为n,度为2的节点数为m,则n=m+1
- 具有n个结点的完全二叉树的深度是(log2N)+1

3.二叉树分类:
- 满二叉树:深度为k且有2^k-1个结点的二叉树
- 完全二叉树:深度为k,有n个结点的二叉树,每个结点的编号与深度为k的满二叉树编号一一对应

4.二叉树的存储结构:
- 顺序结构:按照完全二叉树的编号将其存放在一位数组中标有i-1的分量中。
- 链表结构:typedef struct BitNode{ElemType data; struct BitNode *lchild,*rchild}BitNode;

5.二叉树的遍历:
- 先序(根)遍历
- 中序(根)遍历
- 后序(根)遍历
先根和后根反映的是双亲与孩子节点的关系,中根反映的是兄弟节点之间的左右次序。对于表达式而言,这三种遍历分别前缀表达式(波兰表达式)、中缀表达式和后缀表达式(逆波兰表达式)。

6.二叉树的确定:
- 已知先根和中根遍历可以建立唯一二叉树
- 已知后根和中根遍历可以建立唯一二叉树
- 已知先根和后根遍历不可以建立唯一二叉树

7.二叉树的遍历可以使用递归实现,其非递归中根遍历的算法是(使用栈操作):

8.二叉树从根开始分层从左至右遍历算法是(使用队列操作):

9.线索二叉树:指向前驱或者后继的节点的链成为线索。线索二叉树使用的节点结构为:data、left、right、ltag、rtag。其中ltag(rtag)=0表示子树,=1表示前驱(后继)节点。

10.赫夫曼树又称最优树,是一类带权路径长度(子叶到根的路径个数)最短的树。赫夫曼树的构造算法:赫夫曼算法:
- (1)以权值分别为W1,W2...Wn的n各结点,构成n棵二叉树T1,T2,...Tn并组成森林F={T1,T2,...Tn},其中每棵二叉树 Ti仅有一个权值为 Wi的根结点;
- (2)在F中选取两棵根结点权值最小的树作为左右子树构造一棵新二叉树,并且置新二叉树根结点权值为左右子树上根结点的权值之和(根结点的权值=左右孩子权值之和,叶结点的权值= Wi)
- (3)从F中删除这两棵二叉树,同时将新二叉树加入到F中;
- (4)重复(2)、(3)直到F中只含一棵二叉树为止,这棵二叉树就是Huffman树。

11.赫夫曼树的应用:
- 不同分数段评定优良中差,可以按照分数出现比例为权值构造赫夫曼数,优化程序判断次序
- 赫夫曼编码

第七章 图

1.图的遍历算法:
- 深度优先算法
- 广度优先算法

第八章 动态管理内存

第九章 查找

1.查找算法(详见https://www.cnblogs.com/yw09041432/p/5908444.html)。平均查找长度(Average Search Length,ASL):需和指定key进行比较的关键字的个数的期望值,称为查找算法在查找成功时的平均查找长度。对于含有n个数据元素的查找表,查找成功的平均查找长度为:ASL = Pi*Ci的和。Pi:查找表中第i个数据元素的概率。Ci:找到第i个数据元素时已经比较过的次数。
- (1)顺序表查找:顺序查找:
- 要求:存储结构为顺序存储或者链表存储
- 思想:顺序依次查找
- ASL:(1/n)*(1+2+…+n)=(n+1)/2
- 时间复杂度:O(n)
- (2)二分查找、折半查找:
- 要求:有序顺序存储列表
- 思想:先将查找值与中间值比较,查找不成功折半查找区间
- ASL:log2(n+1)
- 时间复杂度:O(log2n)
- (3)插值查找:
- 要求:有序顺序存储列表
- 思想:基于二分查找算法,将查找点的选择改进为自适应选择(由mid=low+1/2*(high-low)改为mid=low+(key-a[low])/(a[high]-a[low])*(high-low),),可以提高查找效率。
- 时间复杂度:O(log2n)
- (4)斐波那契额查找:
- 要求:有序顺序存储列表
- 思想:依然是对查找点的优化,采用Fibonacci数组,找到对于当前长度的有序表的黄金分割点,作为每次的中间值。
- 时间复杂度:O(log2n)。平均性能,菲波那切查找优于折半查找,最坏情况低于折半查找。
- (5)二叉查找树:
- 要求:需要首先二叉查找树(左子树<根<右子树)
- 思想:先对待查找的数据进行生成树,确保树的左分支的值小于右分支的值,然后在就行和每个节点的父节点比较大小,查找最适合的范围
- 时间复杂度:O(log2n),最坏O(n),原因是没有保持平衡,形成单支树
- (6)平衡二叉树AVL:
- 要求:二叉查找树的基础上,需要进行树的平衡
- 时间复杂度:一直是O(log2n)
- 此外,在此基础上还有2-3树,2-3-4树,B+树,红黑树等。

2.上述算法中:
- 顺序表查找:(1)
- 优点:简单
- 缺点:效率低O(n)
- 有序表查找:(2)/(3)/(4)
- 优点:时间复杂度低O(log2n)
- 缺点:有序表的插入和删除性能是比较差的

第十章 第十一章 排序

1.排序算法的稳定性:经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。例如冒泡排序是稳定的,但是如果交换条件改为a[j].key>=a[j+1].key,就是不稳定的。

2.排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。

3.常见的8种内部排序算法有(详见https://www.cnblogs.com/RainyBear/p/5258483.html):
- 插入排序:将第一个元素看成是有序的序列,之后的元素看成是未排序的序列,然后遍历未排序的序列,将其插入到有序序列中
- 希尔排序:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序
- 选择排序:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 冒泡排序:比较相邻元素,如果前面的大就交换
- 归并排序
- 快速排序
- 堆排序
- 基数排序

第十二章 文件

数据结构(C语言版本)相关推荐

  1. 数据结构(C语言第二版)严蔚敏编,数据结构电子教材,线性表,栈,队列,顺序存储结构,初始化,入栈,出栈,入队,出队,c++

    前言 提示:本篇文章收录严蔚敏编写的数据结构C语言版本 简单介绍一下顺序表,顺序栈,循环队列,的顺序存储结构之间的区别 代码参考严蔚敏编写的<数据结构>,二维码动态演示可扫码可观看. - ...

  2. rsa算法c语言实现_数据结构与算法之线性表-顺序表实现(C语言版本)

    原文托管在Github: https://github.com/shellhub/blog/issues/52 数据结构与算法之线性表-顺序表实现(C语言版本) 前言 数据结构与算法是一个程序员必备的 ...

  3. 快速排序的两种实现方法(c语言版本)

    经过调研发现,对任意无序整数数组,快速排序有两种实现方法,这里简单阐述下思路: 思路一:随意选择一个基准元,一般选择数组的起始元或末尾元,Weiss这本书上特意搞了个算法来选择基准元,--,总之就是基 ...

  4. 十种经典排序算法精粹(c语言版本)

    下面给出这段时间我苦心研究验证过的十种经典排序算法的C语言版本,即下面的排序算法: 插入排序,shell排序,冒泡排序,快速排序,选择排序,堆排序,归并排序,桶排序,基数排序和计数排序.整理出来以作备 ...

  5. 邓公数据结构C++语言版学习笔记1

    1. 对于计算幂2n2^n2n的算法优化 暴力算法时间复杂度O(n)O(n)O(n) __int64 power2BF_I(int n) //幂函数2^n算法(蛮力迭代版),n >= 0{ __ ...

  6. 解读|TARS开源项目发布Go语言版本

    文章转自开源中国 导语:近日,Tars 开源项目在上海发布并开源了 Go 语言版本,其性能与 C++ 版本相当,比 gRPC 的性能高 5 倍. --编者 Tars 是腾讯开源的一款微服务框架,它于去 ...

  7. 解读|TARS开源项目发布Go语言版本 1

    解读|TARS开源项目发布Go语言版本 文章转自开源中国 导语:近日,Tars 开源项目在上海发布并开源了 Go 语言版本,其性能与 C++ 版本相当,比 gRPC 的性能高 5 倍. --编者 Ta ...

  8. 数据结构c语言版入门教材,《数据结构(C语言版)》C语言-教材-数据结构.pdf

    数 据 结 构 ( C 语 言版 ) 孟祥瑞 汤文兵 编著 胡胜利 葛 斌 华东理工大学出版社 内 容 提 要 <数据结构>(C 语言版) 是为"数据结构"课程编写 的 ...

  9. 学生信息管理系统(C语言版本+源码)

    学生信息管理系统(C语言版本) 有需要的可以自行下载 链接:https://download.csdn.net/download/qq_52889967/14955434 源码在后面 java+数据库 ...

  10. zookeeper 学习笔记 (C语言版本)

    1.zookeeper简介 zookeeper是Hadoop的子项目,在大型分布式系统中,zookeeper封装好了一些复杂易出错的服务,提供简单易用的接口,给使用者提供高效稳定的服务.这些服务包括配 ...

最新文章

  1. oracle 日期 extract,ORACLE——EXTRACT() 截取日期时间的函数使用
  2. ubuntu 将 python 设定为python3, pip设定为pip3
  3. GoldenGate系统三:trouble shooting and log
  4. checkpoint_通过Main的Checkpoint Restore加快Java启动速度
  5. 机器学习 量子_量子机器学习:神经网络学习
  6. 跨年操作--new Date()
  7. VS2019优化新鲜出炉:C++后端更新汇总
  8. 2017.9.21 problem a 失败总结
  9. Android学习导航线路
  10. 《精通.Net核心技术》
  11. Rust : ref下的match
  12. 运行 jar 文件_如何运行JAR文件
  13. flask基础根据知了课堂整理
  14. Postgresql的基本操作
  15. 斑马Revit:“BIM等级考试证书”究竟要不要考?
  16. md5算法大作战推html5版本,MD5大作战
  17. LearnOpenGL 模型加载—Assimp
  18. 离散数学证明公式整理
  19. 七大江河水系--黑龙江
  20. 《东周列国志》第七十三回 伍员吹箫乞吴市 专诸进炙刺王僚

热门文章

  1. 亲测可用企业级自动发卡平台PHP系统源码
  2. C++初学者该如何写程序?
  3. Matlab来实现DDS功能
  4. 计算机组成原理——指令格式设计
  5. 网易云镜像仓库选择镜像
  6. JAVA 函数的重载
  7. Spring整合activityMq
  8. JCR分区与中科院分区
  9. VTD-传感器使用小结
  10. Mac 安装 CentOS镜像 及 VMware虚拟机