最大子列和刷题总结:
C++的输入输出,是由iostream库提供的
iostream库定义了以下三个标准流对象:
1. cin,表示标准输入(standard input)的istream类对象。cin使我们可以从设备读入数据。
2. cout,表示标准输出(standard output)的ostream类对象。cout使我们可以向设备输出或者写数据。
3. cerr,表示标准错误(standard error)的osttream类对象。cerr是导出程序错误消息的地方,它只能允许向屏幕设备写数据。
输出主要由重载的左移操作符(<<)来完成,输入主要由重载的右移操作符(>>)完成:
1. >>a表示将数据放入a对象中。
2. <<a表示将a对象中存储的数据拿出。
线性表
顺序表:初始化、插入、删除、查找
//顺序表的定义
typedef int Position;
typedef struct LNode *List;
struct{
ElementType Data[MaxSize];
Position Last;
};
//初始化
List MakeEmpty(){
List L=(List)malloc(sizeof(struct LNode));
L->Last=-1;
return L;
}
//查找表中是否存在某个元素x
#define ERROR -1
Position Find(List L,ElementType x){
Position i=0;
while(i<=L->Last&&L->Data[i]!=x){
i++;
}
if(i>L->Last) return ERROR;
else return i;
}
// 插入
bool Insert(List &L,ElementType x,Position P){
Position i;
if(L->Last==MaxSize-1) return false;
if(P<0||P>MaxSize) return false;
//后面的循环不必考虑范围超过的问题了,可以放心的边找边移动位置
for(i=L->Last;i>P;--i){//i和p都是在利用下标找位置,下标是有序的
L->Data[i+1]=L->Data[i];
}
L->Data[P]=x;
L->Last++;
return true;
}
//删除
bool Delete(List L,Position P){
if(L->Last<0) return false;
if(P<0||P>MaxSize) return false;
Position i;
for(i=P;i>=0;i--){
L->Data[i]=L->Data[i-1];
}
L->Last--;
return true;
}
- 结构类型:数组且有最大容量,指向数组最后一个元素的指针
- 初始化:申请一个结构、让last=-1,返回这个结构
- 查找:传入要查找的值和线性表,用一个循环遍历一遍这个表,条件是在表的范围内找,而且范围内没有找到不符合条件的情况,有两种:1、已经超过了数组范围,就返回没-1 表示没找到2、数组的值和要找的值相等了,说明找到了,返回存储位置也就是数组下标。
- 插入:在第i个位置上插入一个x:判断是否满,数组下标和最大容量-1相等就满了,满则不能插入。判断是否在合法范围内插入,0<=i<=last。然后用一个for循环将从last开始到p位置上的所有值后移一位,插入新元素到p位置,再把last++,返回true表示插入成功
- 删除:判断是否空和检查位置合法性结合在一起了,因为如果插入的位置不在0-last之间的话也就意味着肯定有错,要么是表空要么是超出范围,但是表满和范围判断是不能结合的,因为表满的情况大于超出范围的情况。然后就是把从p+1位置开始所有的元素向前移动一位,并把last减减。
链式表:查找、带头结点插入、带头结点的删除
//链式表结构定义
typedef struct Node *PtrToLNode;
struct LNode{
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
//按值查找
Position Find(List L,ElemenType x){
Position p=L;
while(p&&p->Data!=x){
p=p->Next;
}
if(p->Data==x) return p;
else return -1;
}
//按序号查找
Position FindX(List L,int k){
Position p=L;
int i=1;
while(p&&i<k){
p=p->Next;
i++;
}
if(i==k) return p;
else return -1
}
// 求表长
int Length(List L){
Position p=L;
int i=0;
while(p) {
p=p->next;
i++;
}
return i;
}
//带头结点的插入,在p位置之前插入
bool Insert(List &L,ElementType x,Position p){
Position tmp,pre;
for(pre=L;pre&&pre->Next!=p;p=p->Next);
if(pre->Next==p){
tmp=(Position)malloc(sizeof(struct LNode));
tmp->Data=x;
pre->Next=tmp;
tmp->Next=p;
free(tmp);
return true;
}
}
//带头结点的删除,删掉p指向的节点
bool Delete(List &L,Position p){
Position pre;
if(L->Next==NULL) return false;
for(pre=L;pre&&pre->Next!=p;pre=pre->Next);
if(pre->Next=p){
pre->Next=p->Next;
free(p);
return true;
}
else return false;
}
- 结构类型:数据和next指针
- 查找:
- 按指查找:(定义ERROE为空,则返回ERROR就表示为空,因为return返回的时候是根据函数的返回值类型的,若返回值类型不是bool则不能用0或1来返回,所以定义ERROR。不过这里的返回可以写为returnp;也就是返回找到的值的位置)
- 传入链表和要查找的x
- 定义一个指针指向头
- 用一个循环不断使p=p的next,当p的next是空的就出循环或者p的值就是要找的值就出循环,
- 返回的p有两种可能1、空的2、所找的值所在的位置。
- 按序号查找:
- 传入序号和链表
- 定义一个指针指向头
- 用循环不断判断序号是否相等就一直序号加加,指针后移
- 出了循环代表要么是找到了,要么是表都结束了也没找到,分别返回当前指针和空
- 按指查找:(定义ERROE为空,则返回ERROR就表示为空,因为return返回的时候是根据函数的返回值类型的,若返回值类型不是bool则不能用0或1来返回,所以定义ERROR。不过这里的返回可以写为returnp;也就是返回找到的值的位置)
- 插入:
- 传入:链表,要插入的值,标记当前位置的指针p。
- 用一个for循环查找p的前一个节点:头结点开始,当前节点的前一个节点不空且当前节点的下一个节点不是要找的节点就出循环。
- 出循环的情况有两种,当前节点的前一个节点为空,返回false或者找到了要删除节点的前一个节点
- 申请一个节点,放要插入的节点值和next,然后改指针,返回true
- 求表长
- 传入链表
- 使p指向表的第一个节点,
- 用while循环当p为真时不断下移指针并且i++,
- 返回i可以得到链表的表长。
- 带头结点的删除
- 传入链表和一个指针p用来指向要删除的节点
- 用一个for来找要删除节点的前一个节点pre:
- 开始时指向的是头结点
- 不断后移的指针判断当前节点的next是否与要找的指针相等
- 出循环的条件有两个:找到了要删节点的前一个节点或者表已经走完了没找到
- 判断要找的指针或前一个节点指针是否为空,为空则删除的位置不对
- pre不为空而且next指向要找的节点了,说明找到了,那就改指针然后free(p)返回一个true
王道习题1:设顺序表用数组A[]表示,表中元素存储在数组下标0-m+n-1范围内,前m个元素递增有序,后n个元素也递增有序,设计一个算法,使整个顺序表有序
王道习题2:已知递增有序的单链表AB(分别有mn个元素,且都有头结点),分别存储了一个结合,请设计算法,求连个集合的差集,仅在A中出现的元素构成的集合。将差集保存在A中,并保持有序性
广义表
- 广义表是线性表的推广
- 广义表中的元素不仅可以是单元素也可以是另一个广义表·,用tag的0 1来表示
多重链表
- 链表中的节点可能同时隶属于多个链
- 指针域有多个,如广义表中包含了next和sublist(子表指针域)
- 但包含两个指针域的链表并不一定是多重链表,比如双向链表不是多重链表(指针串起来的是同一个链表,只是指向了不同方向)
- 应用于弥补二维数组的缺陷
- 二维数组的大小要事先确定
- 稀疏矩阵造成的空间浪费
- 采用多重链表-十字链表来存储稀疏矩阵
- 只存储非零项:行列坐标和数值
- 每个节点通过行列指针串起来,属于不同的链
- 节点有两种类型:
-
同行同列的非零项的统计节点term
-
行列的头结点head
-
左上角的特殊表示十字链表的入口表示有多少行有多少列有多少非零项,通过这个节点可以找到所有的行节点和列节点
-
可以用union把这两种统一起来
堆栈
顺序堆:判断空和满,压入和弹出
//定义
typedef struct SNode *Stack;//指向结构的指针 //传入指针最好,是值的传递
typedef int Position;
struct SNode{
ElementType *Data[MaxSize];// *a[]相当于a[0] char*:每个a[i]指向不同的内容
Position Top;
int MaxSize;
};
//初始化
Stack CreateStack(int MaxSize){
Stack S=(Stack)malloc(sizeof(struct SNode));//给堆栈分配空间
S->Data=(ElementType *)malloc(MaxSize*sizeof(ElementType));//给数组分配空间
S->Top=-1;//用->表示指针所指的结构变量中的成员 S所指的结构的top
S->MaxSize=MaxSize;
return S;
}
//判断满
bool IsFull(Stack S){
return (S->Top==S->MaxSize-1);
}
//入栈
bool Push(Stack S,ElementType x){
if(isFull(S)) return false;
else {
S->Data[(S->Top)++]=x;
return true;
}
}
//判断空
bool IsEmpty(Stack S){
return (S->Top==-1);
}
//弹出
Stack Pop(Stack S){
if(IsEmpty(S)) return flase;
else return (S->Data[(S->Top)--]);
}
- 结构类型:数组,栈顶指针,最大容量
- 创建堆栈:
- 传入最大容量
- malloc为数组和数据开辟空间
- 从top=-1也就是数组外面开始此时没有数据
- 让开辟的这个堆栈的大小为传入的最大容量
- 返回堆栈的头指针
- 判断满:返回top与最大容量-1之间的关系,相等则满
- 判断是否入栈成功:
- 传入堆栈和入栈元素,调用判断满的函数用if判断
- 如果满返回false表示入栈失败,否则:先top上移再把x赋值到栈的date
- 判断空:判断top是否==-1,返回真假
- 出栈操作:
- 判断栈空,若空则初战失败,返回ERROR这表示错误,是ElementType的特殊值,
- 否则返回当前的top的值:先对top减减然后取出当前的top所在位置的data值。所以这个函数的返回值类型是elementtype,因为要返回此时的栈顶值
链式堆:单链表,一端进出,只对top操作,top在头上
//定义
typedef struct SNode *PtrToSNode;
typedef PtrToSNode Stack;
struct SNode{
ElementType Data;
PtrToSNode Next;
};
//初始化
Stack CreateStack(){
Stack S=(Stack)malloc(sizeof(struct SNode));
S->Next=NULL;
return S;
}
//判断空
bool IsEmpty(Stack S){
return (S->Next==NULL);
}
//出栈:出栈返回的是出栈元素
#define
ElementType Pop(Stack S){
PtrToStack FirstCell;
ElementType TopElem;
if(IsEmpty(S)) return ERROR;
else{
FirstCell=S->Next;//S是头指针,不是第一个节点
TopElem=FirstCell->Data;//链栈的所有操作都在单链表的表头进行
S->Next=FirstCell->Next;
free(FirstCell);
return TopElem;
}
}
//入栈,没有判断满,因为链表是不会满的
//入栈返回的是,是否成功
bool Push(Stack S,ElementType x){
PtrToStack TmpCell;
TmpCell=(PtrToStack)malloc(sizeof(struct SNode));
TmpCell->Next=S->Next;
S->Next=TmpCell;
TmpCell->Data=x;
return true;
}
- 结构类型:数据、指针
- 创建堆:按照这个堆的结构类型创建一个头结点并分配空间,让头指针的next指向空,并返回该头结点指针
- 判断空:头结点next是否指向空,返回真假
- 入栈:传入 栈和入栈元素,先申请一个节点,给这个节点添加值,然后改指针就可以了
- 出栈:判断堆栈空不空,不空就可以出栈,就是改指针,但是要先把要删除的节点的值存下来,改完指针之后free这个要删的节点