1 //陈 2 typedef struct LNode *List;3 struct LNode{4     int Data[MaxSize];//如果放多个元素,这个可改为指针,在初始化中指向数组 5     int Last;6 };7 //严8 typedef struct {9     ElemType *elem;//存储空间基地址   zt:上面用的数组,数组首地址跟指针一样的,但这里没声明大小,初始化时再声明
10     int length;
11 } SqList; 

线性表-顺序表-定义

 1 //陈 2 List MakeEmpty(){3     List PtrL;4     PtrL=(List)malloc(sizeof(struct LNode));5     PtrL->Last=-1;6     return PtrL;7 }8 //严 9 Status InitList(SqList &L){
10     L.elem=new ElemType[MAXSIZE];
11     if(!L.elem)exit(OVERFLOW);  //多了校验分配失败
12     L.length=0;
13     return OK;
14 } 

线性表-顺序表-初始化

 1 //陈 2 int Find(int X,List PtrL){3     int i=0;4     while(i<=PtrL->Last&&PtrL->Data[i]!=X) i++;5     if(i>PtrL->Last) return -1;6     else return i;7 }8 //严 9 int LocateElem(SqList L,ElemType e){
10     for(i=0;i<L.length;i++){
11         if(e==L.elem[i]) return i+1;  //查找成功返回序号
12     }
13     return 0;
14 }
15 //取值
16 //严  获取第i个值,他的数组存储位置是i-1
17 Status GetElem(SqlList &L,int i,ElemType &e){
18     if(i<1||i>L.length) return ERROR;  //判断i值是否合理
19     e=L.elem[i-1];
20     return OK;
21 }

线性表-顺序表-查找

 1 //陈 2 void insert(ElementType X,int i,List PtrL){3     //i表示插入第几个数,他在数组中的位置是i-1 4     int j; 5     if(PtrL->Last==MaxSize-1){6         printf("表满");7         return;8     }9     if(i<1||i>PtrL->Last+2){ //i最小是第1个数字;last初始值是-1,所以加2,严老师初始值是0,所以加1
10         printf("位置不合法");
11         return;
12     }
13     for(j=PtrL->Last;j>=i-1;j--)
14         PtrL->Data[j+1]=PtrL->Data[j];
15     PtrL->Data[i-1]=X;
16     PtrL->Last++;
17     return;
18 }
19 //严
20 Status ListInsert(SqList &L,int i,ElemType e) {
21     if(i<1||i>L.length+1) return ERROR;  //插入位置不合理
22     if(L.length==MAXSIZE) return ERROR;  //表满了
23     for(j=L.length-1;j>=i-1;j--) L.elem[j+1]=L.elem[j];  //后面元素向后移一位
24     L.elem[i-1]=e;  //做插入
25     L.length++;        //长度+1
26     return OK;
27 }

线性表-顺序表-插入

 1 //陈 2 void Delete (int i,List PtrL){3     //i表示删除第几个数,他在数组中的位置是i-1 4     int j;5     if(i<1||i>PtrL->Last+1){  //删的位置不合理 6         printf("不存在");7         return; 8     }9     for(j=i;j<=PtrL->Last;j++)  //元素往前移一位
10         PtrL->Data[j-1]=PtrL->Data[j];
11     PtrL->Last--;
12 }
13 //严
14 Status ListDelete(SqList &L,int i){
15     if(i<1||i>L.length) return ERROR;  //删的位置不合理
16     for(j=i;j<=L.length-1;j++) L.elem[j-1]=L.elem[j];
17     L.length--;
18     return OK;
19 }

线性表-顺序表-删除

 1 //陈2 typedef struct LNode *List;3 struct LNode{4     ElementType Data;5     List Next;6 };7 //严8 typedef struct LNode{9     ElemType data;
10     struct LNode *next;
11 } LNode,*LinkList; //LinkList为指向结构体LNode的指针类型
12
13 //附:陈,求表长
14 int length(List PtrL){
15     int j=0;
16     List p=PtrL;
17     while(p){
18         p=p->Next;
19         j++;
20     }
21     return j;
22 }

线性表-链表-定义

1 //严
2 Status InitList(LinkList &L){
3     L=new LNode;  //生成新节点作为头结点,用头指针,指向头结点
4     L->next=NULL;  //头结点的指针域置空
5     return OK;
6 }

线性表-链表-初始化

 1 //陈 2 List findKth(int K,List PtrL){3     List p=PtrL;4     int i=1;5     while(i<K&&p!=NULL){6         p=p->Next;7         i++;8     }9     if(i==K)return p;
10     else return NULL;
11 }
12 //严
13 Status GetElem(LinkList L,int i,ElemType &e){
14     p=L.next; //p指向首元结点
15     j=1;
16     while(p&&j<i){  //找第i个元素
17         p=p->next;
18         ++j;
19     }
20     if(!p||j>i) return ERROR; //i>n或i<=0,i值不合法,比如i直接取-1,j=1比i大,i就不合法,若i>n,那取到边界外了,p早就为null了
21     e=p->data;
22     return OK;
23 } 

线性表-链表-取值

 1 //陈2 List find(Element X,List PtrL){3     List p=PtrL;4     while(p!=NULL&&p->Data!=X)p=p->Next;5     return p;6 }7 //严8 LNode *LocateElem(LinkList L,ElemType e){  //返回指向LNode类型的指针 9     p=L->next;  //还是指向首元结点
10     while (p&&p->data!=e) p=p->next; //直到p为空或找到
11     return p;
12 } 

线性表-链表-查找

 1 //陈 2 List Insert(ElementType X,int i,List PtrL){3     List p,s;4     if(i==1){ //新节点插在表头       如果有头指针,就不用单独考虑这种了 5         s=(List)malloc(sizeof(struct LNode));6         s->Data=X;7         s->Next=PtrL;8         return s; 9     }
10     p=findKth(i-1,PtrL); //查找第i-1个结点
11     if(p==NULL){  //第i-1个结点不存在
12         return NULL;
13     }else{
14         s=(List)malloc(sizeof(struct LNode));
15         s->Data=X;
16         s->Next=p->Next;
17         p->Next=s;  //新节点插到p结点后面
18         return PtrL;
19     }
20 }
21 //严
22 Status ListInsert(LinkList &L,int i,ElemType e){
23     p=L;j=0;
24     while(p&&j<i-1) { //找到第i-1个元素,并用p指向 ,有头结点,不用单独考虑插到第1位
25         p=p->next;
26         j++;
27     }
28     if(!p||j>i-1) return ERROR;  //与上面获取值一样,校验不合法
29     s=new LNode;
30     s->data=e;
31     s-next=p-next;
32     p->next=s;
33     return OK;
34 }

线性表-链表-插入

 1  //严2  //前插法3  void CreateList_H(LinkList &L,int n){4      L=new LNode;5      L->next=NULL;  //建立带头结点的空链表 6      for(i=0;i<n;i++){  //逆序输入n个值,不断插到头部 7          p=new LNode;8          cin>>p->data;  //给data设置值 9          p->next=L->next;
10          L->next=p;  //头结点不断指向新的首元结点
11      }
12  }
13  //后插法
14  void CreateList_R(LinkList &L,int n){
15      L=new LNode;
16      L-next=NULL;
17      r=L; //r当做尾指针,指向头结点
18     for(i=0;i<n;++i){
19         p=new LNode;
20         cin>>p->data;
21         p->next=NULL;
22         r->next=p;  //新结点p插到尾部
23         r=p;  //尾指针指向尾部
24     }
25  } 

线性表-链表-创建单链表的两种方法-前插法、后插法

 1 //陈 2 List Delete(int i,List PtrL){3     List p,s; //s用来释放空间 ,p是要删除结点的前驱 4     if(i==1){  //删除第1个结点 5         s=PtrL; 6         if(PtrL!=NULL)PtrL=PtrL->Next;7         else return NULL;8         free(s);9         return PtrL;
10     }
11     p=findKth(i-1,PtrL);
12     if(p==NULL)return NULL;  //要删除结点的前一个结点 不存在
13     else if(p->Next==NULL) return NULL; //前一个结点存在,但要删除的结点不存在
14     else{
15         s=p->Next;  //删除第i个结点
16         p->Next=s->Next;
17         free(s);
18         return PtrL;
19     }
20 }
21 //严
22 Status ListDelete(LinkList &L,int i){
23     p=L;  //p是被删结点的前驱
24     j=0;
25     while (!(p->next)&&j<i-1){
26         p=p->next;
27         j++;
28     }
29     if(p->next||j>i-1) return ERROR;  //p-next为空了,或者i值不合法 则退出
30     q=p->next;
31     p->next=q->next;
32     delete q;
33     return OK;
34 }

线性表-链表-删除

 1   //严2   //双向链表的定义3   typedef struct DuLNode{4       ElemType data;5       struct DuLNode *prior;6       struct DuLNode *next;7   } DuLNode ,*DuLinkList;8   9   //双向链表的插入
10   Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
11       //带头结点的双链表L,在第i个位置之前插入e
12       if(!(p=GetElem_DuL(L,i))) return ERROR;  //找到第i个位置的元素p
13       s=new DuLNode;
14       s-data=e;
15       s-next=p;
16       s-prior=p->prior;
17       p->prior->next=s;
18       p->prior=s;
19       return OK;
20   }
21
22   //双向链表的删除
23   Status ListDelete_DuL(DuLinkList &L,int i){
24       //删除 带头结点的双链表L的第i个元素
25       if(!(p=GetElem_DuL(L,i))) return ERROR;  //找到第i个位置的元素p
26        p->prior->next=p->next;
27        p->next->prior=p->prior;
28        delete p;
29        return OK;
30   } 

线性表-链表-双向链表-定义、插入、删除

尾指向头,就是循环链表。

 1 //陈 2 typedef struct SNode *Stack;3 struct SNode{4     ElementType Data[MaxSize];5     int Top;6 };7 //严8 typedef struct{9     SElemType *base;  //栈底指针
10     SElemType *top;  //栈顶指针
11     int stacksize;  //栈可用的最大容量
12 } SqStack; 

线性表-顺序栈-定义

1 //严
2 Status InitStack(SqStack &S){
3     S.base=new SElemType[MAXSIZE];  //为顺序栈,分配一个最大容量为MAXSIZE的数组空间
4     if(!S.base) exit(OVERFLOW);  //分配失败
5      S.top=S.base;  //top初始为base,空栈
6      S.stacksize=MAXSIZE;  //stacksize置为数组最大容量
7      return OK;
8 }

线性表-顺序栈-初始化

 1 //陈 2 void Push(Stack PtrS,ElementType item{3     if(PtrS->Top==MaxSize-1){4         printf("满");5         return;6     }7     PtrS->Data[++(PtrS->Top)]=item;8     return; 9 })
10 ElementType Pop(Stack PtrS){
11     if(PtrS->Top==-1)return ERROR;
12     return PtrS->Data[(PtrS->Top)--];
13 }
14 //严
15 Status Push(SqStack &S,SElemType e){
16     if(S.top-S.base==S.stacksize) return ERROR; //栈满
17     *S.top++=e;  //e压入栈顶,栈顶指针加1
18     return OK;
19 }
20 Status Pop(SqStack &S,SElemType &e){
21     if(S.top==S.base) return ERROR; //栈空
22     e=*--S.top;
23     return OK;
24 }
25 //严,取栈顶元素
26 SElemType GetTop(SqStack S){
27     if(S.top!=S.base)     //栈非空
28         return *(S.top-1);  //不修改栈顶指针,返回栈顶元素值
29 } 

线性表-顺序栈-入栈、出栈

 1 //陈 2 struct DStack{3     ElementType Data[MaxSize];4     int Top1;5     int Top2;6 }; 7 void Push(struct DStack *PtrS,ElementType item,int Tag){8     if(PtrS->Top2-PtrS->Top1==1)return;  //栈满 9     if(Tag==1) PtrS->Data[++(PtrS->Top1)]=item; //对第1个栈操作
10     else        PtrS->Data[--(PtrS->Top2)]=item; //对第2个栈操作
11 }
12 ElementType Pop(struct DStack *PtrS,int Tag){
13     if(Tag==1){
14         if(PtrS->Top1==-1)return NULL; //第1个栈空
15         else return PtrS->Data[(PtrS->Top1)--];
16     }else{
17         if(PtrS->Top2==MaxSize))return NULL; //第2个栈空
18         else return PtrS->Data[(PtrS->Top2)++];
19     }
20 }

线性表-顺序栈-两头生长:定义、入栈、出栈

 1 //陈 2 typedef struct SNode *Stack;3 struct SNode{4     ElementType Data;5     struct SNode *Next;6 };7 //严8 typedef struct StackNode{9     ElemType data;
10     struct StackNode *next;
11 } StackNode,*LinkStack; 

线性表-链栈-定义

 1 //陈 2 Stack CreateStack(){3     Stack S;4     S =(Stack)malloc(sizeof(struct SNode));5     S->Next=NULL;6     return S;7 }8 int isEmpty(Stack S){9     return (S->Next==NULL);
