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;iL.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(iNext;
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&&jnext;
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&&jnext;
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>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>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)&&jnext;
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<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<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 (keydata.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(XData) 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(XData)
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(XData) 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.keydata.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(XData) 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(keydata.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]- 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]
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;iSize;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
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.vexs[i]; //按总顶点数,依次输入顶点信息
8
9 for(i=0;i>v1>>v2>>w; //输入一条边依附的顶点及权值
15 i=LocateVex(G,v1);
16 j=LocateVex(G,v2); //确定v1,v2在G中的位置,即顶点的数组下标
17 G.arcs[i][j]=w; //边的权值置为w
18 G.arcs[j][i]=G.arcs[i][j]; //置的对称边的权值为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.vertices[i].data; //还是按总顶点数,依次输入顶点信息
7 G.vertices[i].firstarc=NULL; //每个顶点的首条边初始化为null
8 }
9 for(k=0;k>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<=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 }
1 //严
2 //遍历非连通图
3 void DFSTraverse(Graph G){
4 for(v=0;v
1 //严
2 //用邻接矩阵表示
3 void DFS_AM(AMGraph G,int v){ //图G为邻接矩阵类型,从第v个顶点出发,深度优先搜索遍历图G
4 cout<
1 //严
2 //用邻接表表示
3 void DFS_AL(ALGraph G,int v){ //图G为邻接矩阵类型,从第v个顶点出发,深度优先搜索遍历图G
4 cout<adjvex; //w是v的邻接点
9 if(!visited[w])
10 DFS_AL(G,w); //若w未访问,则递归调用DFS_AL
11 p=p->nextarc; //p指向下一个边结点
12 }
13 }
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<=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<
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)
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
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; //是就改值
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
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
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;cntadjvex; //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
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;iadjvex; //j为邻接顶点的序号
21 if(ve[j]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=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;iadjvex; //j为i的邻接顶点的序号
48 e=ve[i]; //计算活动的最早开始时间
49 l=vl[j]-p->weight; //计算活动的最迟开始时间
50 if(e==l) //若为关键活动,则输出
51 cout<nextarc; //p指向i的下一个邻接顶点
53 } //while
54 } //for
55 }
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(leftTbl->Element[mid])left=mid+1; //调整左边界
9 else if(KElement[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
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树的查找结果类型
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 }
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->keynumkey[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 }
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
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;i0 && 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
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=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].key0&& L.r[0].key
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;iarr[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=pivotkey) --high;
88 L.r[low]=L.r[high]; //将比枢轴记录小的记录移到低端
89 while(low
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;iarr[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
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=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