文章标题
来源:互联网 发布:windows找不到cmd.exe 编辑:程序博客网 时间:2024/06/05 05:46
算法:解决特定问题求解步骤的描述
好的算法:时间效率高和存储量低
判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注最高阶项的阶数:输入规模越大,次要项影响越来越小
算法事件复杂度:随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同;O(n) ;(n就是程序语句执行多少次)
对数阶:2的x次方等n,x=O(logn)
int count = 1;while(count < n) count = count * 2;
顺序表,在存、读数据时,不管哪个位置,时间复杂度都是O(1);而插入或删除时,时间复杂度都是O(n)
链表的每个节点中只包含一个指针域:单链表
头指针:链表指向第一个节点的指针,若链表有头节点,则是指向头节点的指针;无论链表是否为空,头指针均不为空;头指针是链表的必要元素
头结点:不一定是链表的必须要素;为了操作的统一和方便而设立的
typedef struct Node{ ElemType data; struct Node* next;}Node;typedef struct Node* LinkList;
单链表的读取(第i个数据)
链表插入:注意要重新申请一个节点的内存空间
链表删除:主要要释放删除节点的内存
头插法:p =(LinkList*)malloc(sizeof(Node)); p -> next = head->next;
head -> next = p;
尾插法: p = (LinkList*) malloc(sizeof(Node)); head -> next = p; head = p;
整表删除:p = head->next; while(p) { q = p->next; free(p); p = q;}
单链表和顺序表:
- 存储方式:用一段连续的存储单元依次存储线性表的数据元素;单链表用一组任意的存储单元存放线性表的元素
- 时间性能:查找:O(1)、O(n);插入和删除:O(n)、O(1)
- 空间性能:顺序存储结构需要预分配空间
静态链表:用数组描述的链表;数组的元素由两个数据域组成:data存放数据元素,cur存放该元素的后继在数组中的下表
#define MAX_SIZE 1000typedef struct{ ElemType data; int cur; }Component,StaticLinkList[MAXSIZE];
数组第一个元素,即下标为0的元素的cur就存放数组空闲空间的第一个元素的下标
数组最后一个元素的cur存放第一个有数值的元素的下表(相当于头结点)
循环链表:将单链表中终端节点指针由空指针改为指向头节点,就使整个单链表形成一个环,这种头尾衔接的单链表称为循环链表
循环链表和单链表的主要差异就在于循环的判断条件上,原来是判断p->next 是否为空,现在则是p->next不等于头结点,则循环未结束
单链表有了头节点,我们可以用O(1)的时间访问第一个节点,但对于要访问最后一个节点,却需要O(n)时间
我们用指向终端结点的尾指针来表示循环链表,此时查找开始节点和终端节点都很方便了:终端节点用read指针指示,查找终端节点:rear;查找开始节点rear->next->next
将两个链表合并成一个表时,有了尾指针也非常简单:已知rearA和rearB
p = rearA->next;rearA ->next = rearB->next->next;rearB->next = p;free(rearB->next);
双向链表:在单链表的每个节点中,再设置一个指向其前驱节点的指针域
单链表根据next指针要查找上一节点的话,最坏的时间复杂度就是O(n),因为每次都要从头开始遍历查找
插入操作:将s节点插入到节点p和p->next之间
s->prior = p;s->next = p->next;p->next ->prior = s;p->next = s;
删除操作:删除节点p
p->prior->next = p->next;p->next->prior = p->prior;
栈:限定仅在表尾进行插入和删除操作的线性表;栈顶和栈底;后进先出
栈的顺序存储结构(需要事先确定数组存储空间大小)
- 数组下标为0的一端作为栈底;
- top栈顶元素在数组中的位置,top必须小于StackSize
空栈:top = -1
typedef int SElemType;typedef struct{ SElemType data[MAXSIZE]; int top; //用于栈顶指针}SqStack;Status Push(SqStack* s,SElemType e){ if(s->top == MAXSIZE-1) return ERROR; s->top++; s->data[s->top] = e; return OK;}Status Pop(SqStack* s, SElemType e){ if(s->top == -1) return ERROR; e = s->data[s->top]; s->top--; return OK;}
栈的链式存储结构:栈顶指针就是指向链表的头部(第一个节点),对于链栈来说,是不需要头节点的。
typedef struct StackNode{ ElemType data; struct StackNode* next;}StackNode,*LinkStackPtr;typedef struct LinkStack{ LinkStackPtr top; int count;}LinkStack;(链栈)Status Push(LinkStack* s,SElemType e){ LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode)); s->data = e; s->next = s->top; s->top = s; s->count++; return OK;}Status Pop(LinkStack* s,SElemType* e){ LinkStackPtr p; if(StackEmpty(*s)) return ERROR; *e = s->top->data; p = s->top; s->top = s->top->next; free(p); s->count--; return OK;}
如果栈的使用过程元素变化不可预料,有时大有时小,那么最好用链栈;反之,栈的大小变化范围在可控范围内,建议使用顺序栈
栈的应用–递归:在前行阶段,对于每一层递归,函数的局部变量、参数值以及返回地址都被压入栈中,在退回阶段,位于栈顶的局部变量、参数值和返回地址被弹出,恢复调用的状态
栈的应用–四则运算表达式:
- 后缀表达式:所有的符号都是在要运算数字的后面出现
- “9+(3-1)X3+10/2”:“931-3*+102/+”
- 规则:从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,已知到最终获得结果
中缀表达式转后缀表达式:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即称为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号,则栈顶元素依次出栈并输出
队列:先进先出;只允许在一端进行插入操作,而在另一端进行删除操作的线性表
为了避免当只有一个元素时,队头和队尾重合使处理变得麻烦,引入两个指针,front指针指向队头元素,rear指针指向队尾元素的下一个位置;当front等于rear时,空队列
循环队列:队列的头尾相接的顺序存储结构
typedef struct{ QElemType data[MAXSIZE]; int front; int rear; }SqQueue;
队列的链式存储结构:其实就是单链表,只不过是尾进头出
队头指针指向链队列的头结点,队尾指针指向终端节点
typedef struct QNode{ QElemType data; struct QNode* next;}QNode,*QueuePtr;
typedef struct
{
QueuePtr front, rear;
}LinkQueue;
串:由零个或多个字符组成的有限序列
查找子串位置
int Index(String s,String t,int pos){ int n = strlen(s); int m = strlen(t); int i = pos; String sub; while(i <= n-m+1) { SubStr(sub,s,i,m); if(StrCompare(sub,t) != 0) { ++i; } else { return i; } } return 0; }
串的模式匹配
从主串“goodgoogle”中找到”google”这个子串的位置:对主串的每一个字符作为子串的开头,与要匹配的字符串进行匹配
int Index(String s,String t,int pos){ int n = strlen(s); int m = strlen(t); int i = pos; int j = 0; while(i < n && j < m) { if(s[i] == t[j]) { i++; j++; } else { i = i-j+1; j = 0; } } if(j>m) return i-m; else return 0; }
树:n个节点的有限集;n=0时称为空树;
在任意一颗非空树中:
- 有且仅有一个特定的称为根的节点
当n>1时,其余节点可分为m个互不相交的有限集T1, T2, T3…..Tm,其中每一个集合本身又是一棵树,并称为根的子树
节点拥有的子树数称为节点的度;度为0的节点称为叶节点;树的度就是树内各节点的度的最大值
- 节点的祖先是从根到该节点所经分支上的所有节点。
- 树中节点的最大层次称为树的深度或高度
如果将树中节点的各子树看成从左到右是有次序的,不能互换的,则称该树为有序树
双亲表示法:每个节点:data(数据域)和parent(指针域:存储该节点的双亲在数组中的下标)
孩子表示法:每个节点有多个指针域,其中每个指针指向一颗子树的根节点
孩子兄弟表示法:设置两个指针:分别指向该节点的第一个孩子和此节点的右兄弟
二叉树:n个结点的有限集合,该集合或者为空集,或者由一个根节点和两颗互不相交的、分别称为根节点的左子树和右子树的二叉树组成
- 每个结点最多有两颗子树,二叉树不存在度大于2的结点
- 左子树和右子树是有顺序的,次序不能颠倒
斜树:所有的结点都只有左子树的二叉树叫左斜树;所有的结点只有右子树的二叉树叫右斜树
满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上
完全二叉树:对一棵具有n个结点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树编号为i的结点在二叉树中位置完全相同
满二叉树一定是一棵完全二叉树,但完全二叉树不一定是满的
二叉树的性质
- 在二叉树的第i层上至多有2的i-1次方个结点
- 深度为k的二叉树至多有2的k次方-1个结点
- 对任何一颗二叉树T,如果其终端节点数为N0,度为2的节点数N2,N0 = N2+1
- 具有n个结点的完全二叉树的深度为[log2n]+1([x]表示不大于x的最大整数)
二叉树的顺序存储结构
- 顺序存储结构一般只用于完全二叉树
二叉树的链式存储结构
data、lchild和rchild
typedef struct BiTNode{ TElemType data; struct BiTNode* lchild,*rchild; }BiTNode,*BiTree;
二叉树的遍历:从根节点出发,按照某种次序依次访问二叉树中所有节点,使得每个结点被访问一次且仅被访问一次
- 前序遍历:若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树
- 中序遍历:若二叉树为空,则空操作返回,否则从根节点开始(注意不是先访问根节点),中序遍历根节点的左子树,然后是访问根节点,最后中序遍历右子树;
- 后序遍历:若二叉树为空,则空操作返回;从左到右先叶子后节点的方式遍历左右子树,最后是访问根节点
前序遍历算法:
void PreOrderTraverse(BiTree T){ if(T == NULL) return; printf("%c\n",T->data); PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); }
中序遍历算法:
void InOrderTraverse(BiTree T){ if(T==UNLL) return NULL; InOrderTraverse(T->lchild); printf("%c",T->data); InOrderTraverse(T->rchild); }
后序遍历算法
void PostOrderTraverse(BiTree T){ if(T==NULL) return; PostOrderTraverse(T->lchild); PostOrderTraverse(T->rchild); printf("%c",T->data); }
- 文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题 文章标题 文章标题 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- Android组件间通讯Eventbus日常使用
- 算法练习(5):Longest Palindromic Substring
- 数据库那点事(Mysql)-1
- 设计模式之命令模式
- 设置页面元素垂直居中的几种方法
- 文章标题
- Android蓝牙4.0BLE与智能设备间的通讯全解析
- 读Spring源码的一些杂乱思绪(三)
- springmvc+mybatis整合
- Session的3种同步方法
- Android 2.0蓝牙使用全解析
- Lock&Condition实现线程同步通信
- Hello Blog
- Spring