10 }
11 //严
12 Status InitStack(LinkStack &S){
13     S=NULL; //栈没必要设头结点,初始化直接置为空就行
14     return OK;
15 } 

线性表-链栈-初始化

 1 //陈 2 void Push(ElementType item,Stack S){3     struct SNode *TempCell;4     TempCell=(struct SNode *)malloc(sizeof(struct SNode));5     TempCell->Data=item; 6     TempCell->Next=S->Next;7     S->Next=TempCell;//S的位置是栈顶,他总是next指向最顶部的元素   新元素插到头结点S和首元结点S->next之间,像链表的头插法 8 }9 ElementType Pop(Stack S){
10     struct SNode *FirstCell;  //用来释放空间
11     ElementType TopElement;  //返回元素
12     if(isEmpty(S))return NULL;
13     else{
14         FirstCell=S->Next;   //S->Next指向栈顶元素
15         S->Next=FirstCell->Next;
16         TopElement=FirstCell->Data;
17         free(FirstCell);
18         return TopElement;
19     }
20 }
21 //严
22 Status Push(LinkStack &S,SElemType e){
23     p=new StackNode;
24     p->data=e;
25     p->next=S; //因为没设头结点,所以新元素直接指向旧的栈顶元素
26     S=p;    //把新元素作为栈顶
27     return OK;
28 }
29 Status Pop(LinkStack &S,SElemType e){  //删除S的栈顶元素,用e返回其值
30     if(S==NULL) return ERROR;
31     e=S->data;
32     p=S;  //p临时保存栈顶元素空间,以备释放
33     S=S->next;  //修改栈顶指针
34     delete p;
35     return OK;
36 }
37 //严  取栈顶元素
38 SElemType GetTop(LinkStack S){
39     if(S!=NULL) return S->data;
40 } 

线性表-链栈-入栈、出栈

 1 //定义2 //陈3 struct QNode{4     ElementType Data[MaxSize];5     int front;6     int rear;7 };8 typedef struct QNode *Queue;9 //严
10 typedef struct{
11     QElemType *base; //存储空间的基地址
12     int front;  //头指针
13     int rear;  //尾指针
14 } SqQueue;

线性表-顺序队列(就是循环队列)-定义

 1 //初始化2 //严3 Status InitQueue(SqQueue &Q){4     Q.base=new QElemType[MAXQSIZE];  //指针指向新分配的数组基地址 5     if(!Q.base) return ERROR;  //校验分配失败 6     Q.front=Q.rear=0;  //头尾指针置为0,队列为空 7     return OK;8 } 9 //求队列长度
10 int QueueLength(SqQueue Q){
11     return (Q.rear-Q.front+MAXSIZE)%MAXSIZE;
12 } 

线性表-顺序队列(就是循环队列)-初始化

 1 //入队、出队2 //陈 3 void Add(ElementType item,Queue PtrQ){4     if((PtrQ->rear+1)%MaxSize==PtrQ->front)return NULL;  //校验队满 5     PtrQ->rear=(PtrQ->rear+1)%MaxSize;  //队尾+1 6     PtrQ->Data[PtrQ->rear]=item;7 }8 ElementType Delete(Queue PtrQ){9     if(PtrQ->front==PtrQ->rear)return NULL;  //校验队空
10     PtrQ->front=(PtrQ->front+1)%MaxSize;  //队头+1
11     return PtrQ->Data[PtrQ->front];
12 }
13 //严
14 Status EnQueue(SqQueue &Q,QElemType e) {
15     if((Q.rear+1)%MAXSIZE==Q.front) return ERROR;  //校验队满
16     Q.base[Q.rear]=e;
17     Q.rear=(Q.rear+1)%MAXSIZE;  //队尾指针+1
18     return OK;
19 }
20 Status DeQueue(SqQueue &Q,QElemType &e){
21     if(Q.front==Q.rear) return ERROR;  //校验队空
22     e=Q.base[Q.front];
23     Q.front=(Q.front+1)%MAXSIZE;  //队头指针+1
24     return OK;
25 }
26 //取队头元素
27 QElemType GetHead(SqQueue Q){
28     if(Q.front!=Q.rear) return Q.base[Q.front];
29 }

线性表-顺序队列(就是循环队列)-入队、出队

 1 //定义2 //陈 3 struct Node{4     ElementType Data;5     struct Node *Next;6 };7 struct QNode{8     struct Node *front;9     struct Node *rear;
10 };
11 typedef struct QNode *Queue;
12 //严
13 typedef struct QNode{
14     QElemType data;
15     struct QNode *next;
16 } QNode,*QueuePtr;
17 typedef struct {
18     QueuePtr front;
19     QueuePtr rear;
20 } LinkQueue; 

线性表-链队-定义

1 //初始化
2 //严
3 Status InitQueue(LinkQueue &Q){
4     Q.front=Q.rear=new QNode;  //生成新结点作为头结点,队头和队尾指针指向此结点
5     Q.front->next=NULL;  //头结点的指针域置为空
6     return OK;
7 } 

线性表-链队-初始化

 1 //入队、出队2 //陈 3 ElementType Delete(Queue PtrQ){4     Queue FrontCell;  //临时保存出队元素,以备释放 5     ElementType FrontElem;  //保存出队元素的值 6     if(PtrQ->front==NULL)return NULL;  //校验队列为空 7     FrontCell=PtrQ->front;    8     if(PtrQ->front==PtrQ->rear)PtrQ->front=PtrQ->rear=NULL; //若队列只有一个元素,删除后,队列置为空 9     else FrontElem=FrontCell->Data;
10
11     PtrQ->front=PtrQ->front->Next;  //队头+1
12     free(FrontCell);
13     return FrontElem;
14 }
15 //严
16 Status EnQueue(LinkQueue &Q,QElemType e){
17     p=new QNode;  //p是QueuePtr类型,c语言里可以省略强转,强制类型转换是为了兼容c++
18     p->data=e;
19     p->next=NULL;
20     Q->rear->next=p;  //初始化时,队头队尾指向同一个,所以若是第一次入队,这里使Q->front->next也指向了p,p是首元结点,从第二次入队开始,就只是新元素不断加到尾部了
21     Q->rear=p;  //队尾指针后移一位,就是队尾+1
22     return OK;
23 }
24 Status DeQueue(LinkQueue &Q,QElemType &e){
25     if(Q.front==Q.rear) return ERROR;  //校验队列为空
26     p=Q.front->next;  //临时保存出队元素,以备释放
27     e=p->data;
28     Q.front->next=p->next;  //队头+1,若p是最后一个元素,p->next就是NULL,那 Q.front->next也是NULL了
29     if(Q.rear==p) Q.rear=Q.front;  //校验p是否是最后一个元素,若是,尾指针像初始化时一样,重新指向头结点,若不加校验,队头一直指向头结点,但删了首元结点后,又不管队尾指针,队尾就不知道指向谁了
30     delete p;
31     return OK;
32 }
33 //严  取队头元素
34 SElemType GetHead(LinkQueue Q){
35     if(Q.front!=Q.rear) return Q.front->next->data;  //若非空,返回头结点指向的首元结点的值
36 } 

线性表-链队-入队、出队

 1 //串也有顺序存储和链式存储,考虑到效率和算法方便,多采用顺序存储2 //严3 //串的定长顺序存储 4 #define MAXLEN 255  //串的最大长度 5 typedef struct {6     char ch[MAXLEN+1];  //0空置不用,所以长度+1 7     int length;  //串的当前长度 8 } SString; 9 //串的堆式顺序存储
10 typedef struct {
11     char *ch;    //按串长分配存储区,若空串则为NULL
12     int length;  //串的当前长度
13 } HString; 

线性表-串

 1 //广义表2 //陈 3 typedef struct GNode *GList;4 struct GNode{5     int tag;  //标志域:0表示结点是单元素,1表示结点是广义表 6     union{7         ElementType Data;8         GList SubList;  //子表指针域SubList与单元素数据域Data复用,即共用存储空间 9     } URegion;
10     GList Next;  //指向后继结点
11 };
12 //严
13 typedef enum{ATOM,LIST} ElemTag;  //ATOM==0:原子 ; LIST==1:子表
14 typedef struct GLNode{
15     ElemTag tag;  //公共部分,用于区分原子结点和表结点
16     union{        //原子结点和表结点的联合部分
17         AtomType atom;  //atom是原子结点的值域, AtomType由用户定义
18         struct {struct GLNode *hp,*tp;} ptr; //ptr是表结点的指针域,ptr.hp和ptr.tp分别指向表头和表尾
19     };
20 } *GList;  //广义表的头尾链表存储表示 

线性表-广义表

 1 //树用儿子-兄弟表示法,就成了二叉树2 //一般二叉树用顺序存储浪费空间,所以大都用链式存储3 //特殊的二叉树有完美或满二叉树、完全树 。完全树可以用顺序存储4 5  //二叉树顺序存储定义 6 //严7 #define MAXSIZE 100  //二叉树的最大结点数8 typedef TElemType SqBiTree[MAXSIZE]; //0号单元存根结点 9 SqBiTree bt;
10
11  //二叉树链式存储定义
12  //陈
13  typedef struct TreeNode *BinTree;
14  struct TreeNode{
15      ElementType Data;
16      BinTree Left;
17      BinTree Right;
18  };
19  //严
20  typedef struct BiTNode{
21      TElemType data;  //结点数据域
22      struct BiTNode *lchild,*rchild;  //左右孩子指针
23  } BiTNode,*BiTree;
24  

树-二叉树链式存储、顺序存储-定义

 1 //中序-左根右2  //递归 3  //陈 4  void InOrderTraversal(BinTree BT){5      if(BT){6          InOrderTraversal(BT->Left);7          printf("%d",BT->Data);8         InOrderTraversal(BT->Right);9      }
10  }
11  //严
12  void InOrderTraverse(BiTree T){
13      if(T){
14          InOrderTraverse(T->lchild); //中序遍历左子树
15          count<<T->data;            //访问根结点
16          InOrderTraverse(T->rchild); //中序遍历右子树
17      }
18  }
19  //非递归
20  //陈
21  void InOrderTraversal(BinTree BT){
22      BinTree T=BT;  //用T做操作,不改变原树
23      Stack S=CreateStack();  //创建并初始化一个栈,栈是为了回溯
24      while(T||!isEmpty(S)){ //树不空说明这个树结点还有子树未遍历,栈不空说明还有等待回溯的结点
25          while(T){  //一直向左,并把沿途结点压入栈
26              PUSH(S,T);
27              T=T->Left;
28          }
29          if(!isEmpty(S)){
30              T=POP(S);  //结点出栈
31              printf("%d",T->Data);//打印或访问结点
32              T=T->Right;//转向右子树
33          }
34      }
35  }
36  //严
37  void InOrderTraverse(BiTree T){
38      InitStack(S); //创建栈,用来做回溯
39      p=T; //用p做操作,不改变原树
40      q=new BiTNode;   //临时存放根结点数据
41      while(p||!StackEmpty(S)){  //跟陈越老师的一样
42          if(p){  //p非空
43              Push(S,p);  //根指针入栈
44              p=p->lchild;  //根指针已入栈,遍历左子树
45          }else{  //p空
46              Pop(S,q); //出栈
47              count<<q->data;  //访问根结点
48              p=q->rchild;  //遍历右子树
49          }
50      }
51  } 

树-二叉树链式存储-中序遍历

 1  //先序-根左右2   //陈3  void PreOrderTraversal(BinTree BT){4      if(BT){5          printf("%d",BT->Data);6          PreOrderTraversal(BT->Left);7          PreOrderTraversal(BT->Right);8      }9  }
10   //非递归
11  void PreOrderTraversal(BinTree BT){
12      BinTree T=BT;
13      Stack S=CreateStack();
14      while(T||!isEmpty(S)){
15          while(T){
16              printf("%d",T->Data);  //只是访问根结点的代码位置变了
17              PUSH(S,T);
18              T=T->Left;
19          }
20          if(!isEmpty(S)){
21              T=POP(S);
22              T=T->Right;
23          }
24      }
25  }

树-二叉树链式存储-先序遍历

 1 //后序-左右根2  //陈 3  void PostOrderTraversal(BinTree BT){4      if(BT){5          PostOrderTraversal(BT->Left);6          PostOrderTraversal(BT->Right);7          printf("%d",BT->Data);8      }9  }
10  //非递归
11  void PostOrderTraversal(BinTree BT){
12      BinTree T=BT;
13      Stack S=CreateStack();
14      while(T||!isEmpty(S)){
15          while(T){
16              PUSH(S,T);
17              T=T->Left;
18          }
19          if(!isEmpty(S)){
20              T=POP(S);
21              T=T->Right;
22              printf("%d",T->Data);  //只是访问根结点的代码位置变了
23          }
24      }
25  }

