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

 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个顶点出发,深度优先搜索遍历图G
 4      cout<<v;          //访问第v个顶点
 5      visited[v]=true;  //并把它的标志数组值置为true
 6      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 //单源-无权-BFS
 3 //单源-有权-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 sort
 6 //两种算法可实现拓扑排序 
 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个关键字等于key
 5 //否则特征值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]之间插入关键字K
 4 //若引起结点过大,则沿双亲链进行必要的分裂调整,使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 2
 9 //第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=5
 3 //第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 9
 3 //第2轮 3 5 2 8 9
 4 //第3轮 3 2 5 8 9
 5 //第4轮 2 3 5 8 9
 6 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=5
 14 //第一轮: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=4
 15 //第二轮:start=0 end=3 mid=8 left=0 right=3 进do left=1 {3,5,2,8,9} left=2 right=2 left=3
 16 //第三轮: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=0
 18 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         do
 32         {
 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=5
 50 //第一轮: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 return
 53 //进递归  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 return
 55 //进递归  start=4 end=4 return
 56 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     else
 71         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 3
 3 //第2轮 2 3 9 8 5
 4 //第3轮 2 3 5 9 8
 5 //第4轮 2 3 5 8 9
 6 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    }                                      //while
 11    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=5
 39 //第一轮  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=3
 41 //                 start=4 low=4 mid=5 high=5 k=4 start1=4 end1=5 start2=5 end2=5 b[4]=2 k=5,start1=5
 42 //                start=6 exit
 43 //                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=4
 45 //                start=4,low=4,mid=5 high=5 k=4 start1=4 end1=5 start2=5 end2=5 b[4]=2 k=5,start1=5
 46 //                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 exit
 49 //                a[]={2,3,5,8,9}
 50 //第三轮  seg=8 exit
 51 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=5
 89 //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]=8
 94 //上步代码走完,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]=9
 96 //上步代码走完,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]=5
 99 //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 10000
 7 typedef struct
 8 {
 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 } 
排序-基数排序-定义、排序

 

posted @ 2021-10-08 17:24  zhaot1993  阅读(414)  评论(0编辑  收藏  举报