树-二叉树链式存储-后序遍历

 1  //层序用的不是栈,而是队列2  //陈 3  void LevelOrderTraversal(BinTree BT){4      Queue Q;  //队列做回溯 5      BinTree T; //临时用来操作树 6      if(!BT)return;  //校验是否为空树 7     Q=CreateQueue(MaxSize);  //创建并初始化队列 8     Add(BT,Q);  //最初是根节点入队 9     while(!IsEmpty(Q)){
10         T=Delete(Q);
11         printf("%d",T->Data);  //访问根节点,下面将左右孩子入队。
12         if(T->Left)Add(T->Left,Q);
13         if(T->Right)Add(T->Right,Q);
14 //提示一下:父弹出时,左右儿子入队;左儿子弹出时,左边两个孙子入队,然后右儿子弹出,右边两个孙子入队;这样总能一层层地访问
15     }
16  } 

树-二叉树链式存储-层序遍历

1  //二叉树的二叉线索存储
2  //严
3   typedef struct BiThrNode{
4       TElemType data;
5       struct BiThrNode *lchild,*rchild;  //左右孩子指针
6       int LTag,RTag; //左右标志
7   }BiThrNode,*BiThrTree ;

树-二叉树链式存储-线索存储

 1 //二叉排序树,也叫二叉搜索树、二叉查找树,比二叉树多了个条件,左小右大2  //定义3  //严4  typedef struct { 5      KeyType key;          //关键字项 6     InfoType otherinfo;  //其他数据项 7 }ElemType;               //每个结点的数据域的类型 8  typedef struct BSTNode{    //二叉排序树的二叉链表存储表示 9      ElemType data;          //每个结点的数据域包括关键字项和其他数据项
10      struct BSTNode *lchild,*rchild; //左右孩子指针
11  } BSTNode,*BSTree;
12  

树-二叉树链式存储-二叉排序树-定义

 1 //创建2  //严3  void CreatBST(BSTree &T){4      T=NULL;  //将二叉排序树T初始化为空 5      cin>>e;  //读输入的数据e 6      while(e.data!=ENDFLAG){  //  ENDFLAG为自定义常量,作为输入结束标志 7          InsertBST(T,e);  //将此结点插入到二叉排序树T中 8          cin>>e;  //继续读输入的数据 9      }
10  } 

树-二叉树链式存储-二叉排序树-初始化

 1  //查找-递归 2  //严3  BSTree SearchBST(BSTree T,KeyType key){4      //在二叉排序树T中,查找关键字等于key的数据元素5     if((!T)||key==T->data.key) return T;  //要么T查完了也没找到,此时T为空,返回空; 要么查找成功,返回该数据元素结点的指针6     else if (key<T->data.key) return  SearchBST(T->lchild,key);  //在左子树中继续查找7     else return SearchBST(T->rchild,key);  //在右子树中继续查找 8  } 9  //陈
10  Position Find(ElementType X,BinTree BST){
11      if(!BST)return NULL;
12      if(X>BST->Data) return Find(X,BST->Right); // 在右子树继续查找
13      else if(X<BST->Data) return Find(X,BST->Left); //在左子树继续查找
14      else return BST;  //查找成功
15  }
16
17  //查找-非递归
18  //陈
19   Position IteraFind(ElementType X,BinTree BST){
20       while(BST){
21           if(X>BST->Data)
22               BST=BST->Right;
23           else if(X<BST->Data)
24               BST=BST->Left;
25           else return BST;
26     }
27     return NULL;
28   }
29
30   //附加
31   //陈
32   //查找最小值,最小值在最左边,这个展示下递归方式实现
33   Position FindMin(BinTree BST){
34       if(!BST)return NULL;
35       else if(!BST->Left)
36       return BST;  //找到最左叶结点返回
37       else
38       return FindMin(BST->Left); //沿左分支继续查找
39   }
40   //查找最大值,最大值在最右边,这个展示下循环方式实现 ,递归和循环都可以用
41   Position FindMax(BinTree BST){
42       if(BST)
43       while(BST->Right) BST=BST->Right;  //沿右分支继续查找,直到最右叶结点
44     return BST;
45   }

树-二叉树链式存储-二叉排序树-查找

 1  //插入2   //陈 3   BinTree Insert(ElementType X,BinTree BST){4       if(!BST){  //树为空,则生成新的 5           BST=malloc(sizeof(struct TreeNode));6           BST->Data=X;7           BST->Left=BST->Right=NULL;8     }else{  //开始找要插入元素的位置 9         if(X>BST->Data) BST->Right=Insert(X,BST->Right); //递归插入右子树
10         else if(X<BST->Data) BST->Left=Insert(X,BST->Left);    //递归插入左子树
11         //否则就是X已存在,什么都不做
12     }
13     return BST;
14   }
15   //严
16   void InsertBST(BSTree &T,ElemType e){
17       if(!T){  //树为空,生成新的
18           S=new BSTNode;
19           S->data=e;
20           S->lchild=S->rchild=NULL;
21           T=S;
22       }else if(e.key<T->data.key) InsertBST(T->lchild,e); //插到左边
23        else if(e.key>T->data.key) InsertBST(T->rchild,e); //插到右边
24   } 

树-二叉树链式存储-二叉排序树-插入

 1   //删除 三种情况,叶结点、1个孩子、2个孩子2   //陈 3   //陈越是用递归实现的 4   BinTree Delete(ElementType X,BinTree BST){5       Position Temp;6       if(!BST);  //要删除的元素未找到,不做处理或打印个提示 7       else if(X>BST->Data) BST->Right=Delete(X,BST->Right); //右子树递归删除 8       else if(X<BST->Data) BST->Left=Delete(X,BST->Left);  //左子树递归删除 9       else  //找到了要删除的结点
10           if(BST->Left&&BST->Right){  //被删除的结点有左右两个子结点
11               Temp=FindMin(BST->Right);  //在右子树中,找到最小的元素,填充删除结点
12               BST->Data=Temp->Data;
13               BST->Right=Delete(BST->Data,BST->Right); //填充后,再删除右子树中那个最小元素
14         }else{  //被删除的结点有一个子结点、或没有子结点
15             Temp=BST;  //临时存放待删结点,以备释放
16             if(!BST->Left) BST=BST->Right;  //左孩子为空,右孩子填充上来
17             else if(!BST->Right) BST=BST->Left; //右孩子为空,左孩子填充上来
18             free(Temp);  //无子结点,那直接释放就行
19         }
20       return BST;
21   }
22   //严
23   //严蔚敏是用循环实现的
24   void  DeleteBST(BSTree &T,KeyType key){
25       p=T;f=NULL;  //p用来临时操作树T,f表示被删结点的父节点
26       while(p){
27           if(key==p->data.key) break;  //从根开始查被删结点key,找到就停止循环
28           f=p;                        //每次都存一下父节点
29           if(key<p->data.key) p=p->lchild;  //小于就去左子树继续找,大于就去右子树继续找
30           else p=p->rchild;
31       }
32     if(!p) return;  //最后没找到被删结点,退出 ,若找到了,分下面三种情况
33     if(p->lchild&&p->rchild){    // 1、被删除的结点有左右两个子结点
34         q=p;  //q临时存放被删结点p
35         s=p->lchild;  //s要成为p左子树的最大值
36         while(s->rchild){  //s一直往右走到头,找到最大值
37             q=s;  //q临时存放最大值的父节点
38             s=s->rchild;
39         }
40         p->data=s->data;  //把最大值s提拔上来,替代被删结点p的值,做善后工作
41         if(q!=p) q->rchild=s->lchild;   //q!=p,说明上面循环走了,q改成s了,那q的右儿子s被提拔了,但s没有右儿子,只有左儿子,s的左儿子就顶上s的位置,哪怕它是null
42         else q->lchild=s->lchild;//若q==p,说明上面循环没走,q还是p,即p的左儿子s被直接提拔上来,s没有右儿子,原来指向s的指针现在指向s的左儿子,对p来讲,左孙成了左儿
43         delete s;//释放
44         return ;  //处理完成,直接退出,这里是修改了p的值,但没有改链表关系,下面是改了链表关系,直接重置p节点指针
45     }else if(!p->rchild){  //2、被删除的结点右孩子为空,左孩子直接上位
46         q=p;  //q临时存放被删结点p
47         p=p->lchild;  //重置p节点指针
48     }else if(!p->lchild){  //3、被删除的结点左孩子为空,右孩子直接上位
49         q=p;  //q临时存放被删结点p
50         p=p->rchild;//重置p节点指针
51     }
52     if(!f) T=p; //能走到这里,说明p节点已被重置。若f==NULL,说明第一个while没走,要删的是根节点,重置后得p作为新树根
53     else if(q==f->lchild) f->lchild=p; //被删结点是其父节点f的左孩子,左孩子重连为重置后得p
54     else f->rchild=p;                     //被删结点是其父节点f的右孩子,右孩子重连为重置后得p
55     delete q;//释放
56   } 

树-二叉树链式存储-二叉排序树-删除

 1 //堆,即优先队列,是特殊队列。取元素按优先级,而非进队顺序;使用完全二叉树结构,分为最大堆、最小堆2 3  //定义4  //陈 5  typedef struct HeapStruct *MaxHeap;6  struct HeapStruct{7      ElemetType *Elements;  //数组空间 8      int Size;  //堆的当前元素个数 9      int Capacity;  //堆的最大容量
10  };
11  //创建
12  MaxHeap Create(int MaxSize){
13      MaxHeap H=malloc(sizeof(struct HeapStruct));
14      H->Elements=malloc((MaxSize+1)*sizeof(ElementType));  //申请容量为MaxSize的数组空间
15      H->Size=0;
16      H->Capacity=MaxSize;
17      H->Elements[0]=MaxData;  //定义哨兵为大于堆中所有可能元素的值,便于以后更快操作
18                              //把MaxData换成小于堆中所有元素的MinData,同样适用于创建最小堆
19      return H;
20  } 

树-二叉树顺序存储-堆-定义、创建

 1  //最大堆为例2  //插入3  void Insert(MaxHeap H,ElementType item){4      int i;5      if(IsFull(H))return;  //最大堆已满,退出 6      i=++H->Size;  //i指向插入后堆中最后一个元素的位置 7      for(;H->Elements[i/2]<item;i/=2)  //H->Element[ 0 ] 是哨兵元素,它不小于堆中的最大元素,控制顺环结束。i最小为1 8       H->Elements[i]=H->Elements[i/2];//向下过滤结点,并在此过程中交换数据 9      H->Elements[i]=item; //将item插入
10  }
11
12  //删除
13  ElementType DeleteMax(MaxHeap H){
14      ElementType MaxData,Temp; //分别存堆顶元素,堆尾元素
15      int Parent,Child;  //这两个值用来一层层向下过滤,保证每层左右较大子结点成为父节点
16     if(IsEmpty(H))return;  //最大堆已空,退出
17     MaxData=H->Elements[1]; //取出堆顶
18     Temp=H->Elements[H->Size--]; //取出堆尾
19     for(Parent=1;Parent*2<=H->Size;Parent=Child){ //从第一层开始向下层走
20         Child=Parent*2;   //child代表来到下一层,再次循环时,进入的是上次较大子树的下一层,2就到4,3就到6,到6就不用管4、5那些值,因为4、5拼爹没拼过6、7
21         if(Child!=H->Size&&(H->Elements[Child]<H->Elements[Child+1])) Child++; //child代表左右子结点的较大者
22         if(Temp>=H->Elements[Child]) break;//走到最后一个节点了,结束循环,跳出循环,在最后一步让堆尾元素提拔为父节点
23         else H->Elements[Parent]=H->Elements[Child];//还有子树,让当前子树的左右孩子较大值者提拔为父节点,继续下次循环,进入被提拔者的下一层,比较它左右子树较大者
24     }
25     H->Elements[Parent]=Temp;//独子直接当爹,或者小儿子放左边
26     return MaxData;
27  }
28  //通俗一点讲,就是让大儿子当爹,大孙子当大儿子,依次类推直到最后一个子树,
29  //如果最后一个树有俩儿子,左儿子大,去当爹,右儿子要放左边
30  //如果最后一个树有一儿子,那他直接当爹
31  //找个实际的例子模拟一遍就明白了 

树-二叉树顺序存储-堆-插入、删除

 1 //最优二叉树,也叫哈夫曼树。带权路径长度(WPL)最小的二叉树2 //定义3 //陈  链式存储 4 typedef struct TreeNode *HuffmanTree;5 struct TreeNode{6     int weight;7     HuffmanTree Left,Right;8 }; 9 //严  顺序存储
10 typedef struct {
11     int weight;  //结点的权值
12     int parent,lchild,rchild;//结点的双亲、左右孩子下标
13 } HTNode,*HuffmanTree; //动态分配数组存储 

树-二叉树顺序、链式存储-哈夫曼树-定义

 1 //构造2 //陈 3 HuffmanTree Huffman(MinHeap H){//假设最小堆里的值就是权值,把最小堆改成哈夫曼树4     HuffmanTree T;5     int i;6     for(i=1;i<H->Size;i++){ //若3个值,做2次合并 7         T=malloc(sizeof(struct TreeNode));  8         T->Left=DeleteMin(H);  //从最小堆中删除一个节点,作为新T的左子结点 9         T->Right=DeleteMin(H); //从最小堆中删除一个节点,作为新T的右子结点
10         T->weight=T->Left->weight+T->Right->weight; //计算新权值
11         Insert(H,T); //将新T插入最小堆
12     }
13     T=DeleteMin(H);
14     return T;
15 }
16 //严
17 void CreateHuffmanTree(HuffmanTree &HT,int n){
18     if(n<=1) return ;  //
19     m=2*n-1;
20     HT=    new HTNode[m+1]; //申请2n个单元的数组空间,其中0号单元未用
21     for(i=1;i<=m;i++){  //从1到2n-1所有单元中的父节点、左孩子、右孩子,初始化为0
22         HT[i].parent=0;
23         HT[i].lchild=0;
24         HT[i].rchild=0;
25     }
26     for(i=1;i<=n;++i){  //输入前n个单元叶子节点的权值
27         cin>>HT[i].weight;
28     }//初始化完成
29     for(i=n+1;i<m;++i){ //m=2n-1,此循环是从1到n-1 ,将两个节点权值和,作为新节点权值存到数组n+1之后的单元中
30         Select(HT,i-1,s1,s2);//在已初始化的数组HT中,选择两个父节点为0且权值最小的结点,并返回他们在HT中的序号s1和s2
31         HT[s1].parent=i;  //新节点存到n+1之后单元中
32         HT[s2].parent=i;
33         HT[i].lchild=s1;  //记录新节点的左右儿子
34         HT[i].rchild=s2;
35         HT[i].weight=HT[s1].weight+HT[s2].weight;  //记录新节点的权重值
36     }
37 } 

树-二叉树顺序、链式存储-哈夫曼树-构造

 1 //定义2 //严 3 //邻接矩阵存储,图没有顺序存储结构,但可以用二维数组表示元素之间关系4 5 #define MVNum 100  //最大顶点数 6 typedef char VerTexType;  //假设顶点数据类型为字符型 7 typedef int ArcType;    //假设边的权值类型为整型 8 typedef struct{9     VerTexType vexs[MVNum];  //顶点表,用一维数组存储
10     ArcType arcs[MVNum][MVNum];  //邻接矩阵,表示顶点间的关系,用二维数组表示
11     int vexnum,arcnum;   //图的当前顶点数和边数
12 } AMGraph;

图-邻接矩阵表示-定义

 1 //严2 #define MaxInt 32767  //表示极大值,即无穷 3 4  Status CreateUDN(AMGraph &G){  //用邻接矩阵表示法,创建无向图5      cin>>G.vexnum>>G.arcnum;   //输入总顶点数、总边数 6      for(i=0;i<G.vexnum;++i) 7          cin>>G.vexs[i];  //按总顶点数,依次输入顶点信息 8          9      for(i=0;i<G.vexnum;++i)
10          for(j=0;j<G.vexnum;++j)
11              G.arcs[i][j]=MaxInt;  //初始化邻接矩阵,边的权值均置为极大值MaxInt
12
13      for(k=0;k<G.arcnum;++k){  //按总边数,构造邻接矩阵
14          cin>>v1>>v2>>w;  //输入一条边依附的顶点及权值
15          i=LocateVex(G,v1);
16          j=LocateVex(G,v2);  //确定v1,v2在G中的位置,即顶点的数组下标
17          G.arcs[i][j]=w;  //边<v1,v2>的权值置为w
18          G.arcs[j][i]=G.arcs[i][j]; //置<v1,v2>的对称边<v2,v1>的权值为w
19      }
20      return OK;
21  }
22 //陈
23 //无向图的邻接矩阵是对称的,可以只留上三角或下三角,用一维数组存储,数组下标是和=(i*(i+1)/2+j),数组值是权重——适合稠密图 

图-邻接矩阵表示-创建

 1 //定义 2 //严3 #define MVNum 100  //最大顶点数 4 typedef struct ArcNode{  //边结点 5     int adjvex;                //该边所指向的顶点位置 6     struct ArcNode *nextarc;  //指向下一条边的指针 7     OtherInfo info;              //和边相关的信息 8 } ArcNode;9 typedef struct VNode{  //顶点信息
10     VerTexType data;
11     ArcNode * firstarc;  //指向第一条依附该顶点的边的指针
12 } VNode,AdjList[MVNum];  // AdjList表示邻接表类型
13 typedef struct {    //邻接表
14     AdjList vertices;
15     int vexnum,arcnum;  //图的当前顶点数和边数
16 } ALGraph;  //总之就是,邻接表里存放顶点数组,数组里每个顶点元素包含多条边的链式指针。

图-链式存储-邻接表-定义

 1 //创建2 //严 3 Status CreateUDG(ALGraph &G){ // 用邻接表表示法,创建无向图 4     cin>>G.vexnum>>G.arcnum;  //还是输入总顶点数、总边数 5     for(i=0;i<G.vexnum;++i){  6         cin>>G.vertices[i].data;  //还是按总顶点数,依次输入顶点信息  7         G.vertices[i].firstarc=NULL;  //每个顶点的首条边初始化为null 8     }9     for(k=0;k<G.arcnum;++k){// 还是按总边数,构造邻接表
10         cin>>v1>>v2;    //还是输入一条边依附的两个顶点
11         i=LocateVex(G,v1);
12         j=LocateVex(G,v2);  //还是确定v1,v2在G中的位置,即顶点在G.vertices中的序号
13
14         p1=new ArcNode;  //生成一个新的边结点*p1
15         p1->adjvex=j;    //邻结点序号为j
16         p1->nextarc=G.vertices[i].firstarc;
17         G.vertices[i].firstarc=p1;  //将新节点*p1插入顶点vi的边表头部
18
19         p2=new ArcNode;  //生成另一个对称的新的边结点*p2
20         p2->adjvex=i;     //邻接点序号为i
21         p2->nextarc=G.vertices[j].firstarc;
22         G.vertices[j].firstarc=p2;  //将新节点*p2插入顶点vj的边表头部
23     }
24     return OK;
25 }
26 //陈:邻接表,用指针数组存储,只存非零 ——适合稀疏图 

图-链式存储-邻接表-创建

图的链式存储有邻接表、十字链表、邻接多重表,后两种991大纲不考,不列代码。

 1 //陈 2 void DFS(Vertex X){3     Visited(V)=true; // Vertex是顶点集合,E是边集合,V,W是一对顶点,(V,W)是一条边 4     for(V的每个邻接点W) 5         if(!Visited(W)) //若邻接点为空 6             DFS(W); 7 }8 //严9 //遍历连通图
10  bool visited[MVNum];  //访问标志数组,其初始值为false
11  void DFS(Graph G,int v){  //从第v个顶点出发,递归地深度优先遍历图G
12      cout<<v;    //访问第v个顶点
13      visited[v]=true;  //访问到就把它的标志数组值置为true
14      for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w))  //依次检查v的所有邻接点w, FirstAdjVex(G,v)表示v的第一个邻接点;NextAdjVex(G,v,w)表示v相对w的下一个邻接点,w>=0表示存在邻接点
15          if(!visited[w])  //若邻接点未访问
16              DFS(G,w);  //对邻接点递归调用DFS
17  }

图-搜索-深度优先搜索DFS-连通图

1 //严
2 //遍历非连通图
3  void DFSTraverse(Graph G){
4      for(v=0;v<G.vexnum;++v)
5          visited[v]=false;  //把标志数组初始化
6      for(v=0;v<G.vexnum;++v)  //访问每个顶点
7          if(!visited[v])        //对未访问过的顶点,调用遍历连通图
8              DFS(G,v);
9  }

图-搜索-深度优先搜索DFS-非连通图

1 //严
2  //用邻接矩阵表示
3  void DFS_AM(AMGraph G,int v){  //图G为邻接矩阵类型,从第v个顶点出发,深度优先搜索遍历图G
4      cout<<v;          //访问第v个顶点
5      visited[v]=true;  //并把它的标志数组值置为true
6      for(w=0;w<G.vexnum;w++)  //依次检查邻接矩阵中,顶点v所在的行
7          if(G.arcs[v][w]!=0&&!visited[w])  //G.arcs[v][w]!=0表示w是v的邻接点,如果w未访问,则递归调用DFS
8              DFS(G,w);
9  } 

图-搜索-深度优先搜索DFS-邻接矩阵

 1 //严 2  //用邻接表表示 3  void DFS_AL(ALGraph G,int v){  //图G为邻接矩阵类型,从第v个顶点出发,深度优先搜索遍历图G4      cout<<v;          //访问第v个顶点5      visited[v]=true;  //并把它的标志数组值置为true6      p=G.vertices[v].firstarc;  //p指向v的边链表的第一个边结点 7      while(p!=NULL){               //边结点非空 8          w=p->adjvex;           //w是v的邻接点 9          if(!visited[w])
10              DFS_AL(G,w);         //若w未访问,则递归调用DFS_AL
11          p=p->nextarc;           //p指向下一个边结点
12      }
13  } 

图-搜索-深度优先搜索DFS-邻接表

 1 //陈 2 void BFS(Vertex X){3     Visited(V)=true;4     Enqueue(V,Q); //把初始点放入队列5     while(!IsEmpty(Q)) {6         V=Dequeue(Q);7         for(V的每个邻接点W)8             if(!Visited(W)){9                 Visited(W)=true;
10                 Enqueue(W,Q); //把每个邻接点都放入队列,下次找邻接点的邻接点,一层层向外
11             }
12     }
13 }
14 //严
15 void BFS(Graph G,int v){  //按广度优先,非递归遍历连通图G
16     cout<<v;                //访问第v个顶点
17     visited[v]=true;        //并把它的标志数组值置为true
18     InitQueue(Q);            //辅助队列Q初始化,置空
19     EnQueue(Q,v);            //v进队
20     while(!QueueEmpty(Q)){  //队列非空
21         DeQueue(Q,u);        //队头元素出队并置为u
22         for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w)) //依次检查u的所有邻接点w, FirstAdjVex(G,u)表示u的第一个邻接点;NextAdjVex(G,u,w)表示u相对w的下一个邻接点,w>=0表示存在邻接点
23             if(!visited[w]){  //w为u的尚未访问的邻接顶点
24                 cout<<w;     //访问w
25                 visited[w]=true; //把它的标志数组值置为true
26                 EnQueue[Q,w];  //w进队
27             }
28     }
29 } 

图-搜索-广度优先搜索BFS-连通图

 1 //最小生成树 MST Minimum Spanning Tree ,就是权重之和最小的,连通各顶点边,组成的集合。2 //思路是每一步都是当前最优的解,但不能保证总体是最优的。这叫贪心算法3 4 //Prim  从起点开始,不断找连通起点的,权重最小的边,和它对应的顶点,加入集合,直到所有的顶点都加进来5 //陈 6  void Prim(){7      MST={s};8      while(1){9          V=未收录顶点中dist最小值;
10         if(这样的V不存在)break; //说明全搞完了
11         将V收录进MST:dist[V]=0;
12         for(V的每个邻接点W){
13             if(dist[W]!=0){
14                 if(E(V,W)<dist[W]){
15                     dist[W]=E(V,W);
16                     parent[W]=V;
17                 }
18             }
19         }
20      }
21      if(MST中收录的顶点不足V个) Error;
22  }
23
24  //严
25  struct {  //定义辅助数组,用来记录从顶点集U到V-U的权值最小的边
26      VerTexType adjvex;  //最小边在U中的那个顶点
27     ArcType lowcost;   //最小边上的权值
28  } closedge[MVNum];
29
30  //无向网G以邻接矩阵形式存储,从顶点u出发构造G的最小生成树T,输出T的各条边
31  void MiniSpanTree_Prim(AMGraph G,VerTexType u){
32      k=LocateVex(G,u);         //k为顶点u的下标
33     for(j=0;j<G.vexnum;++j) //对V-U的每一个顶点vj,初始化closedge[j]
34         if(j!=k)
35             closedge[j]={u,G.arcs[k][j]}  //{adjvex,lowcost}
36     closedge[k].lowcost=0;                //初始,U={u}
37     for(i=1;i<G.vexnum;++i){            //选择其余n-1个顶点,生成n-1条边(n=G.vexnum)
38         k=Min(closedge);                //求出T的下一个结点:第k个顶点,closedge[k]中存有当前最小边
39         u0=closedge[k].adjvex;            //u0为最小边的一个顶点,u0∈U
40         v0=G.vexs[k];                    //v0为最小边的另一个顶点,v0∈V-U
41         cout<<u0<<v0;                    //输出当前的最小边(u0,v0)
42         closedge[k].lowcost=0;            //第k个顶点并入U集
43         for(j=0;j<G.vexnum;++j)
44             if(G.arcs[k][j]<closedge[j].lowcost) //新顶点并入U后重新选择最小边
45                 closedge[j]={G.vexs[k],G.arcs[k][j]};
46     }
47  } 

图-应用-最小生成树-Prim

 1  // Kruskal  将边按权值大小添加到图中,别形成环,直到所有顶点都连通2  //陈 3  void Kruskal(Graph G){4      MST={};5      while(MST中不到V-1条边&&E中还有边){6          从E中取一条权重最小的边E(V,W); //最小堆7          将E(V,W)从E中删除;8          if(E(V,W)不在MST中构成回路){9              将E(V,W)加入MST;
10          } else{
11              彻底无视E(V,W);
12          }
13     }
14     if (MST中不到V-1条边) Error;
15  }
16
17  //严
18  struct {  //定义辅助数组,存储边的信息,包括边的两个顶点信息和权值
19      VerTexType Head;    //边的始点
20      VerTexType Tail;    //边的终点
21      ArcType lowcost;    //边上的权值
22  } Edge[arcnum];
23  int Vexset[MVNum];        //表示该顶点所在的连通分量
24
25  void MiniSpanTree_Kruskal(AMGraph G){
26 //无向网G以邻接矩阵形式存储,构造G的最小生成树T,输出T的各条边
27     Sort(Edge);                            //将数组Edge中的元素按权值从小到大排序
28     for(i=0;i<G.vexnum;++i)    Vexset[i]=i;//辅助数组,表示各顶点自成一个连通分量
29     for(i=0;i<G.arcnum;++i){            //依次查看数组Edge中的边
30         v1=LocateVex(G,Edge[i].Head);    //v1为边的始点Head的下标
31         v2=LocateVex(G,Edge[i].Tail);    //v2为边的终点Tail的下标
32         vs1=Vexset[v1];                    //获取边Edge[i]的始点所在的连通分量vs1
33         vs2=Vexset[v2];                    //获取边Edge[i]的终点所在的连通分量vs2
34         if(vs1!=vs2){                    //边的两个顶点分属不同的连通分量
35             cout<<Edge[i].Head<<Edge[i].Tail; //输出此边
36             for(j=0;j<G.vexnum;++j)        //合并vs1和vs2两个分量,即两个集合统一编号
37                 if(Vexset[j]==vs2) Vexset[j]=vs1; //集合编号为vs2的都改成vs1
38         }
39     }
40  } 

图-应用-最小生成树-Kruskal

 1 //最短路径问题2 //单源-无权-BFS3 //单源-有权-BFS-Dijkstra算法 4 //数组下标代表各点,值为源点到当前点最短权重值,数组中找最小,然后添加点到T,找出度该改值就改;再找没找过的最小,……  5 //上面博客的理解,跟下面老师的逻辑是一样的 6 7 //陈 8 void Dijkstra(Vertex s){9     while(1){
10         V=未收录顶点中dist最小者;
11         if(这样的V不存在) break; //说明所有点都搞完了
12         collected[V]=true;//处理点
13         for(V的每个邻接点W)
14             if(collected[W]==false) //这个点没被处理过
15                 if(dist[V]+E<v,w><dist[W]){ //源点到这里的权值跟目前数组的值比是不是小
16                     dist[W]=dist[V]+ E<v,w>; //是就改值
17                     path[W]=V;
18                 }
19     }
20 }
21
22 //严
23 void ShortestPath_DIJ(AMGraph G,int v0){
24 //用 Dijkstra 算法求有向网G的v0顶点到其余顶点的最短路径
25     n=G.vexnum;                        //n为G中顶点的个数
26     for(v=0;v<n;++v){                //n个顶点依次初始化
27         S[v]=false;                    //S初始为空集
28         D[v]=G.arcs[v0][v];            //将v0到各个终点的最短路径长度初始化为弧上的权值
29         if(D[v]<MaxInt) Path[v]=v0;    //如果v0和v之间有弧,则将v的前驱置为v0
30         else Path[v]=-1;            //如果v0和v之间无弧,则将v的前驱置为-1
31     }
32     S[v0]=true;                        //将v0加入S
33     D[v0]=0;                        //源点到源点的距离为0
34     //初始化结束,开始主循环,每次求得v0到某个顶点v的最短路径,将v加到S集
35     for(i=1;i<n;++i){                //对其余n-1个顶点,依次进行计算
36         min=MaxInt;
37         for(w=0;w<n;++w)
38             if(!S[w]&&D[w]<min){
39                 v=w;
40                 min=D[w];            //选择一条当前的最短路径,终点为v
41             }
42         S[v]=true;                    //将v加入S
43         for(w=0;w<n;++w){            //更新从v0出发到集合V-S上所有顶点的最短路径长度
44             if(!S[w]&&(D[v]+G.arcs[v][w]<D[w])){
45                 D[w]=D[v]+G.arcs[v][w];//更新D[w]
46                 Path[w]=v;            //更新w的前驱为v
47             }
48         }
49     }
50 } 

图-应用-最短路径-Dijkstra

 1 //多源-Floyd算法  S矩阵存两点权重距离,P矩阵存他们过哪个点连在一起的,S矩阵和P矩阵都是延对角线对称,因此只看一半就行 2 //”a[i][j]的距离” > “a[i][0]+a[0][j]”(a[i][0]+a[0][j]表示”i与j之间经过第1个顶点的距离”)3 //意思是  这两点现在的距离,如果过 第一个点0的距离比现有距离更短,那就把更短距离更新进S矩阵,然后把他们经过的这个点0,写进P矩阵 4 //陈 5 void Floyd(){6     for(i=0;i<N;i++)7         for(j=0;j<N;j++){8             D[i][j]=P[i][j];9             path[i][j]=-1;
10         }
11     for(k=0;k<N;k++)
12         for(i=0;i<N;i++)
13             for(j=0;i<N;i++)
14                 if(D[i][k]+D[k][j]<D[i][j]){
15                     D[i][j]=D[i][k]+D[k][j];
16                     path[i][j]=k;
17                 }
18 }
19 //严
20 void ShortestPath_Floyd(AMGraph G){
21 //用Floyd算法求有向网G中各对顶点i和j之间的最短路径
22     for(i=0;i<G.vexnum;++i)            //各对结点之间初始已知路径及距离
23         for(j=0;j<G.vexnum;++j){
24             D[i][j]=G.arcs[i][j];
25             if(D[i][j<MaxInt]) Path[i][j]=i;//如果i和j之间有弧,则将j的前驱置为i
26             else Path[i][j]=-1;                //如果i和j之间无弧,则将j的前驱置为-1
27         }
28     for(k=0;k<G.vexnum;++k)
29         for(i=0;i<G.vexnum;++i)
30             for(j=0;j<G.vexnum;++j)
31                 if(D[i][k]+D[k][j]<D[i][j]){//从i经k到j的一条路径更短
32                     D[i][j]=D[i][k]+D[k][j];//更新 D[i][j]
33                     Path[i][j]=Path[k][j];    //更改j的前驱为k
34                 }
35 } 

图-应用-最短路径-Floyd

 1 //有向无环图  Directed Acyclic Graph简称DAG,有方向的,没有首尾相连的图2 //AOV网,顶点活动网(Activity On Vertex network),顶点表示活动、边表示活动间先后关系的有向图 3 //AOV是DAG, 首尾相连就没有起点了,也没有顺序,且会死循环 4 //AOV中所有活动组成线性序列,叫做拓扑序列Topological order,5 //由AOV构造 拓扑序列的过程叫做拓扑排序Topological sort6 //两种算法可实现拓扑排序 7 8 //陈 9 //Kahn算法  有向图中选个没有前驱的顶点,删除他和他的所有边,放入栈,重复此步骤直到所有顶点入栈,栈中就是个线性序列
10 void TopSort(){
11     for(cnt=0;cnt<V;cnt++){
12         V=未输出的,入度为0的顶点;
13         if(这样的V不存在){
14             图中有回路;
15             break;
16         }
17         输出V,或者记录V的输出序号;
18         for(V的每个邻接点W) Indegree[W]--;
19     }
20 }
21 //基于DFS的拓扑排序算法 它每次都沿着一条路径一直往下搜索,知道某个顶点没有了出度时,就停止递归,往回走
22 //此算法可以用来检测有向图是否DAG
23 void TopSort(){
24     for(图中每个顶点V)
25         if(Indegree[V]==0) Enqueue(V,Q); //随时将入度变为0的顶点放入一个容器
26     while(!isEmpty(Q)){
27         V=Dequeue(Q);
28         输出V,或者记录V的输出序号; cnt++
29         for(V的每个邻接点W){
30         if(--Indegree[W]==0) Enqueue(W,Q);//入度为0的放入容器
31     }
32     if(cnt!=V) Error(图中有回路);
33 }
34
35 //严
36 Status TopologicalSort(ALGraph G,int topo[]){
37 //有向图G采用邻接表存储结构
38 //若G无回路,则生成G的一个拓扑序列topo[]并返回OK,否则ERROR
39     FindInDegree(G,indegree);        //求出各顶点的入度存入数组indegree中
40     InitStack(S);                    //栈S初始化为空
41     for(i=0;i<G.vexnum;++i)
42         if(!indegree[i]) Push(S,i); //入度为0者进栈
43     m=0;                            //对输出顶点计数,初始为0
44     while(!StackEmpty(S)){            //栈S非空
45         Pop(S,i);                    //将栈顶顶点vi出栈
46         topo[m]=i;                    //将vi保存在拓扑序列数组topo中
47         ++m;                        //对输出顶点计数
48         p=G.vertices[i].firstarc;    //p指向vi的第一个邻接点
49         while(p!=NULL){
50             k=p->adjvex;            //vk为vi的邻接点
51             --indegree[k];            //vi的每个邻接点的入度减1
52             if(indegree[k]==0) Push(S,k); //若入度减为0,则入栈
53             p=p->nextarc;            //p指向顶点vi下一个邻接结点
54         }
55     }
56     if(m<G.vexnum) return ERROR;    //该有向图有回路
57     else return OK;
58 }

图-应用-拓扑排序AOV

 1 //关键路径   AOE-网(Activity On Edge) 2 //与AOV-网对应,它是以边表示活动的网。带权的有向无环图。3 //顶点表示事件,弧表示活动,权表示活动持续的时间。通常用来估算工程的完成时间4 5 //严6 Status CriticalPath(ALGraph G)7 {//G为邻接表存储的有向网,输出G的各项关键活动 8    if(!TopologicalOrder(G,topo)) return ERROR;  9    //调用拓扑排序算法,使拓扑序列保存在topo中,若调用失败,则存在有向环,返回ERROR
10    n=G.vexnum;                       //n为顶点个数
11    for(i=0;i<n;i++)                  //给每个事件的最早发生时间置初值0
12      ve[i]=0;
13 /*- - - - - - - - - -  - 按拓扑次序求每个事件的最早发生时间 - - - -  - - - - - -*/
14    for(i=0;i<n;i++)
15    {
16       k=topo[i];                    //取得拓扑序列中的顶点序号k
17       p=G.vertices[k].firstarc;     //p指向k的第一个邻接顶点
18       while(p!=NULL)
19       {                             //依次更新k的所有邻接顶点的最早发生时间
20          j=p->adjvex;               //j为邻接顶点的序号
21          if(ve[j]<ve[k]+p->weight)  //更新顶点j的最早发生时间ve[j]
22             ve[j]=ve[k]+p->weight;
23           p=p->nextarc;             //p指向k的下一个邻接顶点
24        }                            //while
25    }                                //for
26    for(i=0;i<n;i++)                 //给每个事件的最迟发生时间置初值ve[n-1]
27       vl[i]=ve[n-1];
28 /*- - - - - - - - - - - - -按逆拓扑次序求每个事件的最迟发生时间- -- - - - - -  - - - - - -*/
29    for(i=n-1;i>=0;i--)
30    {
31       k=topo[i];                   //取得拓扑序列中的顶点序号k
32       p=G.vertices[k].firstarc;    //p指向k的第一个邻接顶点
33       while(p!=NULL)               //根据k的邻接点,更新k的最迟发生时间
34       {
35          j=p->adjvex;              //j为邻接顶点的序号
36          if(vl[k]>vl[j]-p->weight) //更新顶点k的最迟发生时间vl[k]
37             vl[k]=vl[j]-p->weight;
38           p=p->nextarc;            //p指向k的下一个邻接顶点
39       }                            //while
40    }                               //for
41 /*- - - - - - - - - - - - - -- -判断每一活动是否为关键活动- -- - - - - -  - - - - - -*/
42    for(i=0;i<n;i++)                //每次循环针对vi为活动开始点的所有活动
43    {
44       p=G.vertices[i].firstarc;    //p指向i的第一个邻接顶点
45       while(p!=NULL)
46       {
47          j=p->adjvex;              //j为i的邻接顶点的序号
48          e=ve[i];                  //计算活动<vi, vj>的最早开始时间
49          l=vl[j]-p->weight;        //计算活动<vi, vj>的最迟开始时间
50          if(e==l)                  //若为关键活动,则输出<vi, vj>
51             cout<<G.vertices[i].data <<G.vertices[j].data;
52          p=p->nextarc;             //p指向i的下一个邻接顶点
53       }                            //while
54    }                               //for
55 }

图-应用-拓扑排序AOE

 1 //严 2 //数据元素类型定义3 typedef struct{4     KeyType key;  //关键字域 5     InfoType otherinfo;  //其他域 6 }ElemType; 7 //顺序表定义8 typedef struct {9     ElemType *R;  //存储空间基地址
10     int length;      //当前长度
11 } SSTable;
12
13
14 //顺序查找
15 //严
16 int Search_Seq(SSTable ST,KeyType key){  //在顺序表ST中查找其关键字等于key的数据元素。若找到,返回该元素在表中的位置
17     for(i=ST.length;i>1;--i)
18         if(ST.R[i].key==key) return i;  //从后往前找
19     return 0;
20 }
21 //设置监视哨的顺序查找
22 int Search_Seq(SSTable ST,KeyType key){  //找不到还是返回0,少了一次比较,length大于1000时,查找平均时间少了一半
23     ST.R[0].key=key;                    //哨兵
24     for(i=ST.length;ST.R[i].key!=key;--i);//从后往前找
25     return i;
26 } 

查找-线性表-顺序查找

 1 //陈   2 int BinarySearch(StaticTable *Tbl,ElementType K){3     int left,right,mid,notFound=-1;4     left=1;             //初始左边界 5     right=Tbl->length;    //初始右边界 6     while(left<right){7         mid=(left+right)/2;  //计算中间元素坐标 8         if(K>Tbl->Element[mid])left=mid+1;  //调整左边界 9         else if(K<Tbl->Element[mid])right=mid-1;//调整右边界
10         else return mid;                    //查找成功,返回数组元素下标
11     }
12     return notFound;        //查找不成功,返回-1
13 }
14 //严
15 int Search_Bin(SSTable ST,KeyType key){
16     low=1;
17     high=ST.length;                    //置查找区间初值
18     while(low<=high){
19         mid=(low+high)/2;
20         if(key==ST.R[mid].key) return mid;  //找到待查元素
21         else if(key<ST.R[mid].key) high=mid-1;  //继续在前一子表查找
22         else low=mid+1;                            //继续在后一子表查找
23     }
24     return 0;            //表中不存在待查元素
25 } 

查找-线性表-折半查找

 1 //严2 #define m 3            //B树的阶,暂设为3阶 3 typedef struct BTNode{4     int keynum;        //结点中关键字的个数,即结点的大小 5     struct BTNode *parent;//指向双亲结点 6     KeyType K[m+1];  //关键字向量,0号单元未用 7     struct BTNode *ptr[m+1];//子树指针向量 8     Record *recptr[m+1];    //记录指针向量,0号单元未用 9 } BTNode,*BTree;    //B树结点和B树的类型
10
11 typedef struct {
12     BTNode *pt;        //指向找到的结点
13     int i;            //1..m,在结点中的关键字序号
14     int tag;        //1:查找成功;0:查找失败
15 } Result;             //B树的查找结果类型 

查找-树表(文件)-B树-定义

 1 //严2 Result SearchBTree(BTree T,KeyType key){3 //在m阶B树上查找关键字key,返回Result类型结果4 //若查找成功,则特征值tag=1,指针pt所指结点中,第i个关键字等于key5 //否则特征值tag=0,等于key的关键字应插入指针pt所指结点中第i个和第i+1个关键字之间6     p=T;7     q=NULL;8     found=FALSE;9     i=0;    //初始化,p指向待查结点,q指向p的双亲
10     while(p&&!found){
11         i=Search(p,key);  //在p-key[1..keynum]中查找i,使得 p->key[i] <= k < p->key[i+1]
12         if(i>0&&p->key[i]==k) found=TRUE;  //找到待查关键字
13         else {
14             q=p;
15             p=p->ptr[i];
16         }
17     }
18     if(found) return (p,i,1);    //查找成功
19     else return (q,i,0);        //查找不成功,返回K的插入位置信息
20 } 

查找-树表(文件)-B树-查找

 1 //严2 Status InsertBTree(BTree &T,KeyType K,BTree q,int i){3 //在m阶B树T上结点*q的key[i]与key[i+1]之间插入关键字K4 //若引起结点过大,则沿双亲链进行必要的分裂调整,使T仍是m阶B树5     x=K;6     ap=NULL;7     finished=FALSE;  //x表示新插入的关键字,ap为一个空指针 8     while(q&&!=finished){9         Insert(q,i,x,ap);    //将x和ap分别插入到q->key[i+1]和q->ptr[i+1]
10         if(q->keynum<m) finished=TRUE;  //插入完成
11         else{        //分裂结点*p
12             s=[m/2];
13             split(q,s,ap);
14             x=q->key[s];    //将q->key[s+1..m],q->ptr[s..m]和q->recptr[s+1..m]移入新结点*ap
15             q=q->parent;
16             if(q) i=Search(q,x);  //在双亲结点*q中查找x的插入位置
17         }
18     }
19     if(!finished)             //T是空树(参数q初值为NULL)或者根结点已分裂为结点*q和*ap
20         NewRoot(T,q,x,ap);  //生成含信息(T,x,ap)的新的根结点*T,原T和ap为子树指针
21     return OK;
22 } 

查找-树表(文件)-B树-插入

 1 //陈2 //定义 3 typedef struct HashTbl *HashTable;4 struct HashTbl{5     int TableSize;6     Cell *TheCells;7 }H ;8 //初始化 9 HashTable InitializeTable( int TableSize )
10 {
11     HashTable H;
12     int i;
13     if ( TableSize < MinTableSize ){
14         Error( "散列表太小" );
15         return NULL;
16     }
17     /* 分配散列表 */
18     H = (HashTable)malloc( sizeof( struct HashTbl ) );
19     if ( H == NULL )
20         FatalError( "空间溢出!!!" );
21     H->TableSize = NextPrime( TableSize );
22     /* 分配散列表 Cells */
23     H->TheCells=(Cell *)malloc(sizeof( Cell )*H->TableSize);
24     if( H->TheCells == NULL )
25         FatalError( "空间溢出!!!" );
26     for( i = 0; i < H->TableSize; i++ )
27         H->TheCells[ i ].Info = Empty;
28     return H;
29 }

查找-散列函数-冲突解决方法-开放地址法-平方探测法-定义、初始化

 1 Position Find( ElementType Key, HashTable H ) /*平方探测*/2 { 3     Position CurrentPos, NewPos;4     int CNum; /* 记录冲突次数 */5     CNum = 0;6     NewPos = CurrentPos = Hash( Key, H->TableSize );7     while( H->TheCells[ NewPos ].Info != Empty &&H->TheCells[ NewPos ].Element != Key ) {8     /* 字符串类型的关键词需要 strcmp 函数!! */9         if(++CNum % 2){ /* 判断冲突的奇偶次 */
10             NewPos = CurrentPos + (CNum+1)/2*(CNum+1)/2;
11             while( NewPos >= H->TableSize )
12                 NewPos -= H->TableSize;
13         } else {
14             NewPos = CurrentPos - CNum/2 * CNum/2;
15             while( NewPos < 0 )
16                 NewPos += H->TableSize;
17         }
18     }
19     return NewPos;
20 }

查找-散列函数-冲突解决方法-开放地址法-平方探测法-查找

 1 //陈2 void Insert( ElementType Key, HashTable H )3 { /* 插入操作 */4     Position Pos;5     Pos = Find( Key, H );6     if( H->TheCells[ Pos ].Info != Legitimate ) {7     /* 确认在此插入 */8         H->TheCells[ Pos ].Info = Legitimate;9         H->TheCells[ Pos ].Element = Key;
10     /*字符串类型的关键词需要 strcpy 函数!! */
11     }
12 }

查找-散列函数-冲突解决方法-开放地址法-平方探测法-插入

 1 //严2 //- - - - -开放地址法散列表的存储表示- - - - -3 #define m 20                                            //散列表的表长4 typedef struct{5     KeyType key;                                        //关键字项6     InfoType otherinfo;                                 //其他数据项7 }HashTable[m];8 9 //查找
10 #define NULLKEY 0                               //单元为空的标记
11 int SearchHash(HashTable HT,KeyType key)
12 {//在散列表HT中查找关键字为key的元素,若查找成功,返回散列表的单元标号,否则返回-1
13    H0=H(key);                                  //根据散列函数H(key)计算散列地址
14    if(HT[H0].key==NULLKEY) return -1;          //若单元H0为空,则所查元素不存在
15    else if(HT[H0].key==key) return H0;         //若单元H0中元素的关键字为key,则查找成功
16    else
17    {
18       for(i=1;i<m;++i)
19      {
20          Hi=(H0+i)%m;                          //按照线性探测法计算下一个散列地址Hi
21          if(HT[Hi].key==NULLKEY) return -1;    //若单元Hi为空,则所查元素不存在
22          else if(HT[Hi].key==key) return Hi;   //若单元Hi中元素的关键字为key,则查找成功
23       }                                        //for
24       return -1;
25     }                                          //else
26 } 

查找-散列函数-冲突解决方法-开放地址法-线性探测法-定义、查找

 1 //陈 2 //将相应位置上冲突的所有关键词存储在同一个单链表中3 //定义 4 typedef struct ListNode *Position,*List;5 struct ListNode{6     ElementType Element;7     Position Next;8 };9 typedef struct HashTbl *HashTable;
10 struct HashTbl{
11     int TableSize;
12     List TheLists;
13 };
14 //查找
15 Position Find(ElementType X,HashTable H){
16     Position P;
17     int Pos;
18     Pos=Hash(X,H->TableSize);
19     P=H->TheLists[Pos].Next;
20     if(P!=NULL&&strcmp(P->Element,X)) P=P->Next;
21     return P;
22 }

查找-散列函数-冲突解决方法-链地址法-分离地址法-定义、查找

int ar[5]={3,8,9,5,2};//对它从小到大排序

 1 //插入排序, 每个数与前面排好序的比较,满足条件,就把大家往后移,当前数插入前面自己的位置 2 //3,8,9,5,2  3 //arr[1]是8,temp= arr[1]  ,arr[0]没有>arr[1], 4 //arr[2]是9,temp= arr[2]  ,5 //arr[3]是5,temp= arr[3]  ,6 //arr[4]是2,temp= arr[3]  ,7 //第1轮 3 8 9 5 2   8 //第2轮 3 8 9 5 29 //第3轮 3 5 8 9 2
10 //第4轮 2 3 5 8 9
11 void insert_sort(int arr[], int len){
12     int i,j,temp;
13     for (i=1;i<len;i++){ //此处不-1,因为是从1开始
14             temp = arr[i]; //当前数待插入,先拿出来
15             for (j=i;j>0 && arr[j-1]>temp;j--) //循环每个数,把它和前面比,满足条件就把前面的往后挪一位,再比前面的,
16                     arr[j] = arr[j-1];
17             arr[j] = temp;  //直到没法挪,当前位置前一位不满足大小,就把待插入的放到当前位
18     }
19 }
20 //严
21 void InsertSort(SqList &L)
22 {//对顺序表L做直接插入排序
23    for(i=2;i<=L.length;++i)
24       if(L.r[i].key<L.r[i-1].key)                 //“<”,需将r[i]插入有序子表
25       {
26          L.r[0]=L.r[i];                          //将待插入的记录暂存到监视哨中
27          L.r[i]=L.r[i-1];                        //r[i-1]后移
28          for(j=i-2; L.r[0].key<L.r[j].key; --j)  //从后向前寻找插入位置
29             L.r[j+1]=L.r[j];                     //记录逐个后移,直到找到插入位置
30          L.r[j+1]=L.r[0];                        //将r[0]即原r[i],插入到正确位置
31       }                                          //if
32 }

排序-插入排序-直接插入排序

 1 //严2 void BInsertSort(SqList &L)3 {//对顺序表L做折半插入排序 4    for(i=2;i<=L.length;++i) 5    { 6       L.r[0]=L.r[i];                              //将待插入的记录暂存到监视哨中 7       low=1;high=i-1;                             //置查找区间初值 8       while(low<=high)                            //在r[low..high]中折半查找插入的位置9       {
10          m=(low+high)/2;                           //折半
11          if(L.r[0].key<L.r[m].key) high=m-1;       //插入点在前一子表
12          else low=m+1;                             //插入点在后一子表
13       }                                            //while
14       for(j=i-1;j>=high+1; --j) L.r[j+1]=L.r[j];   //记录后移
15       L.r[high+1]=L.r[0];                          //将r[0]即原r[i],插入到正确位置
16    }                                               //for
17 } 

排序-插入排序-折半插入排序

 1 //希尔排序,插入排序的升级版 2 //3,8,9,5,2   len=53 //第1轮 3 5 2 8 9    gap=2  i=2 temp=9 j=0  |  i=3 temp=5 j=1 | i=4 temp=2 j=2 j=0 4 //第2轮 2 3 5 8 9    gap=1  i=1 temp=5 j=0  |  i=2 temp=2 j=1 j=0  j=-1          5 void shell_sort(int arr[], int len) {6     int gap, i, j;7     int temp;8     for (gap = len >> 1; gap > 0; gap = gap >> 1)9         for (i = gap; i < len; i++) {
10             temp = arr[i];
11             for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
12                 arr[j + gap] = arr[j];
13             arr[j + gap] = temp;
14         }
15 }
16 //严
17 void ShellInsert(SqList &L, int dk)
18 {//对顺序表L做一趟增量是dk的希尔插入排序
19    for(i=dk+1;i<=L.length;++i)
20       if(L.r[i].key<L.r[i-dk].key)     //需将L.r[i]插入有序增量子表
21       {
22          L.r[0]=L.r[i];                //暂存在L.r[0]
23          for(j=i-dk; j>0&& L.r[0].key<L.r[j].key;j-=dk)
24             L.r[j+dk]=L.r[j];          //记录后移,直到找到插入位置
25          L.r[j+dk]=L.r[0];             //将r[0]即原r[i],插入到正确位置
26       }                                //if
27 }
28 void ShellSort(SqList &L,int dt[],int t)
29 {//按增量序列dt[0..t-1]对顺序表L作t趟希尔排序
30    for(k=0;k<t;++k)
31       ShellInsert(L,dt[k]);            //一趟增量为dt[t]的希尔插入排序
32 } 

排序-插入排序-希尔排序

 1 //冒泡排序,相邻两数比较,把大的往后冒,每轮循环找最大放后面 2 //第1轮 3 8 5 2 93 //第2轮 3 5 2 8 94 //第3轮 3 2 5 8 95 //第4轮 2 3 5 8 96 void bubble_sort(int arr[],int len){7     int i,j,temp;8     for(i=0;i<len-1;i++){ // 同上 9         for(j=0;j<len-1-i;j++){ //下面有+1,所以这里减-1,防止最后一个数和外面比较越界了; 每次放一个最大的,放过的不用再比,因此-i。
10             if(arr[j]>arr[j+1]){
11                 temp = arr[j];
12                 arr[j]=arr[j+1];
13                 arr[j+1]=temp;
14             }
15         }
16     }
17 }
18 //严
19 void BubbleSort(SqList &L)
20 {//对顺序表L做冒泡排序
21    m=L.length-1;flag=1;                           //flag用来标记某一趟排序是否发生交换
22    while((m>0)&&(flag==1))
23    {
24       flag=0;                                     //flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序
25       for(j=1;j<=m;j++)
26          if(L.r[j].key>L.r[j+1].key)
27          {
28             flag=1;                                //flag置为1,表示本趟排序发生了交换
29             t=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=t;//交换前后两个记录
30           }                                       //if
31         --m;
32     }                                            //while
33 }                                                //BubbleSort 

排序-交换排序-冒泡排序

  1 //快速排序-迭代法2 Range new_Range(int s, int e) {3     Range r;4     r.start = s;5     r.end = e;6     return r;7 }8 void swap(int *x, int *y) {9     int t = *x;10     *x = *y;11     *y = t;12 }13 //3,8,9,5,2   len=514 //第一轮:start=0 end=4 mid=9 left=0 right=4 进do left=1 left=2 {3,8,2,5,9} left=3 right=3 left=415 //第二轮:start=0 end=3 mid=8 left=0 right=3 进do left=1 {3,5,2,8,9} left=2 right=2 left=316 //第三轮:start=0 end=2 mid=5 left=0 right=2 进do left=1 {3,2,5,8,9} left=2 right=1 17 //第四轮:start=0 end=1 mid=3 left=0 right=1 进do right=0 {2,3,5,8,9} left=1 right=018 void quick_sort(int arr[], const int len) {19     if (len <= 0)20         return; // 避免len等於負值時引發段錯誤(Segment Fault)21     // r[]模擬列表,p為數量,r[p++]為push,r[--p]為pop且取得元素22     Range r[len];23     int p = 0;24     r[p++] = new_Range(0, len - 1);25     while (p) {26         Range range = r[--p];27         if (range.start >= range.end)28             continue;29         int mid = arr[(range.start + range.end) / 2]; // 選取中間點為基準點30         int left = range.start, right = range.end;31         do32         {33             while (arr[left] < mid) ++left;   // 檢測基準點左側是否符合要求34             while (arr[right] > mid) --right; //檢測基準點右側是否符合要求35  36             if (left <= right)37             {38                 swap(&arr[left],&arr[right]);39                 left++;right--;               // 移動指針以繼續40             }41         } while (left <= right);42  43         if (range.start < right) r[p++] = new_Range(range.start, right);44         if (range.end > left) r[p++] = new_Range(left, range.end);45     }46 } 47 48 //快速排序-递归法49 //3,8,9,5,2   len=550 //第一轮:start=0 end=4 mid=2 left=0 right=3 进while right=2 right=1 right=0 {2,8,9,5,3}51 //进递归,start=1 end=4 mid=3 left=1 right=3 进while right=2 right=1 {2,3,9,5,8}52 //进if递归,start=1 end=0 return53 //进递归  start=2 end=4 mid=8 left=2 right=3 进while {2,3,5,9,8} left=3 {2,3,5,8,9}54 //进if递归,start=2 end=2 return55 //进递归  start=4 end=4 return56 void quick_sort_recursive(int arr[], int start, int end) {57     if (start >= end)58         return;59     int mid = arr[end];60     int left = start, right = end - 1;61     while (left < right) {62         while (arr[left] < mid && left < right)63             left++;64         while (arr[right] >= mid && left < right)65             right--;66         swap(&arr[left], &arr[right]);67     }68     if (arr[left] >= arr[end])69         swap(&arr[left], &arr[end]);70     else71         left++;72     if (left)73         quick_sort_recursive(arr, start, left - 1);74     quick_sort_recursive(arr, left + 1, end);75 }76 void quick_sort_digui(int arr[], int len) {77     quick_sort_recursive(arr, 0, len - 1);78 }79 80 //严81 int Partition(SqList &L, int low, int high)82 {//对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴位置 83    L.r[0]=L.r[low];                     //用子表的第一个记录做枢轴记录 84    pivotkey=L.r[low].key;               //枢轴记录关键字保存在pivotkey中 85    while(low<high)                      //从表的两端交替地向中间扫描 86    {      87       while(low<high&&L.r[high].key>=pivotkey) --high; 88       L.r[low]=L.r[high];               //将比枢轴记录小的记录移到低端 89       while(low<high&&L.r[low].key<=pivotkey) ++low; 90       L.r[high]=L.r[low];               //将比枢轴记录大的记录移到高端 91    }                                    //while 92    L.r[low]=L.r[0];                     //枢轴记录到位 93    return low;                          //返回枢轴位置 94 }95           96 void QSort(SqList &L,int low,int high) 97 {//调用前置初值:low=1; high=L.length; 98  //对顺序表L中的子序列L.r[low..high]做快速排序 99    if(low<high){                        //长度大于1
100       pivotloc=Partition(L, low, high); //将L.r[low..high]一分为二,pivotloc是枢轴位置
101       QSort(L, low, pivotloc-1);        //对左子表递归排序
102       QSort(L, pivotloc+1, high);       //对右子表递归排序
103    }
104 }
105
106 void QuickSort(SqList &L)
107 {//对顺序表L做快速排序
108    QSort(L,1,L.length);
109 } 

排序-交换排序-快速排序

 1 //选择排序,用每个数字和其他依次比较,循环找第一小放第一个、在剩下的里面找第二小放第二个,…… 2 //第1轮 2 8 9 5 33 //第2轮 2 3 9 8 54 //第3轮 2 3 5 9 85 //第4轮 2 3 5 8 96 void select_sort(int arr[],int len){7     int i,j,temp; 8     for(i=0;i<len-1;i++){ //外层循环管轮数,5个数,肯定比4轮,因为最后一个数不用和自己比较,所以减一 9         for(j=i+1;j<len;j++) //每个数跟他后面的依次比较,所以加一
10             if(arr[i]>arr[j]){ //如果比后面大,就把小的放前面
11                 temp = arr[i];
12                 arr[i]=arr[j];
13                 arr[j]=temp;
14             }
15     }
16 }
17 //严
18 void SelectSort(SqList &L)
19 {//对顺序表L做简单选择排序
20    for(i=1;i<L.length;++i){                     //在L.r[i..L.length] 中选择关键字最小的记录
21       k=i;
22       for(j=i+1;j<=L.length;++j)
23          if(L.r[j].key<L.r[k].key) k=j;        //k指向此趟排序中关键字最小的记录
24       if(k!=i)
25          {t=L.r[i]; L.r[i]=L.r[k]; L.r[k]=t;}  //交换r[i]与r[k]
26     }                                          //for
27 } 

排序-选择排序-简单选择排序

 1 //严 2 //调整堆3 void HeapAdjust(SqList &L,int s,int m)4 {//假设r[s+1..m]已经是堆,将r[s..m]调整为以r[s]为根的大根堆 5    rc=L.r[s]; 6    for(j=2*s;j<=m;j*=2)                     //沿key较大的孩子结点向下筛选 7    {       8       if(j<m&&L.r[j].key<L.r[j+1].key) ++j; //j为key较大的记录的下标 9       if(rc.key>=L.r[j].key) break;         //rc应插入在位置s上
10       L.r[s]=L.r[j];s=j;
11    }                                        //for
12    L.r[s]=rc;                              //插入
13 }
14
15 //建初堆
16 void CreatHeap(SqList &L)
17 {//把无序序列L.r[1..n]建成大根堆
18    n=L.length;
19    for(i=n/2;i>0; --i)                  //反复调用HeapAdjust
20      HeapAdjust(L,i,n);
21 }
22 //堆排序
23 void HeapSort(SqList &L)
24 {//对顺序表L进行堆排序
25    CreatHeap(L);                 //把无序序列L.r[1..L.length]建成大根堆
26    for(i=L.length;i>1;--i)
27    {
28      x=L.r[1];                  //将堆顶记录和当前未经排序子序列L.r[1..i]中最后一个记录互换
29      L.r[1]=L.r[i];
30          L.r[i]=x;
31      HeapAdjust(L,1,i-1);       //将L.r[1..i-1]重新调整为大根堆
32    }                            //for
33 } 

排序-选择排序-堆排序

选择排序还有树形选择排序,就是比赛用的那种。

  1 //严2 //相邻两个有序子序列的归并3 void Merge(RedType R[],RedType T[],int low,int mid,int high)4 {//将有序表R[low..mid]和R[mid+1..high]归并为有序表T[low..high]5    i=low;j=mid+1;k=low;6    while(i<=mid&&j<=high)                 //将R中记录由小到大地并入T中7    {8      if(R[i].key<=R[j].key) T[k++]=R[i++];9      else T[k++]=R[j++];10    }                                      //while11    while(i<=mid) T[k++]=R[i++];           //将剩余的R[i..mid]复制到T中12    while(j<=high) T[k++]=R[j++];          //将剩余的R[j.high]复制到T中13 }14 //归并排序15 void MSort(RedType R[],RedType &T[],int low,int high)16 {//R[low..high]归并排序后放入T[low..high]中  17    if(low==high) T[low]=R[low];  18    else 19    {  20       mid=(low+high)/2;       //将当前序列一分为二,求出分裂点mid  21       MSort(R,S,low,mid);     //对子序列R[low..mid]递归归并排序,结果放入S[low..mid]  22       MSort(R,S,mid+1,high);  //对子序列R[mid+1..high]递归归并排序,结果放入S[mid+1..high] 23       Merge(S,T,low,mid,high);//将S[low..mid]和S[mid+1..high]归并到T[low..high] 24    }         //else  25 }  26 void MergeSort(SqList &L) 27 {//对顺序表L做归并排序  28    MSort(L.r,L.r,1,L.length);  29 } 30 31 //归并排序-之迭代法 32 //大致想法是,相邻两数比,变成小大、小大、小大,然后变宽,再比,变成小小大大、…… ;再变宽,小小小小大大大大、……,33 //以此类推,每一轮只要两两比较 小小小小,大大大大的值,把新结果放到新数组里,剩下的抄到后面即可34 //这个有种2分法逆着用的感觉,因为变宽(seg)总以2的指数级增长,所以这个算法快不快,取决于边界值能不能快点比完,比如小小小小都小于大,那么后面3个大直接抄就行35 int min(int x, int y) {36     return x < y ? x : y;37 }38 //3,8,9,5,2   len=539 //第一轮  seg=1 start=0 low=0 mid=1 high=2 k=0 start1=0 end1=1 start2=1 end2=2 b[0]=3,k=1,start1=1 b[1]=8 k=2 start2=2  40 //                start=2 low=2 mid=3 high=4 k=2 start1=2 end1=3 start2=3 end2=4 b[2]=5 k=3,start2=4 b[3]=9 k=4 start1=341 //                 start=4 low=4 mid=5 high=5 k=4 start1=4 end1=5 start2=5 end2=5 b[4]=2 k=5,start1=542 //                start=6 exit43 //                a[]={3,8,5,9,2}44 //第二轮  seg=2 start=0,low=0 mid=2 high=4 k=0 start1=0 end1=2 start2=2 end2=4 b[0]=3 k=1 start1=1 b[1]=5 k=2 start2=3 b[2]=8 k=3 start1=2 b[3]=9 k=4 start2=445 //                start=4,low=4,mid=5 high=5 k=4 start1=4 end1=5 start2=5 end2=5 b[4]=2 k=5,start1=546 //                a[]={3,5,8,9,2}47 //第三轮  seg=4 start=0 low=0 mid=4 high=5 k=0 start1=0 end1=4 start2=4 end2=5 b[0]=2 k=1 start2=5 b[1]=3 k=2 start1=1 b[2]=5 k=3 start1=2 b[3]=8 k=4 start1=3 b[4]=9 k=5 start1=4 48 //                start=8 exit49 //                a[]={2,3,5,8,9}50 //第三轮  seg=8 exit51 void merge_sort(int arr[], int len) {52     int* a = arr; //指向要排序的数组 53     int* b = (int*) malloc(len * sizeof(int));//临时存放每轮排序结果 54     int seg, start;55     for (seg = 1; seg < len; seg += seg) {56         for (start = 0; start < len; start += seg + seg) {57             //按照分段大小,先确定段与段之间的界限 58             int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);59             int k = low;60             int start1 = low, end1 = mid;61             int start2 = mid, end2 = high;62             //段内元素两两比较,小的放到临时数组 63             while (start1 < end1 && start2 < end2)64                 b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];65             //其中一段全比完了,剩下一段直接抄到后面 66             while (start1 < end1)67                 b[k++] = a[start1++];68             //其中一段全比完了,剩下一段直接抄到后面 69             while (start2 < end2)70                 b[k++] = a[start2++];71         }72         //把这种分段下排好的临时数组,作为下次要排序的数组 73         int* temp = a;74         a = b;75         b = temp;76     }77     //释放b空间,我也不知道为啥要重新赋值再释放 78     if (a != arr) {79         int i;80         for (i = 0; i < len; i++)81             b[i] = a[i];82         b = a;83     }84     free(b);85 }86 87 //归并排序-之递归法  88 //3,8,9,5,2   len=589 //start=0,end=4,len=4,mid=2,start1=0,end1=2 start2=3 end2=4 入栈 90 //start=0,end=2 len=2 mid=1 start1=0,end1=1 start2=2 end2=2 入栈91 //start=0,end=1 len=1 mid=0 start1=0 end1=0 start2=1 end2=1 入栈92 //start=0 end=0 return end1=0出栈 start2=1入栈直接出栈,代码第一次往下执行93 //代码第一次往下执行 k=0 reg[0]=3,start1=1,k=1 reg[1]=8 start2=2 arr[0]=3 arr[1]=894 //上步代码走完,return end1=1出栈 start2=2入栈直接出栈,代码第二次往下执行95 //代码第二次往下执行 k=0 reg[0]=3 start1=1 k=1 reg[1]=8 start1=2 k=2 reg[2]=9 start2=3 k=3 arr[0]=3 arr[1]=8 arr[2]=996 //上步代码走完,return end1=2出栈 start2=3入栈,97 //start=3,end=4 len 1 mid=3 start1=3 end1=3 start2=4 end2=4 入栈直接出栈,入栈直接出栈,代码第三次往下执行98 //代码第三次往下执行 k=3 reg[3]=2 start2=5 k=4 reg[4]=5 k=5 start1=4 arr[3]=2 arr[4]=599 //arr[]={3,8,9,2,5}
100 //上步代码走完,第一行 start=0,end=4完成了两个递归,继续往下,
101 //代码第四次往下走  k=0,reg[0]=2,start1=1,k=1, reg[1]=3,start1=2,k=2 reg[2]=5 start2=4 k=3 reg[3]=8 start2=4 k=4 reg[4]=9
102 //arr[]={2,3,5,8,9}
103
104 void merge_sort_recursive(int arr[], int reg[], int start, int end) {
105     if (start >= end)
106         return;
107     int len = end - start, mid = (len >> 1) + start;
108     int start1 = start, end1 = mid;
109     int start2 = mid + 1, end2 = end;
110     merge_sort_recursive(arr, reg, start1, end1);
111     merge_sort_recursive(arr, reg, start2, end2);
112     int k = start;
113     while (start1 <= end1 && start2 <= end2)
114         reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
115     while (start1 <= end1)
116         reg[k++] = arr[start1++];
117     while (start2 <= end2)
118         reg[k++] = arr[start2++];
119     for (k = start; k <= end; k++)
120         arr[k] = reg[k];
121 }
122 void merge_sort_digui(int arr[], const int len) {
123     int reg[len];
124     merge_sort_recursive(arr, reg, 0, len - 1);
125 }

排序-归并排序

 1 //严2 //链式基数排序3 //定义 4 #define MAXNUM_KEY 8                    //关键字项数的最大值5 #define RADIX 10                        //关键字基数,此时是十进制整数的基数6 #define MAX_SPACE 100007 typedef struct8 {9    KeyType keys[MAXNUM_KEY];            //关键字
10    InfoType otheritems;                 //其他数据项
11    int next;
12 }SLCell;                               //静态链表的结点类型
13 typedef struct
14 {
15    SLCell r[MAX_SPACE];                //静态链表的可利用空间,r[0]为头结点
16    int keynum;                         //记录的当前关键字个数
17    int recnum;                         //静态链表的当前长度
18 }SLList;                               //静态链表类型
19 typedef int ArrType[RADIX]             //数组类型
20
21 //排序
22 void Distribute(SLCell &r,int i,ArrType &f,ArrType &e)
23 {//静态链表L的r域中记录已按(keys[0], …, keys[i-1])有序
24  //本算法按第i个关键字keys[i]建立RADIX个子表,使同一子表中记录的 keys[i]相同
25  //f[0..RADIX-1]和e[0..RADIX-1]分别指向各子表中第一个和最后一个记录
26    for(j=0;j<RADIX;++j) f[j]=0;                   //各子表初始化为空表
27    for(p=r[0].next;p;p=r[p].next)
28    {
29      j=ord(r[p].keys[i]);                         //ord将记录中第i个关键字映射到[0..RADIX-1]
30      if(!f[j]) f[j]=p;
31      else r[e[j]].next=p;
32      e[j]=p;                                      //将p所指的结点插入第j个子表中
33    }                                              //for
34 }
35
36 void Collect(SLCell &r,int i,ArrType f,ArrType e)
37 {//本算法按keys[i]自小至大地将f[0..RADIX-1]所指各子表依次链接成一个链表
38  //e[0..RADIX-1]为各子表的尾指针
39    for(j=0;!f[j]; j=succ(j));                     //找第一个非空子表,succ为求后继函数
40    r[0].next=f[j]; t=e[j];                        //r[0].next指向第一个非空子表中第一个结点
41    while(j<RADIX)
42    {
43      for(j=succ(j);j<RADIX-1&&!f[j];j=succ(j));   //找下一个非空子表
44      if(f[j]) {r[t].next=f[j]; t=e[j];}           //链接两个非空子表
45    }                                              //while
46    r[t].next=0;                                   //t指向最后一个非空子表中的最后一个结点
47 }
48
49 void RadixSort(SLList &L)
50 {//L是采用静态链表表示的顺序表
51  //对L做基数排序,使得L成为按关键字自小到大的有序静态链表,L.r[0]为头结点
52    for(i=0;i<L.recnum;++i) L.r[i].next=i+1;
53    L.r[L.recnum].next=0;                         //将L改造为静态链表
54    for(i=0;i<L.keynum;++i)  {                    //按最低位优先依次对各关键字进行分配和收集
55      Distribute(L.r,i,f,e);                      //第i趟分配
56      Collect(L.r,i,f,e);                         //第i趟收集
57    }                                             //for
58 } 

排序-基数排序-定义、排序

《数据结构》严蔚敏与陈越伪代码总结相关推荐

  1. 构建线性表的c语言代码,数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码...

    1.运行环境 这里说明一下这里所有的C语言代码都是基于code::blocks 20.03编译运行的.当然一些其他集成开发环境应该也是可以的,个人不太喜欢功能太过强大的IDE,因为那同样意味着相关设置 ...

  2. 数据结构与算法(陈越版)第五讲 (树下)树的应用——集合及其运算

    数据结构与算法(陈越版)第五讲 (树下)树的应用--集合及其运算 一.集合的表示 1.1.集合的表示 1.2.集合的储存 二.集合的运算 2.1查找以及普通并 2.2按照秩的合并算法 2.3路径压缩优 ...

  3. 数据结构 严蔚敏 第二章 线性表

    数据结构 严蔚敏 第二章 线性表 线性表:由n个(n>=0)数据特征相同的元素构成的有限序列. 线性表的类型定义表示和实现 顺序表 存储单元地址连续 随机存取 若每个元素占用 m 个存储单元,以 ...

  4. 【计算机】数据结构-严蔚敏/清华大学P3

    [计算机]数据结构-严蔚敏/清华大学P1 第二章    线  性表 线性结构 是 一个数据元素的有序(次序)集 线性结构的基本特征: 1.  集合中必存在唯一的一个"第一元素": ...

  5. 数据结构严蔚敏C语言版—线性表顺序存储结构(顺序表)C语言实现相关代码

    数据结构严蔚敏C语言版-线性表顺序存储结构(顺序表)C语言实现相关代码 1.运行环境 2.准备工作 1)项目构建 1>新建一个SeqList项目 2>新建两个文件Sources和Heade ...

  6. 数据结构----严蔚敏

    最近一直想找一本纯数据结构的书来学习,找来找去都没有找到一本合适的书籍,相比之下国内的书籍之中,严蔚敏和吴伟民的还算是经典版了,很多国内其他数据结构教材都参考这本书的.但缺点是很多都是伪代码,对编程初 ...

  7. 数据结构与算法(陈越)(学习笔记)(更新ing)

    数据结构(陈越) 一.数据结构(计算运行时间) #include<stdio.h> #include<time.h> #include<math.h> clock_ ...

  8. 数据结构严蔚敏清华大学pdf_2019年清华大学自动化系控制工程专业大数据方向考研经验分享...

    基本情况(以下内容仅代表个人观点) 我目前就读于西南某双非石油工程专业,2019考研报考清华大学自动化系大数据工程专业,一志愿复试被刷,侥幸调剂录取至微电子系.初试总分346分(政治-63 + 英语一 ...

  9. 数据结构 绪论+视频资料(修订版)严蔚敏、陈文博版

    资料(我感觉老师讲的不错,通俗易懂 需要自取,比较有逻辑 老师是赵海英) 链接: https://pan.baidu.com/s/1zJ-6nvT_0Ya21liHuQS-sw 密码: 496e ht ...

最新文章

  1. [优先队列] 洛谷 P2085 最小函数值
  2. Ubuntu11.10下载android4.0.1源码
  3. gulp几个常见问题及解决方案
  4. HTML5开发 桌面提醒功能
  5. postgresql 动态添加过滤条件_通过窗口函数进行过滤导致Postgresql
  6. python面试设计模式问题_聊聊 Python 面试最常被问到的几种设计模式(下)
  7. eclipse linux远程调试工具,使用本地Eclipse IDE调试器与远程项目源(Linux)
  8. bind mysql django_Django+bind dlz DNS管理平台
  9. 云服务器 ECS > 网络 > 经典网络迁移至专有网络
  10. docker入门与部署微服务--学习笔记
  11. spring 官方文档
  12. ubuntu 编译android .img_全网可用交叉编译工具链大全
  13. 数据结构和算法——线性结构(1)数组、栈、队列和单链表
  14. 产品必备技能(五):如何使用商业画布分析一款产品?附实操报告
  15. 我的gitbub的学习目录
  16. 雷达的工作原理示意图_雷达测距原理.ppt
  17. 为什么要“推销自己”?
  18. 小白入门指南|zookeeper快速入门
  19. vue获取当前时间、时间戳方法
  20. 免费图片素材网站收集

热门文章

  1. 解决flash的虚框问题
  2. 【论文写作】网上选课系统中数据库设计模块如何写
  3. idea debug调试_IDEA中debug调试(非多线程)
  4. 2018渭源县计算机老师,2018年甘肃定西渭源县选调教师公告【招60人】
  5. 简述数学建模的过程_数学建模研究过程指导(精编版) Part IV
  6. VC中利用ADO共同实现数据库的操作
  7. 存储过程调用不同数据库的数据
  8. 洛谷P1079 Vigenère 密码
  9. HTML CSS JS 特殊字符(转义)表
  10. 不一样的三一重工:重在选择 —— 三一集团CIO潘睿刚专访系列之一