(此贴转自 阳光岛主 ,仅做收藏之用,在此谢谢啦!)
单链表(测试通过)
测试环境: Win-TC
- #include <stdio.h>
- struct _node
- {
- int data;
- struct _node *next;
- };
- typedef struct _node list;
- void display(list *l)
- {
- list *p;
- p=l;
- while(p->next)
- {
- printf("%5d", p->next->data);
- p=p->next;
- }
- }
- void main()
- {
- int i, n;
- list *h, *p, *s;
- printf("Enter num n:");
- scanf("%d", &n);
- h=(list*)malloc(sizeof(list));
- h->data=-1;
- h->next=NULL;
- s=p=h;
- for(i=n;i>0;i--)
- {
- p=(list*)malloc(sizeof(list));
- scanf("%d", &(p->data));
- p->next=h->next;
- h->next=p;
- h=h->next;
- }
- display(s);
- getch();
- }
运行结果:
=================================================
单链表各种操作(测试通过)
测试环境: Win-TC
- #include <stdio.h>
- #include <malloc.h>
- #include <stdlib.h>
- struct _node
- {
- int data;
- struct _node *next;
- };
- typedef struct _node node, *plist;
- plist init_list()
- {
- plist pl;
- pl=(plist)malloc(sizeof (node));
- if (NULL==pl)
- {
- printf("init list, malloc is fail.../n" );
- return NULL;
- }
- pl->data=-1;
- pl->next=NULL;
- return pl;
- }
- int isempty_list(plist pl)
- {
- if (NULL==pl || NULL!=pl->next)
- return 1;
- else
- return 0;
- }
- plist clear_list(plist pl)
- {
- pl=NULL;
- return pl;
- }
- void destroy_list(plist pl)
- {
- plist p, s;
- p=pl->next;
- while (p)
- {
- s=p;
- p=p->next;
- free(s);
- }
- pl=NULL;
- }
- void insert_item(plist pl, int i, int e)
- {
- int j=1;
- plist p, s;
- p=pl;
- while (p && j<i)
- {
- p=p->next;
- j++;
- }
- if (!p || j>i) /* >len or <1 */
- printf("Insert fail.../n" );
- s=(plist)malloc(sizeof (node));
- s->data=e;
- s->next=p->next;
- p->next=s;
- }
- void display(plist pl)
- {
- plist p;
- p=pl->next;
- while (pl && p)
- {
- printf("%5d" , p->data);
- p=p->next;
- }
- printf("/n/n" );
- }
- int getbyid_item(plist pl, int i)
- {
- plist p=pl->next;
- int j=1;
- while (p && j<i)
- {
- p=p->next;
- j++;
- }
- if (!p || j>i) /* >len or <1 */
- {
- printf("fail.../n" );
- exit(1);
- }
- return p->data;
- }
- int locate_item(plist pl, int e)
- {
- plist p=pl->next;
- int j=1;
- while (p->data != e && p->next)
- {
- p=p->next;
- j++;
- }
- if (p->data == e)
- return j;
- else
- {
- printf("There is n %d in list/n" , e);
- return -1;
- }
- }
- void delete_item(plist pl, int i, int *e)
- {
- plist p=pl;
- plist q;
- int j=1;
- while (p->next && j<i)
- {
- p=p->next;
- j++;
- }
- if (!p->next || j>i) /* >len or <1 */
- {
- printf("fail..../n" );
- return ;
- }
- q=p->next;
- p->next=q->next;
- *e=q->data;
- free(q);
- }
- int len_list(plist pl)
- {
- int j=0;
- plist p=pl;
- while (pl && p->next)
- {
- j++;
- p=p->next;
- }
- return j;
- }
- plist traverse_list(plist pl)
- {
- plist h, p, s;
- if (!pl || !pl->next)
- return pl;
- h=pl->next;
- s=h;
- p=s->next;
- h->next=NULL;
- while (p)
- {
- s=p;
- p=p->next;
- s->next=h;
- h=s;
- }
- pl->next=h;
- return pl;
- }
- void main()
- {
- int len, pos, *del;
- plist pl=NULL;
- del=(int *)malloc( sizeof ( int ));
- pl=init_list();
- isempty_list(pl);
- insert_item(pl, 1, 1);
- insert_item(pl, 2, 3);
- insert_item(pl, 3, 5);
- insert_item(pl, 4, 7);
- insert_item(pl, 5, 9);
- insert_item(pl, 6, 11);
- display(pl);
- len=len_list(pl);
- printf("link list len: %d/n" , len);
- pos=locate_item(pl, 7);
- printf("num 7 pos: %d/n" , pos);
- delete_item(pl, 3, del);
- printf("delete pos 3 num: %d/n" , *del);
- display(pl);
- printf("link list traverse.../n" );
- pl=traverse_list(pl);
- display(pl);
- destroy_list(pl);
- getch();
- }
运行结果:
=================================================
单向循环链表(测试通过)
测试环境: Win-TC
- #include <stdio.h>
- #include <malloc.h>
- struct _node
- {
- int data;
- struct _node *next;
- };
- typedef struct _node node, *plist;
- plist init_list()
- {
- plist pl=(plist)malloc(sizeof (node));
- if (!pl)
- {
- printf("error malloc fail.../n" );
- return NULL;
- }
- pl->data=-1;
- pl->next=pl; /* pl->next=NULL */
- return pl;
- }
- void insert_item(plist pl, int pos, int data)
- {
- int j=0;
- plist p,s;
- s=p=pl;
- while (p && j<pos-1)
- {
- p=p->next;
- j++;
- }
- if (!p || j>pos-1)
- {
- printf("Error insert fail.../n" );
- return ;
- }
- s=(plist)malloc(sizeof (node));
- if (!s)
- {
- printf("Error malloc fail.../n" );
- return ;
- }
- s->data=data;
- s->next=p->next;
- p->next=s;
- }
- int find_item(plist pl, int data)
- {
- plist s,p;
- s=p=pl;
- p=p->next;
- while (s != p)
- {
- if (data==p->data)
- return 1;
- p=p->next;
- }
- return 0;
- }
- void delete_item(plist pl, int data)
- {
- plist p,s;
- s=p=pl;
- if (data == p->data) /* first item is equal with data, then last item = second item */
- {
- s=p;
- while (s != p->next)
- p=p->next;
- p->next=s->next;
- return ;
- }
- while (s != p->next) /* first item is not equal with data */
- {
- if (data == p->next->data)
- {
- p->next=p->next->next;
- return ;
- }
- p=p->next;
- }
- }
- void display(plist pl)
- {
- plist s,p;
- s=p=pl;
- printf("%5d" , p->data); /* print first item */
- p=p->next;
- while (s != p)
- {
- printf("%5d" , p->data);
- p=p->next;
- }
- printf("/n/n" );
- }
- void main()
- {
- int f;
- plist pl;
- pl=init_list();
- insert_item(pl, 1, 1);
- insert_item(pl, 2, 3);
- insert_item(pl, 3, 5);
- insert_item(pl, 4, 7);
- insert_item(pl, 5, 9);
- display(pl);
- printf("Finding 3.../n" );
- f=find_item(pl, 3);
- if (f)
- printf("True find 3/n" );
- else
- printf("False find 3.../n" );
- printf("/nDeleting 1.../n" );
- delete_item(pl->next, 1);
- display(pl->next);
- getch();
- }
运行结果:
双向循环链表(测试通过)
测试环境: Win-TC
- #include <stdio.h>
- #include <malloc.h>
- struct _node
- {
- int data;
- struct _node *prior;
- struct _node *next;
- };
- typedef struct _node node, *plist;
- plist init_list()
- {
- plist p;
- p=(plist)malloc(sizeof (node));
- if (!p)
- {
- printf("Error, malloc fail.../n" );
- return NULL;
- }
- p->data=-1; /* head->data = -1 */
- p->prior=p;
- p->next=p;
- return p;
- }
- void insert_item(plist pl, int pos, int data)
- {
- int j=0;
- plist s,p;
- p=pl;
- while (p && j<pos-1)
- {
- p=p->next;
- j++;
- }
- if (!p || j>pos-1) /* pos is less than 1 or pos larger than len_list+1 */
- {
- printf("Error %d is invalide num.../n" , pos);
- return ;
- }
- s=(plist)malloc(sizeof (node));
- if (!s)
- {
- printf("Error, malloc fail.../n" );
- return NULL;
- }
- s->data=data;
- s->prior=p;
- s->next=p->next;
- p->next->prior=s;
- p->next=s;
- }
- int find_item(plist pl, int data)
- {
- plist s,p;
- s=p=pl;
- if (data == p->data)
- return 1;
- p=p->next;
- while (s != p)
- {
- if (data == p->data)
- return 1;
- p=p->next;
- }
- return 0;
- }
- void delete_item(plist pl, int data)
- {
- plist s,p;
- s=p=pl;
- if (data == p->data) /* first check equal */
- {
- p->prior->next=p->next;
- p->next=p->prior;
- return ;
- }
- while (s != p->next)
- {
- if (data == p->next->data)
- {
- p->next=p->next->next;
- p->next->next->prior=p;
- }
- p=p->next;
- }
- }
- void display(plist pl)
- {
- plist s,p;
- s=p=pl;
- printf("%5d" , p->data); /* first item, such as head->data is -1 */
- p=p->next;
- while (s != p)
- {
- printf("%5d" , p->data);
- p=p->next;
- }
- printf("/n/n" );
- }
- void main()
- {
- int f;
- plist pl;
- pl=init_list();
- insert_item(pl, 1, 1);
- insert_item(pl, 2, 3);
- insert_item(pl, 3, 5);
- insert_item(pl, 4, 7);
- insert_item(pl, 5, 9);
- display(pl);
- printf("Finding 3.../n" );
- f=find_item(pl->next->next, 3);
- if (f)
- printf("True find 3/n" );
- else
- printf("Fail find 3.../n" );
- printf("Finding 6.../n" );
- f=find_item(pl->prior->prior, 6);
- if (f)
- printf("True find 6/n" );
- else
- printf("Fail find 6.../n" );
- printf("/nDeleting 3.../n" );
- delete_item(pl->next->next, 3);
- display(pl);
- getch();
- }
======================================================
各种基本算法实现小结(二)—— 堆 栈
(均已测试通过)
==============================================================
栈——数组实现
测试环境:Win - TC
- #include <stdio.h>
- char stack[512];
- int top=0;
- void push( char c)
- {
- stack[top]=c;
- top++;
- }
- char pop()
- {
- top--;
- return stack[top];
- }
- int is_empty()
- {
- return 0==top;
- }
- void main()
- {
- push('1' );
- push('2' );
- push('3' );
- push('4' );
- push('5' );
- while (!is_empty())
- putchar(pop());
- putchar('/n' );
- getch();
- }
运行结果:
====================================================
栈 ——数组实现2
测试环境:Win - TC
- #include <stdio.h>
- #include <malloc.h>
- /* typedef int DataType; */
- #define DataType int
- #define MAX 1024
- typedef struct
- {
- DataType data[MAX];
- int top;
- }stack, *pstack;
- pstack *init_stack()
- {
- pstack ps;
- ps=(pstack)malloc(sizeof (stack));
- if (!ps)
- {
- printf("Error. fail malloc.../n" );
- return NULL;
- }
- ps->top=-1;
- return ps;
- }
- int empty_stack(pstack ps)
- {
- if (-1 == ps->top)
- return 1;
- else
- return 0;
- }
- int push(pstack ps, DataType data)
- {
- if (ps->top == MAX-1)
- {
- printf("Stack is full.../n" );
- return 0;
- }
- ps->top++;
- ps->data[ps->top]=data;
- return 1;
- }
- int pop(pstack ps, DataType *data)
- {
- if (empty_stack(ps))
- {
- printf("Stack is empty.../n" );
- return 0;
- }
- *data=ps->data[ps->top];
- ps->top--;
- return 1;
- }
- DataType top_stack(pstack ps)
- {
- if (empty_stack(ps))
- {
- printf("Stack is empty.../n" );
- return 0;
- }
- return ps->data[ps->top];
- }
- void display(pstack ps)
- {
- int i;
- if (empty_stack(ps))
- {
- printf("Stack is empty.../n" );
- return ;
- }
- printf("printf the items of stack.../n" );
- for (i=ps->top;i>-1;i--)
- printf("%4d" , ps->data[i]);
- printf("/n/n" );
- }
- void main()
- {
- int i, num, data, *pdata;
- pstack ps;
- ps=init_stack();
- printf("Enter stack num:" );
- scanf("%d" , &num);
- for (i=0;i<num;i++)
- {
- scanf("%d" , &data);
- push(ps, data);
- }
- display(ps);
- printf("Top is %d/n/n" , top_stack(ps));
- for (i=0;i<num;i++)
- {
- pop(ps, pdata);
- printf("%3d" , *pdata);
- }
- printf("/n/n" );
- display(ps);
- getch();
- }
运行结果:
====================================================
栈 ——链表实现
测试环境:Win - TC
- #include <stdio.h>
- #include <malloc.h>
- typedef char DataType;
- struct _node
- {
- DataType data;
- struct _node *next;
- };
- typedef struct _node node, *pstack;
- pstack init_stack()
- {
- pstack ps;
- ps=(pstack)malloc(sizeof (node));
- if (NULL == ps)
- {
- printf("Error. malloc is fail.../n" );
- return NULL;
- }
- ps->data=-1; /* base of stack: data=-1 and next=NULL */
- ps->next=NULL;
- return ps;
- }
- pstack push(pstack ps, DataType data)
- {
- pstack ptop;
- ptop=(pstack)malloc(sizeof (node));
- if (NULL == ptop)
- {
- printf("Error. malloc is fail.../n" );
- return NULL;
- }
- ptop->data=data;
- ptop->next=ps; /* insert new item */
- ps=ptop; /* move top */
- return ps;
- }
- pstack pop(pstack ps, DataType *data)
- {
- if (ps->next == NULL)
- {
- printf("stack is empty.../n" );
- return NULL;
- }
- *data=ps->data;
- ps=ps->next;
- return ps;
- }
- DataType top_stack(pstack ps)
- {
- if (ps->next == NULL) /* if empty */
- {
- printf("stack is empty.../n" );
- return -1;
- }
- return ps->data;
- }
- int len_stack(pstack ps)
- {
- int len=0;
- pstack ptop=ps;
- while (ptop->next)
- {
- len++;
- ptop=ptop->next;
- }
- return len;
- }
- void display(pstack ps)
- {
- pstack ptop;
- ptop=ps;
- while (ptop->next != NULL)
- {
- printf("%4c" , ptop->data);
- ptop=ptop->next;
- }
- printf("/n/n" );
- }
- void main()
- {
- pstack ps;
- DataType *data=(DataType *)malloc(sizeof (DataType));
- ps=init_stack();
- ps=push(ps, 'a' );
- ps=push(ps, 'b' );
- ps=push(ps, 'c' );
- ps=push(ps, 'd' );
- ps=push(ps, 'e' );
- display(ps);
- printf("len of stack is: %d/n/n" , len_stack(ps));
- printf("top of stack is: %c/n/n" , top_stack(ps));
- ps=pop(ps, data);
- printf("pop %c/n" ,*data);
- display(ps);
- ps=pop(ps, data);
- printf("pop %c/n" ,*data);
- display(ps);
- getch();
- }
运行结果:
========================================================
堆 ——链表实现
测试环境:Win - TC
- #include <stdio.h>
- #include <malloc.h>
- #include <stdlib.h>
- struct _node
- {
- int data;
- struct _node *next;
- };
- typedef struct _node node, *pnode;
- struct _linkqueue
- {
- pnode front;
- pnode rear;
- };
- typedef struct _linkqueue linkqueue, *plinkqueue;
- linkqueue init_queue()
- {
- linkqueue lq;
- lq.front=lq.rear=(pnode)malloc(sizeof (node));
- if (NULL == lq.front)
- {
- printf("Error. malloc is fail.../n" );
- exit(1);
- }
- lq.rear->data=lq.front->data=-1;
- lq.rear->next=lq.front->next=NULL;
- return lq;
- }
- int empty_queue(linkqueue lq)
- {
- if (lq.front == lq.rear)
- return 1;
- else
- return 0;
- }
- linkqueue insert_item(linkqueue lq, int data)
- {
- pnode pq;
- pq=(pnode)malloc(sizeof (node));
- if (pq == NULL)
- {
- printf("Error. malloc is fail.../n" );
- exit(1);
- }
- pq->data=data;
- pq->next=lq.rear->next;
- lq.rear->next=pq;
- lq.rear=lq.rear->next;
- return lq;
- }
- linkqueue delete_item(linkqueue lq, int *data)
- {
- if (empty_queue(lq))
- {
- printf("queue is empty.../n" );
- exit(1);
- }
- *data=lq.front->data;
- lq.front=lq.front->next;
- return lq;
- }
- int len_queue(linkqueue lq)
- {
- int len=0;
- while (lq.front)
- {
- len++;
- lq.front=lq.front->next;
- }
- return len;
- }
- void display(linkqueue lq)
- {
- linkqueue p;
- p=lq;
- if (empty_queue(lq))
- {
- printf("queue is empty.../n" );
- return ;
- }
- while (p.front->next)
- {
- printf("%4d" , p.front->data);
- p.front=p.front->next;
- }
- printf("%4d/n/n" , p.front->data);
- }
- void main()
- {
- int *data = ( int *)malloc( sizeof ( int ));
- linkqueue lq;
- lq=init_queue();
- lq=insert_item(lq, 1);
- lq=insert_item(lq, 2);
- lq=insert_item(lq, 3);
- lq=insert_item(lq, 4);
- lq=insert_item(lq, 5);
- display(lq);
- printf("len of queue is: %d/n/n" , len_queue(lq));
- lq=delete_item(lq, data);
- printf("delete %d/n" , *data);
- display(lq);
- lq=delete_item(lq, data);
- printf("delete %d/n" , *data);
- display(lq);
- getch();
- }
运行结果:
各种基本算法实现小结(三)—— 树与二叉树
(均已测试通过)
===================================================================
二叉树——先序
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <malloc.h>
- #include <stdlib.h>
- struct _node
- {
- char data;
- struct _node *lchild;
- struct _node *rchild;
- };
- typedef struct _node node, *pnode;
- pnode create_tree()
- {
- pnode pt;
- char data;
- scanf("%c" , &data);
- getchar();
- if (data== ' ' )
- pt=NULL;
- else
- {
- pt=(pnode)malloc(sizeof (node));
- pt->data=data;
- pt->lchild=create_tree();
- pt->rchild=create_tree();
- }
- return (pt);
- }
- void print_pretree(pnode ps)
- {
- if (ps != NULL)
- {
- printf("%3c" , ps->data);
- print_pretree(ps->lchild);
- print_pretree(ps->rchild);
- }
- }
- void main()
- {
- pnode ps;
- ps=create_tree();
- print_pretree(ps);
- printf("/n" );
- }
运行结果:
===========================================================
二叉树——各种操作
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <malloc.h>
- struct _node
- {
- char data;
- struct _node *lchild;
- struct _node *rchild;
- };
- typedef struct _node node, *pnode;
- int count_l=0; /* count leaf */
- int count_n=0; /* count node */
- pnode create_tree()
- {
- pnode pt;
- char data;
- scanf("%c" , &data);
- getchar();
- if (data== ' ' )
- pt=NULL;
- else
- {
- pt=(pnode)malloc(sizeof (node));
- pt->data=data;
- pt->lchild=create_tree();
- pt->rchild=create_tree();
- }
- return (pt);
- }
- void print_pretree(pnode ps)
- {
- if (ps != NULL)
- {
- printf("%3c" , ps->data);
- print_pretree(ps->lchild);
- print_pretree(ps->rchild);
- }
- }
- void print_midtree(pnode ps)
- {
- if (ps != NULL)
- {
- print_midtree(ps->lchild);
- printf("%3c" , ps->data);
- print_midtree(ps->rchild);
- }
- }
- void print_posttree(pnode ps)
- {
- if (ps != NULL)
- {
- print_posttree(ps->lchild);
- print_posttree(ps->rchild);
- printf("%3c" , ps->data);
- }
- }
- int count_leaf(pnode ps)
- {
- if (ps != NULL)
- {
- if (ps->lchild == NULL && ps->rchild == NULL)
- count_l++;
- count_leaf(ps->lchild);
- count_leaf(ps->rchild);
- }
- return count_l;
- }
- int count_node(pnode ps)
- {
- if (ps != NULL)
- {
- count_n++;
- count_node(ps->lchild);
- count_node(ps->rchild);
- }
- return count_n;
- }
- int count_depth(pnode ps)
- {
- int ldep, rdep;
- if (ps == NULL)
- return 0;
- else
- {
- ldep=count_depth(ps->lchild);
- rdep=count_depth(ps->rchild);
- return ldep>rdep ? (ldep+1) : (rdep+1);
- }
- }
- void main()
- {
- pnode ps;
- ps=create_tree();
- printf("pre order.../n" );
- print_pretree(ps);
- printf("/n" );
- printf("mid order.../n" );
- print_midtree(ps);
- printf("/n" );
- printf("post order.../n" );
- print_posttree(ps);
- printf("/n" );
- printf("number of leaf is: %d/n" , count_leaf(ps));
- printf("number of node is: %d/n" , count_node(ps));
- printf("max of depth is: %d/n" , count_depth(ps));
- }
运行结果:
===========================================================
二叉树——先序、中序、后序的递归与非递归实现
测试环境:VS2008 (C)
- #include "stdafx.h"
- #include <stdlib.h>
- #include <malloc.h>
- #define DataType char
- /**************************************/
- /******** 树的结构定义 ********/
- /**************************************/
- struct _tree
- {
- DataType data;
- struct _tree *lchild;
- struct _tree *rchild;
- };
- typedef struct _tree tree, *ptree;
- /**************************************/
- /******** 栈的结构定义 ********/
- /**************************************/
- struct _node
- {
- ptree pt;
- struct _node *next;
- };
- typedef struct _node node, *pnode;
- struct _stack
- {
- int size;
- pnode ptop;
- };
- typedef struct _stack stack, *pstack;
- /**************************************/
- /******** 堆的结构定义 ********/
- /**************************************/
- struct _queue
- {
- pnode front;
- pnode rear;
- };
- typedef struct _queue queue, *pqueue;
- /**************************************/
- /******** 栈的数据操作 ********/
- /**************************************/
- pstack init_stack()
- {
- pnode pn=NULL;
- pstack ps=NULL;
- pn=(pnode)malloc(sizeof (node));
- ps=(pstack)malloc(sizeof (stack));
- pn->pt=NULL;
- pn->next=NULL;
- ps->ptop=pn;
- return ps;
- }
- int empty_stack(pstack ps)
- {
- if (ps->ptop->next==NULL)
- return 1;
- else
- return 0;
- }
- void push_stack(pstack ps, ptree pt) /* flag for post tree: 0 for lchild; 1 for rchild */
- {
- pnode pn=NULL;
- pn=(pnode)malloc(sizeof (node));
- pn->pt=pt;
- pn->next=ps->ptop;
- ps->ptop=pn;
- }
- ptree pop_stack(pstack ps)
- {
- ptree pt=NULL;
- pnode pn=NULL;
- if (!empty_stack(ps))
- {
- pn=ps->ptop;
- ps->ptop=ps->ptop->next;
- pt=pn->pt;
- free(pn);
- }
- return pt;
- }
- ptree gettop_stack(pstack ps)
- {
- if (!empty_stack(ps))
- return ps->ptop->pt;
- }
- /**************************************/
- /******** 堆的数据操作 ********/
- /**************************************/
- queue init_queue()
- {
- pnode pn=NULL;
- queue qu;
- pn=(pnode)malloc(sizeof (node));
- pn->pt=NULL;
- pn->next=NULL;
- qu.front=qu.rear=pn;
- return qu;
- }
- int empty_queue(queue qu)
- {
- if (qu.front==qu.rear)
- return 1;
- else
- return 0;
- }
- void en_queue(queue qu, ptree pt)
- {
- pnode pn=NULL;
- pn=(pnode)malloc(sizeof (node));
- pn->pt;
- pn->next=qu.rear->next;
- qu.rear=pn;
- }
- ptree de_queue(queue qu)
- {
- ptree pt=NULL;
- pnode pn=NULL;
- if (!empty_queue(qu))
- {
- pn=qu.front;
- qu.front=qu.front->next;
- pt=pn->pt;
- free(pn);
- }
- return pt;
- }
- /**************************************/
- /******** 堆的数据操作 ********/
- /**************************************/
- ptree init_tree()
- {
- ptree pt=NULL;
- pt=(ptree)malloc(sizeof (tree));
- pt->data='0' ;
- pt->lchild=NULL;
- pt->rchild=NULL;
- return pt;
- }
- ptree create_tree()
- {
- char ch;
- ptree pt=NULL;
- scanf("%c" , &ch);
- getchar();
- if (ch== ' ' )
- return NULL;
- else
- {
- pt=(ptree)malloc(sizeof (tree));
- pt->data=ch;
- pt->lchild=create_tree();
- pt->rchild=create_tree();
- }
- return pt;
- }
- void print_pretree(ptree pt)
- {
- if (pt!=NULL)
- {
- printf("%3c" , pt->data);
- print_pretree(pt->lchild);
- print_pretree(pt->rchild);
- }
- }
- void print_pretree2(ptree pt)
- {
- pstack ps=NULL;
- ptree p=NULL;
- ps=init_stack();
- p=pt;
- while (p!=NULL || !empty_stack(ps))
- {
- while (p!=NULL)
- {
- printf("%3c" , p->data);
- push_stack(ps, p);
- p=p->lchild;
- }
- if (!empty_stack(ps))
- {
- p=pop_stack(ps);
- p=p->rchild;
- }
- }
- }
- void print_midtree(ptree pt)
- {
- if (pt!=NULL)
- {
- print_midtree(pt->lchild);
- printf("%3c" , pt->data);
- print_midtree(pt->rchild);
- }
- }
- void print_midtree2(ptree pt)
- {
- pstack ps=NULL;
- ptree p=NULL;
- ps=init_stack();
- p=pt;
- while (p!=NULL || !empty_stack(ps))
- {
- while (p!=NULL)
- {
- push_stack(ps, p);
- p=p->lchild;
- }
- if (!empty_stack(ps))
- {
- p=pop_stack(ps);
- printf("%3c" , p->data);
- p=p->rchild;
- }
- }
- }
- void print_posttree(ptree pt)
- {
- if (pt!=NULL)
- {
- print_posttree(pt->lchild);
- print_posttree(pt->rchild);
- printf("%3c" , pt->data);
- }
- }
- void print_posttree2(ptree pt)
- {
- pstack ps=NULL;
- ptree p=NULL;
- ptree p2=NULL;
- ptree lastvisit=NULL;
- ps=init_stack();
- p=pt;
- while (p!=NULL || !empty_stack(ps))
- {
- while (p!=NULL)
- {
- push_stack(ps, p);
- p=p->lchild;
- }
- p2=gettop_stack(ps); /* top: rchild==null or sub_root */
- if (p2->rchild==NULL || p2->rchild==lastvisit)
- {
- printf("%3c" , p2->data);
- lastvisit=pop_stack(ps); /* pop */
- }
- else
- p=p2->rchild;
- }
- }
- int _tmain( int argc, _TCHAR* argv[])
- {
- ptree pt=NULL;
- /*pt=init_tree();*/
- printf("Create recursion tree.../n" );
- pt=create_tree();
- /************ recursion ************/
- printf("/n/nrecursion..." );
- printf("/npre tree.../n" );
- print_pretree(pt);
- printf("/nmid tree.../n" );
- print_midtree(pt);
- printf("/npost tree.../n" );
- print_posttree(pt);
- /************ stack ************/
- printf("/n/nstack, non recursion..." );
- printf("/npre tree.../n" );
- print_pretree2(pt);
- printf("/nmid tree.../n" );
- print_midtree2(pt);
- printf("/npost tree.../n" );
- print_posttree2(pt);
- printf("/n" );
- return 0;
- }
运行结果:
===========================================================
二叉树——学习交流与修正改进
在网上看到了好多人转载这段代码,我也复制、粘贴下来学习
但在VC6.0编译器上运行并未通过,于是调试修正了几个小bug
测试运行通过后的代码粘贴如下,希望对大家学习有所帮助,谢谢!
本算法源码引用网址:http://www.ccrun.com/article.asp?i=292&d=y6y12h (二叉树实现源代码)
测试环境:VC 6.0 (C)
- #include <conio.h>
- #include <stdio.h>
- #include <stdlib.h>
- #define OK 1
- #define ERROR 0
- #define TRUE 1
- #define FALSE 0
- #define OVERFLOW -2
- typedef int status;
- typedef struct BiNode
- {
- char Data;
- struct BiNode* lChild;
- struct BiNode* rChild;
- }BiNode,*pBiNode;
- status CreateTree(BiNode** pTree);
- status PreOrderTraval(BiNode* pTree);
- status InOrderTraval(BiNode* pTree);
- status PostOrderTraval(BiNode* pTree);
- status Visit(char Data);
- status ShowLeaves(BiNode* pTree);
- status DelTree(BiNode* pTree);
- status Display(BiNode* pTree,int Level);
- status Clear(BiNode* pTree);
- BiNode *pRoot=NULL;
- void main()
- {
- CreateTree(&pRoot);
- printf("/nPreOrder:" );
- PreOrderTraval(pRoot);
- printf("/n" );
- printf("/nInOrder:" );
- InOrderTraval(pRoot);
- printf("/n" );
- printf("/nPostOrder:" );
- PostOrderTraval(pRoot);
- printf("/n" );
- printf("/nShowLeaves:" );
- ShowLeaves(pRoot);
- printf("/n-----------------------/n" );
- printf("/n" );
- Display(pRoot,0);
- printf("/n" );
- printf("/nDeleting Tree:/n" );
- DelTree(pRoot);
- printf("BiTree Deleted." );
- }
- status CreateTree(BiNode** pTree)
- {
- char ch;
- scanf("%c" ,&ch);
- getchar();
- if (ch== ' ' ) /* NOTE: enter space, example: [ab cd e ] */
- {
- (*pTree)=NULL;
- }
- else
- {
- if (!((*pTree)=(BiNode*)malloc( sizeof (BiNode))))
- {
- exit(OVERFLOW);
- }
- (*pTree)->Data=ch;
- CreateTree(&((*pTree)->lChild));
- CreateTree(&((*pTree)->rChild));
- }
- return OK;
- }
- status PreOrderTraval(BiNode* pTree)
- {
- if (pTree)
- {
- if (Visit(pTree->Data))
- {
- if (PreOrderTraval(pTree->lChild))
- {
- if (PreOrderTraval(pTree->rChild))
- {
- return OK;
- }
- }
- }
- return ERROR;
- }
- else
- {
- return OK;
- }
- }
- status InOrderTraval(BiNode* pTree)
- {
- if (pTree)
- {
- if (InOrderTraval(pTree->lChild))
- {
- if (Visit(pTree->Data))
- {
- if (InOrderTraval(pTree->rChild))
- {
- return OK;
- }
- }
- return ERROR;
- }
- return ERROR;
- }
- else
- return OK;
- }
- status PostOrderTraval(BiNode* pTree)
- {
- if (pTree)
- {
- if (PostOrderTraval(pTree->lChild))
- {
- if (PostOrderTraval(pTree->rChild))
- {
- if (Visit(pTree->Data))
- {
- return OK;
- }
- return ERROR;
- }
- }
- return ERROR;
- }
- else
- {
- return OK;
- }
- }
- status Visit(char Data)
- {
- printf("%c" ,Data);
- return OK;
- }
- status Display(BiNode* pTree,int Level)
- {
- int i;
- if (pTree==NULL)
- return FALSE;
- Display(pTree->lChild,Level+1);
- for (i=0;i<Level-1;i++)
- {
- printf(" " );
- }
- if (Level>=1)
- {
- printf("--" );
- }
- printf("%c/n" ,pTree->Data);
- Display(pTree->rChild,Level+1);
- return TRUE;
- }
- status ShowLeaves(BiNode* pTree)
- {
- if (pTree)
- {
- if (ShowLeaves(pTree->lChild))
- {
- if (ShowLeaves(pTree->rChild))
- {
- if ((pTree->lChild==NULL)&&(pTree->rChild==NULL))
- {
- if (!Visit(pTree->Data))
- {
- return ERROR;
- }
- }
- return OK;
- }
- }
- return ERROR;
- }
- else
- {
- return OK;
- }
- }
- status DelTree(BiNode* pTree)
- {
- if (pTree)
- {
- if (DelTree(pTree->lChild))
- {
- if (DelTree(pTree->rChild))
- {
- printf("Deleting %c/n" ,pTree->Data);
- free((void *)pTree);
- return OK;
- }
- }
- return ERROR;
- }
- else
- return OK;
- }
运行结果:
===========================================================
上述代码改进后,逻辑更清晰 ,并添加了计算二叉树层次的函数 ShowDepth(BiNode* pTree)
具体代码如下:
- #include <conio.h>
- #include <stdio.h>
- #include <stdlib.h>
- #define OK 1
- #define ERROR 0
- #define TRUE 1
- #define FALSE 0
- #define OVERFLOW -2
- typedef int status;
- typedef struct BiNode
- {
- char Data;
- struct BiNode* lChild;
- struct BiNode* rChild;
- }BiNode,*pBiNode;
- status CreateTree(BiNode** pTree);
- status PreOrderTraval(BiNode* pTree);
- status InOrderTraval(BiNode* pTree);
- status PostOrderTraval(BiNode* pTree);
- status Visit(char Data);
- status ShowLeaves(BiNode* pTree);
- status ShowDepth(BiNode* pTree);
- status DelTree(BiNode* pTree);
- status Display(BiNode* pTree,int Level);
- status Clear(BiNode* pTree);
- BiNode *pRoot=NULL;
- void main()
- {
- CreateTree(&pRoot);
- printf("/nPreOrder:" );
- PreOrderTraval(pRoot);
- printf("/n" );
- printf("/nInOrder:" );
- InOrderTraval(pRoot);
- printf("/n" );
- printf("/nPostOrder:" );
- PostOrderTraval(pRoot);
- printf("/n" );
- printf("/nShowLeaves:" );
- ShowLeaves(pRoot);
- printf("/nShowDepth:%d/n" , ShowDepth(pRoot));
- printf("/n------------------/n" );
- printf("/n" );
- Display(pRoot,0);
- printf("/n" );
- printf("/nDeleting Tree:/n" );
- DelTree(pRoot);
- printf("BiTree Deleted." );
- }
- status CreateTree(BiNode** pTree)
- {
- char ch;
- scanf("%c" ,&ch);
- getchar();
- if (ch== ' ' ) /* NOTE: enter space, example: [ab cd e ] */
- (*pTree)=NULL;
- else
- {
- if (!((*pTree)=(BiNode*)malloc( sizeof (BiNode))))
- exit(OVERFLOW);
- (*pTree)->Data=ch;
- CreateTree(&((*pTree)->lChild));
- CreateTree(&((*pTree)->rChild));
- }
- return OK;
- }
- status PreOrderTraval(BiNode* pTree)
- {
- if (pTree)
- {
- Visit(pTree->Data);
- PreOrderTraval(pTree->lChild);
- PreOrderTraval(pTree->rChild);
- }
- return OK;
- }
- status InOrderTraval(BiNode* pTree)
- {
- if (pTree)
- {
- InOrderTraval(pTree->lChild);
- Visit(pTree->Data);
- InOrderTraval(pTree->rChild);
- }
- return OK;
- }
- status PostOrderTraval(BiNode* pTree)
- {
- if (pTree)
- {
- PostOrderTraval(pTree->lChild);
- PostOrderTraval(pTree->rChild);
- Visit(pTree->Data);
- }
- return OK;
- }
- status Visit(char Data)
- {
- printf("%c" ,Data);
- return OK;
- }
- status Display(BiNode* pTree,int Level)
- {
- int i;
- if (pTree==NULL)
- return FALSE;
- Display(pTree->lChild,Level+1);
- for (i=0;i<Level-1;i++)
- {
- printf(" " );
- }
- if (Level>=1)
- {
- printf("--" );
- }
- printf("%c/n" ,pTree->Data);
- Display(pTree->rChild,Level+1);
- return TRUE;
- }
- status ShowLeaves(BiNode* pTree)
- {
- if (pTree)
- {
- ShowLeaves(pTree->lChild);
- ShowLeaves(pTree->rChild);
- if ((pTree->lChild==NULL)&&(pTree->rChild==NULL))
- Visit(pTree->Data);
- }
- return OK;
- }
- status ShowDepth(BiNode* pTree)
- {
- int ldep=0, rdep=0;
- if (!pTree)
- return 0;
- else
- {
- ldep=ShowDepth(pTree->lChild);
- rdep=ShowDepth(pTree->rChild);
- return ldep>rdep ? (ldep+1) : (rdep+1);
- }
- }
- status DelTree(BiNode* pTree)
- {
- if (pTree)
- {
- DelTree(pTree->lChild);
- DelTree(pTree->rChild);
- printf("Deleting %c/n" ,pTree->Data);
- free((void *)pTree);
- }
- return OK;
- }
运行结果:
===========================================================
各种基本算法实现小结(四)—— 图及其遍历
(均已测试通过)
====================================================================
图——深度优先和广度优先算法
无向图用二维邻接矩阵表示
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <malloc.h>
- #include <stdlib.h>
- #define INFINITY 32767
- #define MAX_VEX 20
- #define QUEUE_SIZE (MAX_VERTEX+1)
- #define DataType char /* vertext's info */
- int *visited; /* Node: visited flag with dynamic array, good idea ! */
- /* init queue for bfs */
- struct _node
- {
- int v_num;
- struct _node *next;
- };
- typedef struct _node node, *pnode;
- struct _queue
- {
- pnode front;
- pnode rear;
- };
- typedef struct _queue queue, *pqueue;
- struct _graph
- {
- DataType *vexs;
- int arcs[MAX_VEX][MAX_VEX];
- int vexnum, arcnum;
- };
- typedef struct _graph graph, *pgraph;
- /* operation of queue */
- queue init_queue()
- {
- queue qu;
- qu.front=qu.rear=(pnode)malloc(sizeof (node));
- if (qu.front == NULL)
- exit(1);
- qu.rear->next=NULL;
- return qu;
- }
- void en_queue(pqueue pqu, int v_num)
- {
- pnode pn;
- pn=(pnode)malloc(sizeof (node));
- if (pqu->front == NULL)
- exit(1);
- pn->v_num=v_num;
- pn->next=NULL;
- pqu->rear->next=pn;
- pqu->rear=pqu->rear->next;
- }
- int isempty_queue(pqueue pqu)
- {
- if (pqu->front == pqu->rear)
- return 1;
- else
- return 0;
- }
- int de_queue(pqueue pqu)
- {
- pnode pn;
- int d;
- if (isempty_queue(pqu))
- return -1;
- pn=pqu->front;
- d=pn->v_num;
- pqu->front=pn->next;
- free(pn);
- return d;
- }
- int locate(graph g, DataType data)
- {
- int i;
- for (i=0;i<g.vexnum;i++)
- if (g.vexs[i] == data)
- return i;
- return -1;
- }
- graph create_graph()
- {
- int i,j,w, s1,s2;
- DataType ch1,ch2,tmp;
- graph g;
- printf("g sizeof: %d/n" , sizeof (g));
- printf("Enter vexnum arcnum:" );
- scanf("%d %d" , &g.vexnum, &g.arcnum);
- tmp=getchar();
- g.vexs=(DataType *)malloc(sizeof (DataType));
- if (g.vexs == NULL)
- exit(1);
- printf("Enter %d vertext,please.../n" , g.vexnum);
- for (i=0;i<g.vexnum;i++)
- {
- printf("vex %d: " , i);
- scanf("%c" , &g.vexs[i]);
- tmp=getchar();
- //visited[i]=0;
- }
- for (i=0;i<g.vexnum;i++)
- for (j=0;j<g.vexnum;j++)
- g.arcs[i][j]=INFINITY;
- printf("Enter %d arcs:/n" , g.arcnum);
- for (i=0;i<g.arcnum;i++)
- {
- printf("arc %d: " , i);
- scanf("%c %c %d" , &ch1, &ch2, &w);
- tmp=getchar();
- s1=locate(g, ch1);
- s2=locate(g, ch2);
- g.arcs[s1][s2]=g.arcs[s2][s1]=w; /* NOTE: weight */
- }
- return g;
- }
- int firstvex_graph(graph g, int k)
- {
- int i;
- if (k>=0 && k<g.vexnum)
- for (i=0;i<g.vexnum;i++)
- if (g.arcs[k][i] != INFINITY)
- return i;
- return -1;
- }
- int nextvex_graph(graph g, int i, int j)
- {
- int k;
- if (i>=0 && i<g.vexnum && j>=0 && j<g.vexnum)
- for (k=j+1; k<g.vexnum; k++)
- if (g.arcs[i][k] != INFINITY)
- return k;
- return -1;
- }
- void dfs(graph g, int k)
- {
- int i;
- if (k == -1)
- {
- for (i=0;i<g.vexnum;i++)
- if (!visited[i])
- dfs(g,i);
- }
- else
- {
- visited[k]=1;
- printf("%c " , g.vexs[k]);
- for (i=firstvex_graph(g,k);i>=0;i=nextvex_graph(g,k,i))
- if (!visited[i])
- dfs(g,i);
- }
- }
- void bfs(graph g)
- {
- int i,j,k;
- queue qu;
- qu=init_queue();
- for (i=0;i<g.vexnum;i++)
- if (!visited[i])
- {
- visited[i] =1;
- printf("%c " , g.vexs[i]);
- en_queue(&qu, i);
- while (!isempty_queue(&qu))
- {
- k=de_queue(&qu);
- for (j=firstvex_graph(g,k); j>=0;j=nextvex_graph(g,k,j))
- if (!visited[j])
- {
- visited[j]=1;
- printf("%c " , g.vexs[j]);
- en_queue(&qu, j);
- }
- }
- }
- }
- void main()
- {
- int i;
- graph g;
- g=create_graph();
- visited=(int *)malloc(g.vexnum* sizeof ( int ));
- for (i=0;i<g.vexnum;i++)
- visited[i]=0;
- printf("/n/n dfs:" );
- dfs(g,-1);
- for (i=0;i<g.vexnum;i++)
- visited[i]=0;
- printf("/n bfs:" );
- bfs(g);
- if (visited)
- free(visited);
- printf("/n" );
- }
运行结果:
======================================================
图 ——深度优先
测试环境:VS2008 (C)
- #include "stdafx.h"
- #include <stdlib.h>
- #include <malloc.h>
- #define MAX_VEX 20
- #define INFINITY 65535
- int *visited;
- struct _node
- {
- int vex_num;
- struct _node *next;
- };
- typedef struct _node node, *pnode;
- struct _graph
- {
- char *vexs;
- int arcs[MAX_VEX][MAX_VEX];
- int vexnum, arcnum;
- };
- typedef struct _graph graph, *pgraph;
- int locate(graph g, char ch)
- {
- int i;
- for (i=1; i<=g.vexnum; i++)
- if (g.vexs[i]==ch)
- return i;
- return -1;
- }
- graph create_graph()
- {
- int i, j, w, p1, p2;
- char ch1, ch2;
- graph g;
- printf("Enter vexnum arcnum: " );
- scanf("%d %d" , &g.vexnum, &g.arcnum);
- getchar();
- for (i=1; i<=g.vexnum; i++)
- for (j=1; j<g.vexnum; j++)
- g.arcs[i][j]=INFINITY;
- g.vexs=(char *)malloc( sizeof ( char ));
- printf("Enter %d vexnum.../n" , g.vexnum);
- for (i=1; i<=g.vexnum; i++)
- {
- printf("vex %d: " , i);
- scanf("%c" , &g.vexs[i]);
- getchar();
- }
- printf("Enter %d arcnum.../n" , g.arcnum);
- for (i=1; i<=g.arcnum; i++)
- {
- printf("arc %d: " , i);
- scanf("%c %c %d" , &ch1, &ch2, &w);
- getchar();
- p1=locate(g, ch1);
- p2=locate(g, ch2);
- g.arcs[p1][p2]=g.arcs[p2][p1]=w;
- }
- return g;
- }
- int firstvex_graph(graph g, int i)
- {
- int k;
- if (i>=1 && i<=g.vexnum)
- for (k=1; k<=g.vexnum; k++)
- if (g.arcs[i][k]!=INFINITY)
- return k;
- return -1;
- }
- int nextvex_graph(graph g, int i, int j)
- {
- int k;
- if (i>=1 && i<=g.vexnum && j>=1 && j<=g.vexnum)
- for (k=j+1; k<=g.vexnum; k++)
- if (g.arcs[i][k]!=INFINITY)
- return k;
- return -1;
- }
- void dfs(graph g, int i)
- {
- int k, j;
- if (!visited[i])
- {
- visited[i]=1;
- printf("%c" , g.vexs[i]);
- for (j=firstvex_graph(g, i); j>=1; j=nextvex_graph(g, i, j))
- if (!visited[j])
- dfs(g, j);
- }
- }
- void dfs_graph(graph g)
- {
- int i;
- visited=(int *)malloc((g.vexnum+1)* sizeof ( int ));
- for (i=1; i<=g.vexnum; i++)
- visited[i]=0;
- for (i=1; i<g.vexnum; i++)
- if (!visited[i])
- dfs(g, i);
- }
- int _tmain( int argc, _TCHAR* argv[])
- {
- graph g;
- g=create_graph();
- dfs_graph(g);
- printf("/n" );
- return 0;
- }
======================================================
图 ——广度优先
测试环境:VS2008 (C)
- #include "stdafx.h"
- #include <stdlib.h>
- #include <malloc.h>
- #define MAX_VEX 20
- #define INFINITY 65535
- int *visited;
- struct _node
- {
- int data;
- struct _node *next;
- };
- typedef struct _node node, *pnode;
- struct _queue
- {
- pnode front;
- pnode rear;
- };
- typedef struct _queue queue, *pqueue;
- queue init_queue()
- {
- pnode pn=NULL;
- queue qu;
- pn=(pnode)malloc(sizeof (node));
- if (pn==NULL)
- printf("init queue, malloc is fail.../n" );
- pn->data=-1;
- pn->next=NULL;
- qu.front=qu.rear=pn;
- return qu;
- }
- int empty_queue(queue qu)
- {
- if (qu.rear==qu.front)
- return 0;
- else
- return 1;
- }
- void en_queue(pqueue pqu, int data)
- {
- pnode pn=NULL;
- if (pqu->rear==NULL)
- return ;
- pn=(pnode)malloc(sizeof (node));
- pn->data=data;
- pn->next=pqu->rear->next;
- pqu->rear->next=pn;
- pqu->rear=pn;
- }
- int de_queue(pqueue pqu)
- {
- int data;
- pnode pn=NULL;
- if (pqu->front->next==NULL)
- return -1;
- pn=pqu->front->next;
- pqu->front=pqu->front->next;
- data=pn->data;
- free(pn);
- return data;
- }
- struct _graph
- {
- char *vexs;
- int arcs[MAX_VEX][MAX_VEX];
- int vexnum, arcnum;
- };
- typedef _graph graph, *pgraph;
- int locate(graph g, char ch)
- {
- int i;
- for (i=1; i<=g.vexnum; i++)
- if (g.vexs[i]==ch)
- return i;
- return -1;
- }
- graph create_graph()
- {
- int i, j, w, p1, p2;
- char ch1, ch2;
- graph g;
- printf("Enter vexnum arcnum: " );
- scanf("%d %d" , &g.vexnum, &g.arcnum);
- getchar();
- for (i=1; i<=g.vexnum; i++)
- for (j=1; j<g.vexnum; j++)
- g.arcs[i][j]=INFINITY;
- g.vexs=(char *)malloc((g.vexnum+1)* sizeof ( char ));
- printf("Enter %d vexnum.../n" , g.vexnum);
- for (i=1; i<=g.vexnum; i++)
- {
- printf("vex %d: " , i);
- scanf("%c" , &g.vexs[i]);
- getchar();
- }
- printf("Enter %d arcnum.../n" , g.arcnum);
- for (i=1; i<=g.arcnum; i++)
- {
- printf("arc %d: " , i);
- scanf("%c %c %d" , &ch1, &ch2, &w);
- getchar();
- p1=locate(g, ch1);
- p2=locate(g, ch2);
- g.arcs[p1][p2]=g.arcs[p2][p1]=w;
- }
- return g;
- }
- int firstvex_graph(graph g, int i)
- {
- int k;
- if (i>=1 && i<=g.vexnum)
- for (k=1; k<=g.vexnum; k++)
- if (g.arcs[i][k]!=INFINITY)
- return k;
- return -1;
- }
- int nextvex_graph(graph g, int i, int j)
- {
- int k;
- if (i>=1 && i<=g.vexnum && j>=1 && j<=g.vexnum)
- for (k=j+1; k<=g.vexnum; k++)
- if (g.arcs[i][k]!=INFINITY)
- return k;
- return -1;
- }
- void bfs(graph g)
- {
- int i, ivex, inextvex;
- visited=(int *)malloc((g.vexnum+1)* sizeof ( int ));
- for (i=1; i<=g.vexnum; i++)
- visited[i]=0;
- queue qu=init_queue();
- for (i=1; i<=g.vexnum; i++)
- {
- if (!visited[i])
- {
- visited[i]=1;
- printf("%c" , g.vexs[i]);
- en_queue(&qu, i);
- }
- while (!empty_queue(qu))
- {
- ivex=de_queue(&qu);
- for (inextvex=firstvex_graph(g, ivex); inextvex>=1; inextvex=nextvex_graph(g, ivex, inextvex))
- if (!visited[inextvex])
- {
- visited[inextvex]=1;
- printf("%c" , g.vexs[inextvex]);
- en_queue(&qu, inextvex);
- }
- }
- }
- }
- int _tmain( int argc, _TCHAR* argv[])
- {
- graph g;
- g=create_graph();
- bfs(g);
- printf("/n" );
- return 0;
- }
======================================================
图 ——深度优先和广度优先算法2(网摘)
本文引用网址:http://bbs.bccn.net/thread-155311-1-1.html(编程论坛)
看到本算法在网上转载较多,比较流行,且能直接运行
但发现大多转载中,也把DFS与BFS正好写反了,对此本文已修正
此外,本算法混用了C与C++,不够单纯,申请的指针空间也未及时释放
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <malloc.h>
- #define INFINITY 32767
- #define MAX_VEX 20
- #define QUEUE_SIZE (MAX_VEX+1)
- bool *visited;
- typedef struct
- {
- char *vexs; //顶点向量
- int arcs[MAX_VEX][MAX_VEX]; //邻接矩阵
- int vexnum,arcnum; //图的当前顶点数和弧数
- }Graph;
- //队列类
- class Queue
- {
- public :
- void InitQueue(){
- base=(int *)malloc(QUEUE_SIZE* sizeof ( int ));
- front=rear=0;
- }
- void EnQueue( int e)
- {
- base[rear]=e;
- rear=(rear+1)%QUEUE_SIZE;
- }
- void DeQueue( int &e)
- {
- e=base[front];
- front=(front+1)%QUEUE_SIZE;
- }
- public :
- int *base;
- int front;
- int rear;
- };
- //图G中查找元素c的位置
- int Locate(Graph G, char c)
- {
- for ( int i=0;i<G.vexnum;i++)
- if (G.vexs[i]==c)
- return i;
- return -1;
- }
- //创建无向网
- void CreateUDN(Graph &G){
- int i,j,w,s1,s2;
- char a,b,temp;
- printf("输入顶点数和弧数: " );
- scanf("%d%d" ,&G.vexnum,&G.arcnum);
- temp=getchar(); //接收回车
- G.vexs=(char *)malloc(G.vexnum* sizeof ( char )); //分配顶点数目
- printf("输入%d个顶点./n" ,G.vexnum);
- for (i=0;i<G.vexnum;i++) //初始化顶点
- {
- printf("输入顶点%d: " ,i);
- scanf("%c" ,&G.vexs[i]);
- temp=getchar(); //接收回车
- }
- for (i=0;i<G.vexnum;i++) //初始化邻接矩阵
- for (j=0;j<G.vexnum;j++)
- G.arcs[i][j]=INFINITY;
- printf("输入%d条弧./n" ,G.arcnum);
- for (i=0;i<G.arcnum;i++)
- { //初始化弧
- printf("输入弧%d: " ,i);
- scanf("%c %c %d" ,&a,&b,&w); //输入一条边依附的顶点和权值
- temp=getchar(); //接收回车
- s1=Locate(G,a);
- s2=Locate(G,b);
- G.arcs[s1][s2]=G.arcs[s2][s1]=w;
- }
- }
- //图G中顶点k的第一个邻接顶点
- int FirstVex(Graph G, int k)
- {
- if (k>=0 && k<G.vexnum) //k合理
- for ( int i=0;i<G.vexnum;i++)
- if (G.arcs[k][i]!=INFINITY) return i;
- return -1;
- }
- //图G中顶点i的第j个邻接顶点的下一个邻接顶点
- int NextVex(Graph G, int i, int j)
- {
- if (i>=0 && i<G.vexnum && j>=0 && j<G.vexnum) //i,j合理
- for ( int k=j+1;k<G.vexnum;k++)
- if (G.arcs[i][k]!=INFINITY)
- return k;
- return -1;
- }
- //深度优先遍历
- void DFS(Graph G, int k)
- {
- int i;
- if (k==-1) //第一次执行DFS时,k为-1
- {
- for (i=0;i<G.vexnum;i++)
- if (!visited[i])
- DFS(G,i); //对尚未访问的顶点调用DFS
- }
- else
- {
- visited[k]=true ;
- printf("%c " ,G.vexs[k]); //访问第k个顶点
- for (i=FirstVex(G,k);i>=0;i=NextVex(G,k,i))
- if (!visited[i]) //对k的尚未访问的邻接顶点i递归调用DFS
- DFS(G,i);
- }
- }
- //广度优先遍历
- void BFS(Graph G)
- {
- int k;
- Queue Q; //辅助队列Q
- Q.InitQueue();
- for ( int i=0;i<G.vexnum;i++)
- if (!visited[i]) //i尚未访问
- {
- visited[i]=true ;
- printf("%c " ,G.vexs[i]);
- Q.EnQueue(i); //i入列
- while (Q.front!=Q.rear)
- {
- Q.DeQueue(k); //队头元素出列并置为k
- for ( int w=FirstVex(G,k);w>=0;w=NextVex(G,k,w))
- if (!visited[w]) //w为k的尚未访问的邻接顶点
- {
- visited[w]=true ;
- printf("%c " ,G.vexs[w]);
- Q.EnQueue(w);
- }
- }
- }
- }
- //主函数
- void main(){
- int i;
- Graph G;
- CreateUDN(G);
- visited=(bool *)malloc(G.vexnum* sizeof ( bool ));
- printf("/n深度优先遍历: " );
- for (i=0;i<G.vexnum;i++)
- visited[i]=false ;
- DFS(G,-1); /* NODE: DFS */
- printf("/n广度优先遍历: " );
- for (i=0;i<G.vexnum;i++)
- visited[i]=false ;
- BFS(G); /* NODE: BFS */
- printf("/n程序结束./n" );
- }
运行结果:
======================================================
- #include <iostream.h>
- #include <stdlib.h>
- #define INFINITY 0
- #define MAX_VERTEX_NUM 10 //最大顶点数
- #define MAX_EDGE_NUM 40 //最大边数
- typedef enum {DG,DN,UDG,UDN}Graphkind;
- typedef char VertexType; //顶点数据类型
- typedef struct ArcCell
- {
- int adj; //无权图,1或0表示相邻否;带权图则是权值。
- //int *info;
- }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
- typedef struct
- {
- VertexType vexs[MAX_VERTEX_NUM]; //顶点向量
- AdjMatrix arcs; //邻接矩阵
- int vexnum,arcnum; //图的当前顶点数和弧数。
- Graphkind kind;
- }MGraph;
- int LocateVex(MGraph G,VertexType v1)
- {
- int i;
- for (i=0;i<G.vexnum;i++)
- if (G.vexs[i]==v1)
- return i;
- return -1;
- }
- int CreatUDN(MGraph &G)
- // 采用数组表示法,构造无向网 G
- {
- VertexType v1,v2;
- int w,j;
- cout<<"输入图的顶点数" <<endl;
- cin>>G.vexnum;
- cout<<"输入图的弧数" <<endl;
- cin>>G.arcnum;
- for ( int i=0;i<G.vexnum;i++)
- {
- cout<<"输入顶点向量" <<endl;
- cin>>G.vexs[i];
- }
- for (i=0;i<G.vexnum;i++)
- for (j=0;j<G.vexnum;j++)
- {
- G.arcs[i][j].adj=INFINITY;
- }
- for ( int k=0;k<G.arcnum;++k) //构造邻接矩阵
- {
- cout<<"输入边依附的两个顶点" <<endl;
- cin>>v1>>v2;
- cout<<"输入此边的权值" <<endl;
- cin>>w;
- i=LocateVex(G,v1);
- j=LocateVex(G,v2);
- G.arcs[i][j].adj=w;
- G.arcs[j][i].adj=G.arcs[i][j].adj;
- }
- return 1;
- }
- void dispMGraph(MGraph G)
- {
- cout<<"图的邻接矩阵图是:" <<endl;
- for ( int i=0;i<G.vexnum;i++)
- {
- for ( int j=0;j<G.vexnum;j++)
- cout<<" " <<G.arcs[i][j].adj;
- cout<<endl;
- }
- }
- void main()
- {
- MGraph G;
- CreatUDN(G);
- dispMGraph(G);
- }
- // 邻接表 表示:
- #include <iostream.h>
- #include <stdlib.h>
- #define MAX_VERTEX_NUM 20 //最大顶点数
- #define MAX_EDGE_NUM 40 //最大边数
- int visited[ MAX_VERTEX_NUM];
- typedef int VertexType ; //顶点数据类型
- typedef struct ArcNode
- {
- int adjvex;
- int weight;
- struct ArcNode *nextarc;
- }ArcNode;
- typedef struct VNode
- {
- VertexType data;
- ArcNode *firstarc;
- }VNode,AdjList[MAX_VERTEX_NUM];
- typedef struct
- {
- AdjList vertices;
- int vexnum,arcnum;
- int kind;
- }ALGraph;
- void CreateDG(ALGraph &G)
- {
- int i,j,k;
- ArcNode *p;
- cout<<"创建一个图:" <<endl;
- cout<<"顶点数:" ; cin>>G.vexnum;cout<<endl;
- cout<<"边数:" ; cin>>G.arcnum; cout<<endl;
- for (i=0;i<G.vexnum;i++)
- {
- G.vertices[i].data=i;
- G.vertices[i].firstarc=NULL;
- }
- for (k=0;k<G.arcnum;k++)
- {
- cout<<"请输入第" <<k+1<< "条边:" ;
- cin>>i>>j;
- p=(ArcNode*)malloc(sizeof (ArcNode));
- p->adjvex=j;
- p->nextarc=G.vertices[i].firstarc;
- G.vertices[i].firstarc=p;
- }
- }
- void Disp(ALGraph G)
- {
- int i,j;
- ArcNode *p;
- cout<<"输出图为:" <<endl;
- for (i=0;i<G.vexnum;i++)
- {
- p=G.vertices[i].firstarc;
- j=0;
- while (p!=NULL)
- {
- cout<<"(" <<i<< "," <<p->adjvex<< ")" ;
- p=p->nextarc;
- j=1;
- }
- if (j==1)
- cout<<endl;
- }
- }
- void dfs(ALGraph G, int v) //深度优先遍历
- {
- ArcNode *p;
- cout<<v<<" " ;
- visited[v]=1;
- p=G.vertices[v].firstarc;
- while (p!=NULL)
- { if (!visited[p->adjvex])
- dfs(G,p->adjvex);
- p=p->nextarc;
- }
- return ;
- }
- void dfs1(ALGraph G)
- {
- int i;
- for (i=0;i<G.vexnum;i++)
- if (visited[i]==0)
- dfs(G,i);
- }
- void main()
- {
- ALGraph G;
- CreateDG(G);
- int v;
- Disp(G);
- cout<<"输入顶点:" ;
- cin>>v;
- cout<<"深度优先序列:" ;
- dfs1(G);
- cout<<endl;
- }
各种基本算法实现小结(五)—— 排序算法
(均已测试通过)
* 选择排序 |____简单选择排序 |____堆排序 |____归并排序
* 交换排序 |____冒泡排序 |____快速排序
* 插入排序 |____直接插入排序 |____折半排序 |____希尔排序
* 分配排序 |____箱排序 |____基数排序
======================================================================
简单排序算法
1、 冒泡排序
测试环境:VC 6.0 (C)
- #include
- <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 11
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void sort( int num[])
- {
- int i, j, tmp;
- for (i=1; i<MAX-1; i++)
- {
- printf("bubble.../n" );
- for (j=1; j<MAX-i; j++)
- {
- printf("%5d" , num[j]);
- if (num[j]>num[j+1])
- {
- tmp=num[j];
- num[j]=num[j+1];
- num[j+1]=tmp;
- }
- }
- printf("%5d/n" , num[MAX-i]);
- printf("bubble after.../n" );
- for (j=1; j<MAX; j++)
- printf("%5d" , num[j]);
- printf("/n" );
- }
- }
- /* bubble sort */
- /*
- void sort(int num[])
- {
- int i, j, tmp;
- for(i=1; i<MAX-1; i++)
- {
- for(j=1; j<MAX-i; j++)
- if(num[j]>num[j+1])
- {
- tmp=num[j];
- num[j]=num[j+1];
- num[j+1]=tmp;
- }
- }
- }
- */
- void main()
- {
- int num[MAX];
- printf("sort before.../n" );
- input(num);
- output(num);
- sort(num);
- printf("sort after.../n" );
- output(num);
- }
运行结果:
=======================================================
2、双向冒泡排序
据说可以提高效率,减少比较次数和交换次数
但仔细分析可得,每次while循环,都for循环比较了两次
因此每次low和high各减1,总体上比较次数并未减少,两次for交换也未减少
个人认为双向冒泡算法并未有效的减少比较次数和交换次数,但此算法也富含编程思想,值得学习
测试环境:VC 6.0 (C)
- #include
- <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define swap(x, y){int tmp; tmp=x; x=y; y=tmp;}
- #define MAX 11
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- }
- void sort( int num[], int low, int high)
- {
- int i;
- while (low<high)
- {
- for (i=low; i<high; i++) /* bubble to high */
- if (num[i]>num[i+1])
- swap(num[i], num[i+1]);
- high--;
- for (i=high; i>low; i--) /* bubble to low */
- if (num[i]<num[i-1])
- swap(num[i], num[i-1]);
- low++;
- }
- }
- void main()
- {
- int num[MAX];
- input(num);
- printf("sort before.../n" );
- output(num);
- sort(num, 1, MAX-1);
- printf("sort after.../n" );
- output(num);
- }
运行结果:
=======================================================
3、选择排序
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 101
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void sort( int num[])
- {
- int i, j, k, tmp;
- for (i=1; i<MAX-1; i++)
- {
- k=i;
- for (j=i+1; j<MAX; j++)
- if (num[k]>num[j])
- k=j;
- if (i<k)
- {
- tmp=num[i];
- num[i]=num[k];
- num[k]=tmp;
- }
- }
- }
- void main()
- {
- int num[MAX];
- printf("sort before.../n" );
- input(num);
- output(num);
- sort(num);
- printf("sort after.../n" );
- output(num);
- }
运行结果:
=======================================================
中级排序算法
向部分已排好序数列插入新值,使整个数列最终都有序
1、直接插入排序
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 11
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void sort( int num[])
- {
- int i, pos, tmp;
- for (i=2; i<MAX; i++) /* from 2 to sorting */
- {
- pos=i;
- tmp=num[pos];
- while (pos>1 && tmp<num[pos-1])
- {
- num[pos]=num[pos-1];
- pos--;
- }
- num[pos]=tmp;
- }
- }
- void main()
- {
- int num[MAX];
- printf("sort before.../n" );
- input(num);
- output(num);
- sort(num);
- printf("sort after.../n" );
- output(num);
- }
运行结果:
=======================================================
2、 折半插入排序
折半插入排序算法是一种稳定的排序算法,比直接插入算法明显减少了关键字之间比较的次数
因此速度比直接插入排序算法快,但记录移动的次数没有变,
所以折半插入排序算法的时间复杂度仍然为O(n^2),
测试环境:VC 6.0 (C)
- #include
- <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 11
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void sort( int num[], int low, int high)
- {
- int i, j, mid;
- int l, h;
- for (i=2; i<=high; i++)
- {
- l=low;
- h=i-1;
- num[0]=num[i]; /* save */
- while (l<=h)
- {
- mid=(l+h)/2;
- if (num[0]<num[mid])
- h=mid-1;
- else
- l=mid+1;
- }
- for (j=i; j>l; j--) /* move */
- num[j]=num[j-1];
- num[l]=num[0];
- }
- }
- void main()
- {
- int num[MAX];
- input(num);
- printf("sort before.../n" );
- output(num);
- sort(num, 1, MAX-1);
- printf("sort after.../n" );
- output(num);
- }
运行结果:
=======================================================
3、 2-路插入排序
2-路插入排序: 是在折半插入排序的基础上再次改进,其目的是减少排序过程中记录移动的次数
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 11
- int num2[MAX];
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void bi_insertsort( int num[], int len)
- {
- int i, j, pos, head, tail;
- head=tail=1;
- num2[1]=num[1];
- for (i=2; i<=len; i++)
- {
- if (num[i]>num2[1]) /* larger, save to tail */
- {
- for (j=tail; j>1; j--)
- {
- if (num[i]<num2[j])
- num2[j+1]=num2[j];
- else
- break ;
- }
- num2[j+1]=num[i];
- tail++;
- }
- else /* smaller, save to head */
- {
- if (head==1) /* first to end, then to head... */
- {
- num2[len]=num[i];
- head=len;
- }
- else
- {
- for (j=head; j<=len; j++)
- {
- if (num[i]>num2[j])
- num2[j-1]=num2[j];
- else
- break ;
- }
- num2[j-1]=num[i];
- head--;
- }
- }
- }
- pos=1;
- for (i=1; i<=len; i++) /* move back data from num2[] to num[] */
- {
- if (head<=len)
- num[i]=num2[head++];
- else if (pos<=tail)
- num[i]=num2[pos++];
- }
- }
- int main()
- {
- int num[MAX]; /* 1 - len is num, 0->null */
- input(num);
- printf("sort before.../n" );
- output(num);
- bi_insertsort(num, MAX-1);
- printf("sort after.../n" );
- output(num);
- return 0;
- }
运行结果:
=======================================================
4、合并插入排序(数组实现)
将两个有序数组A、B合并成另一个有序的大数组C
测试环境:VC 6.0 (C)
- #include <stdio.h>
- void input_num1( int num[], int n1)
- {
- int i;
- for (i=1; i<=n1; i++)
- num[i]=3*(i-1);
- printf("/nnum 1.../n" );
- for (i=1; i<=n1; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- }
- void input_num2( int num[], int n2)
- {
- int i;
- for (i=1; i<=n2; i++)
- num[i]=i;
- printf("/nnum 2.../n" );
- for (i=1; i<=n2; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- }
- void output_num3( int num1[], int n1, int num2[], int n2, int num3[], int n3)
- {
- int pos1, pos2, pos3;
- pos3=pos2=pos1=1;
- while (pos1<=n1 && pos2<=n2)
- {
- if (num1[pos1]<num2[pos2])
- num3[pos3++]=num1[pos1++];
- else
- num3[pos3++]=num2[pos2++];
- }
- while (pos1<=n1)
- num3[pos3++]=num1[pos1++];
- while (pos2<=n2)
- num3[pos3++]=num2[pos2++];
- printf("/n/nnum 3.../n" );
- for (pos3=1; pos3<=n3; pos3++)
- {
- printf("%5d" , num3[pos3]);
- if (0 == pos3%10)
- printf("/n" );
- }
- }
- void main()
- {
- int num1[11];
- int num2[21];
- int num3[31];
- input_num1(num1, 10);
- input_num2(num2, 20);
- output_num3(num1, 10, num2, 20, num3, 30);
- }
运行结果:
=======================================================
5、合并插入排序(链表实现)
将两个有序链表A、B合并成另一个有序的大链表C(链表单元来自A和B)
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <malloc.h>
- struct _link
- {
- int data;
- struct _link *next;
- };
- typedef struct _link link, *plink;
- plink init_link()
- {
- plink p;
- p=(plink)malloc(sizeof (link));
- if (!p) /* if(p == NULL) */
- {
- printf("Error. malloc fail.../n" );
- return NULL;
- }
- p->data=-1;
- p->next=NULL;
- return p;
- }
- plink input_num1(plink plk, int n1)
- {
- int i, count;
- plink p, s;
- p=plk;
- for (i=1; i<=n1; i++)
- {
- s=(plink)malloc(sizeof (link));
- if (!s) /* if(p == NULL) */
- {
- printf("Error. malloc fail.../n" );
- return NULL;
- }
- s->data=3*(i-1);
- s->next=NULL;
- p->next=s;
- p=p->next;
- }
- count=0;
- s=plk->next;
- while (s)
- {
- count++;
- printf("%5d" , s->data);
- s=s->next;
- if (0 == count%10)
- printf("/n" );
- }
- printf("/n" );
- return plk;
- }
- plink input_num2(plink plk, int n2)
- {
- int i, count;
- plink p, s;
- p=plk;
- for (i=1; i<=n2; i++)
- {
- s=(plink)malloc(sizeof (link));
- if (!s) /* if(p == NULL) */
- {
- printf("Error. malloc fail.../n" );
- return NULL;
- }
- s->data=i;
- s->next=NULL;
- p->next=s;
- p=p->next;
- }
- count=0;
- s=plk->next;
- while (s)
- {
- count++;
- printf("%5d" , s->data);
- s=s->next;
- if (0 == count%10)
- printf("/n" );
- }
- printf("/n" );
- return plk;
- }
- void output_num3(plink plk1, plink plk2, plink plk3)
- {
- int count;
- plink p1, p2, p3;
- p1=plk1->next;
- p2=plk2->next;
- p3=plk3;
- while (p1 && p2)
- {
- if (p1->data < p2->data)
- {
- p3->next=p1;
- p3=p3->next;
- p1=p1->next;
- }
- else
- {
- p3->next=p2;
- p3=p3->next;
- p2=p2->next;
- }
- }
- p3->next = p1 ? p1 : p2; /* NOTE: directly link to not NULL address, OK */
- count=0;
- p3=plk3->next;
- while (p3)
- {
- count++;
- printf("%5d" , p3->data);
- p3=p3->next;
- if (0 == count%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void main()
- {
- plink plk1, plk2, plk3;
- plk1=init_link();
- plk2=init_link();
- plk3=init_link();
- printf("num 1.../n" );
- plk1=input_num1(plk1, 10);
- printf("num 2.../n" );
- plk2=input_num2(plk2, 20);
- printf("num 3.../n" );
- output_num3(plk1, plk2, plk3);
- }
运行结果:
=======================================================
高级排序算法
1、 快速排序
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 21
- void input( int num[])
- {
- int i;
- srand(time(NULL));
- for (i=0; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- }
- void sort( int num[], int low, int high)
- {
- int l, h;
- l=low;
- h=high;
- if (low < high)
- {
- num[0]=num[l]; /* num[0] save pivot */
- while (l<h)
- {
- while (l<h && num[h]>=num[0]) h--;
- num[l]=num[h];
- while (l<h && num[l]<=num[0]) l++;
- num[h]=num[l];
- }
- num[l]=num[0];
- sort(num, low, l-1);
- sort(num, l+1, high);
- }
- }
- void main()
- {
- int num[MAX];
- input(num);
- printf("/nsort before.../n" );
- output(num);
- sort(num, 1, MAX-1);
- printf("/nsort before.../n" );
- output(num);
- }
运行结果:
=======================================================
2、 希尔排序
说明:本示例仅测试10或11个数的3趟希尔排序
由于希尔排序的增量step至今尚无精准的数学论证,无法给出科学、高效的序列函数
据严蔚敏的《数据结构(C语言版)》介绍说:希尔排序的分析是一个复杂的问题,因为它的时间是所取“增量”序列的函数,这涉及一些数学上尚未解决的难题(P272).
因此,本示例仅是实际问题实际解决的一个特例。
本算法基本思想仍是上述直接排序算法的改进,仅仅步长由1变成了step而已
如果大家想需要增添或减少数组元素个数,请一并修改input()函数中的step等趟数序列
如果大家对希尔排序算法有更好的改进,或有较好步长的函数和通用模板,希望能拿出来共同学习交流分享,谢谢!
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 11 /* num[] */
- #define STEP 4 /* jump[] */
- void input( int num[], int jump[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- for (i=1; i<STEP; i++)
- jump[i]=7-2*i; /* 1->5; 2->3; 3->1 */
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- }
- void sort( int num[], int jump[])
- {
- int i, j, pos, step;
- for (i=1; i<STEP; i++)
- {
- step=jump[i];
- for (j=1+step; j<MAX; j++)
- {
- pos=j;
- num[0]=num[pos]; /* save num[j] where (i+step)<j<MAX */
- while (num[0]<num[pos-step])
- {
- num[pos]=num[pos-step];
- pos=pos-step; /* shell: jump step */
- }
- num[pos]=num[0];
- }
- }
- }
- void main()
- {
- int num[MAX];
- int jump[STEP];
- input(num, jump);
- printf("sort before.../n" );
- output(num);
- sort(num, jump);
- printf("sort after.../n" );
- output(num);
- }
运行结果:
=======================================================
2、 希尔排序(网摘)
在学习希尔排序算法时,看到网上有如下一段希尔排序代码,也可以直接运行
但看代码来真得很费解,感觉变量定义不够直观,算法设计也不太简洁
因此,在最大程度保留源代码时,仅对变量名和算法逻辑简单修改
力争做到变量名清晰,逻辑顺畅,达到不用注释读者也能看明白
希望对大家学习有点帮助
测试环境:VC 6.0 (C)
摘录原代码:http://apps.hi.baidu.com/share/detail/5669244(百度空间)
- #include <iostream.h>
- void ShellSort( int * pData, int Count)
- {
- int step[4];
- step[0] = 9;
- step[1] = 5;
- step[2] = 3;
- step[3] = 1;
- int iTemp;
- int k,s,w;
- for ( int i=0;i<4;i++)
- {
- k = step[i];
- s = -k;
- for ( int j=k;j<Count;j++)
- {
- iTemp = pData[j];
- w = j-k;//求上step个元素的下标
- if (s ==0)
- {
- s = -k;
- s++;
- pData[s] = iTemp;
- }
- while ((iTemp<pData[w]) && (w>=0) && (w<=Count))
- {
- pData[w+k] = pData[w];
- w = w-k;
- }
- pData[w+k] = iTemp;
- }
- }
- }
- void main()
- {
- int data[] = {10,9,8,7,6,5,4,3,2,1,-10,-1};
- ShellSort(data,12);
- for ( int i=0;i<12;i++)
- cout<<data[i]<<" " ;
- cout<<"/n" ;
- }
修改后代码:
- #include <iostream.h>
- void ShellSort( int * pData, int Count)
- {
- int iTemp;
- int steplen, pos;
- int step[4];
- step[0] = 9;
- step[1] = 5;
- step[2] = 3;
- step[3] = 1;
- for ( int i=0;i<4;i++)
- {
- steplen = step[i];
- for ( int j=0+steplen; j<Count; j++)
- {
- iTemp = pData[j];
- pos=j;
- while (iTemp<pData[pos-steplen] && pos>0)
- {
- pData[pos] = pData[pos-steplen];
- pos=pos-steplen;
- }
- pData[pos] = iTemp;
- }
- }
- }
- void main()
- {
- int data[] = {10,9,8,7,6,5,4,3,2,1,-10,-1};
- cout<<endl<<"sort before..." <<endl;
- for ( int i=0;i<12;i++)
- cout<<data[i]<<" " ;
- cout<<endl;
- ShellSort(data,12);
- cout<<endl<<"sort before..." <<endl;
- for (i=0;i<12;i++)
- cout<<data[i]<<" " ;
- cout<<endl;
- }
运行结果:
=======================================================
3、 堆排序
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 11
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void heapadjust( int num[], int s, int len) /* build large heap */
- {
- int j;
- num[0]=num[s]; /* save temp data */
- for (j=2*s; j<=len; j*=2)
- {
- if (j<len && num[j]<num[j+1]) /* num[j+1] is limited by j<len beyond the border */
- j++;
- if (num[0]>num[j])
- break ;
- num[s]=num[j];
- s=j;
- }
- num[s]=num[0];
- }
- void heapsort( int num[], int len)
- {
- int i, tmp;
- for (i=len/2; i>0; i--) /* build heap */
- heapadjust(num, i, len);
- for (i=len; i>1; i--) /* sort heap */
- {
- tmp=num[1]; /* change largest data to end */
- num[1]=num[i];
- num[i]=tmp;
- heapadjust(num, 1, i-1); /* rebuild large heap for (i-1) data */
- }
- }
- int main()
- {
- int num[MAX]; /* 1 - len is num, 0->null */
- input(num);
- printf("sort before.../n" );
- output(num);
- heapsort(num, MAX-1);
- printf("sort after.../n" );
- output(num);
- return 0;
- }
运行结果:
=======================================================
4、 归并排序
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 11
- int num2[MAX]; /* copy array */
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0 == i%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void merge( int num[], int low, int mid, int high)
- {
- int l, h, i, j;
- l=low;
- h=high;
- for (i=mid+1, j=low; low<=mid && i<=high; j++)
- {
- if (num[low]<num[i])
- num2[j]=num[low++];
- else
- num2[j]=num[i++];
- }
- if (low<=mid)
- for (; j<=high; j++, low++)
- num2[j]=num[low];
- if (i<=high)
- for (; j<=high; j++, i++)
- num2[j]=num[i];
- for (i=l; i<=h; i++)
- num[i]=num2[i];
- }
- void mergesort( int num[], int low, int high)
- {
- int mid;
- if (low==high)
- num2[low]=num[low];
- else
- {
- mid=(low+high)/2;
- mergesort(num, low, mid); /* to low */
- mergesort(num, mid+1, high); /* to high */
- merge(num, low, mid, high); /* recursion */
- }
- }
- int main()
- {
- int num[MAX]; /* 1 - len is num, 0->null */
- input(num);
- printf("sort before.../n" );
- output(num);
- mergesort(num, 1, MAX-1);
- printf("sort after.../n" );
- output(num);
- return 0;
- }
运行结果:
=======================================================
排序算法的知识扩展(网摘)
内部排序算法的比较和实现
引用网址: http://www.cppblog.com/feosun/archive/2008/10/12/63831.html(直接摘录,尚未测试)
参考网址: http://sjjp.tjuci.edu.cn/sjjg/DataStructure/DS/web/paixu/paixu8.1.1.1.htm(数据结构)
排序是数据处理中经常使用的一种重要运算,在计算机及其应用系统中,花费在排序上的时间在系统运行时间中占有很大比重;并且排序本身对推动算法分析的发展 也起很大作用。目前已有上百种排序方法,但尚未有一个最理想的尽如人意的方法,本文介绍常用的如下排序方法的C/C++实现,并对它们进行分析和比较。
选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
首先,排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。
其次,说一下稳定性的好处。排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就 是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。另外,如果排序算法稳定,对基于比较的排序算法而言,元素交换 的次数可能会少一些(个人感觉,没有证实)。
回到主题,现在分析一下常见的排序算法的稳定性,每个都给出简单的理由。
(1)冒泡排序
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无 聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改 变,所以冒泡排序是一种稳定排序算法。
(2)选择排序
选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个 元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么 交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。
(3)插入排序
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开 始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相 等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳 定的。
(4)快速排序
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交 换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和 a[j] 交换的时刻。
(5)归并排序
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有 序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定 性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结 果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。
(6)基数排序
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优 先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。
(7)希尔排序(shell)
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小, 插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元 素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
(8)堆排序
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n 的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n /2-1, n/2-2, ...1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没 有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法。
/*
冒泡排序 插入排序 二路插入排序 希尔排序 快速排序 选择排序 归并排序 堆排序算法的
C/C++实现。
作者:feosun
日期:2008年10月12日
参考资料:数据结构(C语言版) 清华大学出版社
*/
#include <iostream>
using namespace std;
//交换两个数的值
void swap(int &a,int &b)
{
int tmp;
tmp=a;
a=b;
b=tmp;
}
//屏幕输出数组
void display(int array[],int len)
{
cout<<"the result is:"<<endl;
for (int i = 0 ;i < len;i++ )
{
cout<<array[i]<<" ";
}
cout<<endl;
}
/*
冒泡排序
算法思想:将被排序的记录数组R[1..n]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡。
根据轻气泡不能在重气泡之下的原则,从下往上扫描数组 R:凡扫描到违反本原则的
轻气泡,就使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上,
重者在下为止。
时间复杂度 o(n^2)
空间复杂度 o(1)
比较次数 n(n+1)/2
*/
void bubble_sort(int array[],int len)
{
for (int i = len-1 ;i >= 0;i-- )
{
for(int j = 0;j < i;j++)
if(array[j] > array[j+1])
swap(array[j],array[j+1]);
}
}
/*
直接插入排序
算法思想:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元
素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,将它
插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。
时间复杂度 o(n^2)
空间复杂度 o(1)
比较次数 n(n+1)/2
*/
void insert_sort(int array[],int len)
{
int tmp,i,j;
for(i = 1;i < len;i++)
{
if (array[i] < array[i-1])
{
tmp = array[i];
array[i] = array[i-1];
//插入到相应位置
for (j = i-2;j >= 0;j--)
{
//往后移
if (array[j] > tmp )
array[j+1] = array[j];
else
{
array[j+1] = tmp;
break;
}
}
if(j == -1)
array[j+1] = tmp;
}
}
}
/*
2-路插入排序
算法思想:增加一个辅助空间d,把r[1]赋值给d[1],并将d[1]看成是排好序后处于中间
位置的记录。然后从r[2]开始依次插入到d[1]之前或之后的有序序列中。
时间复杂度 o(n^2)
空间复杂度 o(1)
比较次数 n(n+1)/2
*/
void bi_insert_sort(int array[],int len)
{
int* arr_d = (int *)malloc(sizeof(int) * len);
arr_d[0] = array[0];
int head = 0,tail = 0;
for (int i = 1;i < len; i++ )
{
if (array[i] > arr_d[0])
{
int j;
for ( j= tail;j>0;j--)
{
if (array[i] < arr_d[j])
arr_d[j+1] = arr_d[j];
else
break;
}
arr_d[j+1] = array[i];
tail += 1;
}
else
{
if (head ==0)
{
arr_d[len-1] = array[i];
head =len-1;
}
else
{
int j;
for (j = head;j <= len-1;j++)
{
if (array[i] > arr_d[j])
arr_d[j-1] = arr_d[j];
else
break;
}
arr_d[j-1] = array[i];
head -= 1;
}
}
}
for (int i = 0;i < len; i++)
{
int pos = (i + head );
if(pos >= len) pos -= len;
array[i] = arr_d[pos];
}
free(arr_d);
}
/*
希尔排序
算法思想:先将整个待排序记录分割成若干子序列分别进行直接插入排
序,待整个序列中的记录基本有序时,再对全体记录进行一
次直接插入排序
时间复杂度 o(n^2)
空间复杂度 o(1)
比较次数 ?
*/
void shell_insert(int array[],int d,int len)
{
int tmp,j;
for (int i = d;i < len;i++)
{
if(array[i] < array[i-d])
{
tmp = array[i];
j = i - d;
do
{
array[j+d] = array[j];
j = j - d;
} while (j >= 0 && tmp < array[j]);
array[j+d] = tmp;
}
}
}
void shell_sort(int array[],int len)
{
int inc = len;
do
{
inc = inc/2;
shell_insert(array,inc,len);
} while (inc > 1);
}
/*
快速排序
算法思想:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递
归地解这些子问题,然后将这些子问题的解组合成为原问题的解。
时间复杂度 o(nlogn)
空间复杂度 o(logn)
比较次数 ?
*/
int partition(int array[],int low,int high)
{
int pivotkey = array[low];
while (low < high)
{
while(low < high && array[high] >= pivotkey)
--high;
swap(array[low],array[high]);
while(low < high && array[low] <= pivotkey)
++low;
swap(array[low],array[high]);
}
array[low] = pivotkey;
return low;
}
void quick_sort(int array[],int low,int high)
{
if (low < high)
{
int pivotloc = partition(array,low,high);
quick_sort(array,low,pivotloc-1);
quick_sort(array,pivotloc+1,high);
}
}
/*
直接选择排序
算法思想:每一趟在n-i+1个记录中选取关键字最小的记录作为有序序列中的第i个记录
时间复杂度 o(n^2)
空间复杂度 o(1) ?
比较次数 n(n+1)/2
*/
int SelectMinKey(int array[],int iPos,int len)
{
int ret = 0;
for (int i = iPos; i < len; i++)
{
if (array[ret] > array[i])
{
ret = i;
}
}
return ret;
}
void select_sort(int array[],int len)
{
for (int i = 0; i < len; i++)
{
int j = SelectMinKey(array,i,len);
if (i != j)
{
swap(array[i],array[j]);
}
}
}
/*
归并排序
算法思想:设两个有序的子文件(相当于输入堆)放在同一向量中相邻的位置上:R[low..m],R[m+1..high],先
将它们合并到一个局部的暂存向量R1(相当于输出堆)中,待合并完成后将R1复制回R[low..high]中。
时间复杂度 o(nlogn)
空间复杂度 o(n)
比较次数 ?
*/
void merge(int array[],int i,int m, int n)
{
int j,k;
int iStart = i, iEnd = n;
int arrayDest[256];
for ( j = m + 1,k = i; i <= m && j <= n; ++k)
{
if (array[i] < array[j])
arrayDest[k] = array[i++];
else
arrayDest[k] = array[j++];
}
if (i <= m)
for (;k <= n; k++,i++)
arrayDest[k] = array[i];
if(j <= n)
for (;k <= n; k++,j++)
arrayDest[k] = array[j];
for(j = iStart; j <= iEnd; j++)
array[j] = arrayDest[j];
}
void merge_sort(int array[],int s,int t)
{
int m;
if (s < t)
{
m = (s + t )/2;
merge_sort(array,s,m);
merge_sort(array,m+1,t);
merge(array,s,m,t);
}
}
/*
堆排序
算法思想:堆排序(Heap Sort)是指利用堆(heaps)这种数据结构来构造的一种排序算法。
堆是一个近似完全二叉树结构,并同时满足堆属性:即子节点的键值或索引总是
小于(或者大于)它的父节点。
时间复杂度 o(nlogn)
空间复杂度 o(1)
比较次数 较多
*/
void heap_adjust(int array[],int i,int len)
{
int rc = array[i];
for(int j = 2 * i; j <len; j *= 2)
{
if(j < len && array[j] < array[j+1]) j++;
if(rc >= array[j]) break;
array[i] = array[j]; i = j;
}
array[i] = rc;
}
void heap_sort(int array[],int len)
{
int i;
for(i = (len-1)/2; i >= 0; i--)
heap_adjust(array,i,len);
for( i = (len-1); i > 0; i--)
{
swap(array[0],array[i]); //弹出最大值,重新对i-1个元素建堆
heap_adjust(array,0,i-1);
}
}
int main() {
int array[] = {45,56,76,234,1,34,23,2,3,55,88,100};
int len = sizeof(array)/sizeof(int);
//bubble_sort(array,len); //冒泡排序
/*insert_sort(array,len);*/ //插入排序
/*bi_insert_sort(array,len);*/ //二路插入排序
/*shell_sort(array,len);*/ //希尔排序
/*quick_sort(array,0,len-1);*/ //快速排序
/*select_sort(array,len);*/ //选择排序
/*merge_sort(array,0,len-1);*/ //归并排序
heap_sort(array,len); //堆排序
display(array,len);
return 0;
}
各种基本算法实现小结(六)—— 查找算法
(均已测试通过)
===================================================================
1、简单查找
在一组无序数列中,查找特定某个数值,并返回其位置pos
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 101
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0==i%10)
- printf("/n" );
- }
- }
- int find( int num[], int x)
- {
- int i;
- for (i=1; i<MAX; i++)
- if (x == num[i])
- return i;
- return 0;
- }
- void main()
- {
- int x, pos, num[MAX];
- input(num);
- printf("num...: /n" );
- output(num);
- printf("Enter find num: " );
- scanf("%d" , &x);
- pos=find(num, x);
- if (pos)
- printf("OK! %d is found in pos: %d/n" , x, pos);
- else
- printf("Sorry! %d is not found... in num/n" , x);
- }
运行结果:
==========================================================
2、 折半查找
在有序数列中,逐步缩小查找范围,直至找到或找不到记录为止
本算法首先随机生成100个无序数列,然后利用快速排序算法排序成有序数列,然后再用折半查找算法
说明: 本算法中的排序算法,可用上一篇排序算法中的任一种算法实现,如选择排序、冒泡排序、快速排序等
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX 101
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0==i%10)
- printf("/n" );
- }
- }
- void sort( int num[], int low, int high) /* quick sort */
- {
- int l, h;
- if (low<high)
- {
- l=low;
- h=high;
- num[0]=num[l]; /* save pivot */
- while (l<h)
- {
- while (l<h && num[h]>=num[0]) h--;
- num[l]=num[h];
- while (l<h && num[l]<=num[0]) l++;
- num[h]=num[l];
- }
- num[l]=num[0]; /* insert pivot */
- sort(num, low, l-1);
- sort(num, l+1, high);
- }
- }
- int find( int num[], int x, int low, int high)
- {
- int mid;
- while (low<=high)
- {
- mid=(low+high)/2; /* find is OK */
- if (x==num[mid])
- return mid;
- else if (x<num[mid])
- high=mid-1;
- else
- low=mid+1;
- }
- return 0;
- }
- void main()
- {
- int x, pos, num[MAX];
- input(num);
- printf("sort before... /n" );
- output(num);
- sort(num, 1, MAX-1);
- printf("sort after... /n" );
- output(num);
- printf("Enter find num: " );
- scanf("%d" , &x);
- pos=find(num, x, 1, MAX-1);
- if (pos)
- printf("OK! %d is found in pos: %d/n" , x, pos);
- else
- printf("Sorry! %d is not found... in num/n" , x);
- }
运行结果:
==========================================================
各种基本算法实现小结(七)—— 常用算法
(均已测试通过)
======================================================================
1、判断素数
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <math.h>
- int is_sushu( int n)
- {
- int i, mid;
- mid=(int )sqrt(n);
- for (i=2; i<=mid; i++)
- if (0 == n%i)
- return 0;
- return 1;
- }
- void main()
- {
- int n;
- printf("Enter a num: " );
- scanf("%d" , &n);
- if (is_sushu(n))
- printf("%d is sushu!/n" , n);
- else
- printf("%d is not sushu.../n" , n);
- }
运行结果:
==========================================================
2、 求2-1000之间的所有素数
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <math.h>
- #define MAX 1000
- int is_sushu( int n)
- {
- int i, mid;
- mid=(int )sqrt(n);
- for (i=2; i<=mid; i++)
- if (0 == n%i)
- return 0;
- return 1;
- }
- void main()
- {
- int i, count;
- count=0;
- for (i=2; i<=MAX; i++)
- if (is_sushu(i))
- {
- count++;
- printf("%5d" , i);
- if (0 == count%10)
- printf("/n" );
- }
- printf("/n" );
- }
运行结果:
==========================================================
3、 验证哥德巴赫猜想
哥德巴赫猜想: 任意一个大于等于6的偶数都可以分解为两个素数之和
如: 6 = 3+3;100 = 3+97=11+89; 1000 = 3+997=59+941=。。。
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <math.h>
- #define MAX 1000
- int is_sushu( int n)
- {
- int i, mid;
- mid=(int )sqrt(n);
- for (i=2; i<=mid; i++)
- if (0 == n%i)
- return 0;
- return 1;
- }
- void main()
- {
- int i, mid, n;
- printf("Enter an even num: " );
- scanf("%d" , &n);
- mid=n/2;
- for (i=2; i<=mid; i++)
- {
- if (is_sushu(i) && is_sushu(n-i))
- printf("%d = %d + %d/n" , n, i, n-i);
- }
- }
运行结果:
==========================================================
4、 求最大公约数(GCD)和最小公倍数(LCM)
测试环境:VC 6.0 (C)
- #include <stdio.h>
- void max_min( int &m, int &n)
- {
- int tmp;
- if (m<n)
- {
- tmp=m;
- m=n;
- n=tmp;
- }
- }
- int Cal_GCD( int m, int n)
- {
- int gcd;
- max_min(m, n);
- gcd=m%n;
- while (gcd)
- {
- m=n;
- n=gcd;
- gcd=m%n;
- }
- return n;
- }
- void main()
- {
- int m, n, gcd;
- printf("Enter two num a b: " );
- scanf("%d %d" , &m, &n);
- gcd=Cal_GCD(m, n);
- printf("%d and %d GCD: %d/n" , m, n, gcd);
- printf("%d and %d LCM: %d/n" , m, n, m*n/gcd);
- }
运行结果:
==========================================================
5、统计个数(数字)
用随机函数产生100个[0,99]范围内的随机整数,
统计个位上的数字分别为0,1,2,3,4,5,6,7,8,9的数的个数并打印出来
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <string.h>
- #define MAX 101
- void input( int num[])
- {
- int i;
- srand((unsigned)time(NULL));
- for (i=1; i<MAX; i++)
- num[i]=rand()%100;
- }
- void output( int num[])
- {
- int i;
- for (i=1; i<MAX; i++)
- {
- printf("%5d" , num[i]);
- if (0==i%10)
- printf("/n" );
- }
- printf("/n" );
- }
- void cal_num( int num[], int count[])
- {
- int i, mod;
- for (i=1; i<MAX; i++)
- {
- mod=num[i]%10;
- count[mod]++;
- }
- }
- void main()
- {
- int num[MAX];
- int i, count[10];
- memset(count, 0, 10*sizeof ( int )); /* initial count[] to 0 */
- input(num);
- printf("100 num:/n" );
- output(num);
- cal_num(num, count);
- for (i=0; i<10; i++)
- printf("%d: %d/n" , i, count[i]);
- }
运行结果:
==========================================================
6、统计个数(数字、字符、其它字符)
输入一行字符,统计其中有多少个数字、字符和其它字符
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <string.h>
- #define MAX 1024
- void cal_num( char *str, int count[])
- {
- char *pstr;
- pstr=str;
- while (*pstr) /* *pstr != 0 */
- {
- if (*pstr>= '0' && *pstr<= '9' )
- count[0]++;
- else if ((*pstr>= 'a' && *pstr<= 'z' ) || (*pstr>= 'A' && *pstr<= 'Z' ))
- count[1]++;
- else
- count[2]++;
- pstr++;
- }
- }
- void main()
- {
- char str[MAX];
- int i, count[3]; /* 0->num; 1->char; 2->others */
- memset(count, 0, 3*sizeof ( int ));
- printf("Enter a string: " );
- scanf("%s" , str);
- cal_num(str, count);
- for (i=0; i<3; i++)
- {
- switch (i)
- {
- case 0:
- printf("num: %d/n" , count[i]);
- break ;
- case 1:
- printf("char: %d/n" , count[i]);
- break ;
- case 2:
- printf("other: %d/n" , count[i]);
- break ;
- }
- }
- }
运行结果:
==========================================================
7、 数制转换(递归实现)
本算法仅实现了基数为2-16的数制转换
如果大家希望扩展范围,仅需要对基数表示字符case 进行扩展即可,如G、H、I ...
测试环境:VC 6.0 (C)
- #include <stdio.h>
- int flag=1; /* check: n/d == 0 */
- void trans_num( int n, int d)
- {
- int mod;
- mod=n%d;
- n=n/d;
- while (flag && n)
- trans_num(n,d);
- flag=0;
- switch (mod)
- {
- case 10:
- printf("A" );
- break ;
- case 11:
- printf("B" );
- break ;
- case 12:
- printf("C" );
- break ;
- case 13:
- printf("D" );
- break ;
- case 14:
- printf("E" );
- break ;
- case 15:
- printf("F" );
- break ;
- default :
- printf("%d" , mod);
- }
- }
- void main()
- {
- int n, d;
- printf("Enter n d: " );
- scanf("%d %d" , &n, &d);
- trans_num(n, d);
- printf("/n" );
- }
运行结果:
算法改进
数制直接转为字符输出,扩展支持16进制以上的数制转换
- #include <stdio.h>
- int flag=1; /* check: n/d == 0 */
- void trans_num( int n, int d)
- {
- int mod;
- mod=n%d;
- n=n/d;
- while (flag && n)
- trans_num(n,d);
- flag=0;
- if (mod>=10)
- mod=mod-10+65; /* convert to char */
- else
- mod=mod+48;
- printf("%c" , mod); /* print char (%c) */
- }
- void main()
- {
- int n, d;
- printf("Enter n d: " );
- scanf("%d %d" , &n, &d);
- trans_num(n, d);
- printf("/n" );
- }
运行结果 (扩展进制):
100 = 4*24+4 1000=1*24*24+17*24+16 10000=17*24*24+8*24+16 1000=27*36+28
==========================================================
8、 数制转换(栈实现)
核心思想和递归实现类似,都是压栈的原理,实现较简单,请自己尝试实现
==========================================================
9、 水仙花数
水仙花数简述: 水仙花数是指一个 n 位数 ( n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身。
如:153=1 ^3+5 ^3+3 ^3(3位数);1634=1 ^4+6 ^4+3 ^4+4 ^4(4位数);54748=5 ^5+4 ^5+7 ^5+4 ^5+8 ^5(5位数)
判断任一3位数,是否为水仙花数
测试环境:GCC
- #include <stdio.h>
- main()
- {
- int b, s, g, n, sum;
- scanf("%d" , &n);
- b=n/100;
- s=n/10%10;
- g=n%10;
- sum=b*b*b+s*s*s+g*g*g;
- if (sum==n)
- printf("Yes/n" );
- else
- printf("No/n" );
- }
运行结果 (Redhat Linux):
================================================
求4位数的水仙花数(1000<=X<=9999)
测试环境:VC 6.0 (C)
- #include <stdio.h>
- int main()
- {
- int i,j,k,l,m,n;
- for (i=1; i<=9; i++)
- for (j=0; j<=9; j++)
- for (k=0; k<=9; k++)
- for (l=0; l<=9; l++)
- if ((i*1000+j*100+k*10+l)==i*i*i*i+j*j*j*j+k*k*k*k+l*l*l*l)
- printf("%d%d%d%d=%d^4+%d^4+%d^4*%d^4/n" , i, j, k, l, i, j, k, l);
- return 0;
- }
运行结果:
================================================
思考: 如果求得高精度大数的水仙花数,如8位、18位、28位的水仙花数(需考虑计算机精度,可采用数组或指针实现,大数计算)
==========================================================
10、 大数计算
大数运算 :参加的值和计算结果通常是以上百位数,上千位数以及更大长度之间的整数运算,早已超出了计算机能够表示数值的精度范围(2^32=4294967296或2^64=18446744073709551616)即64位机最大也才20位,因此需要想出其它的办法计算大数。
求任意两整数之和(1000位以内)
测试环境:VC 6.0 (C)
- #include <stdio.h>
- #include <string.h>
- #define MAX 1000 /* precision */
- void input( char ch[])
- {
- scanf("%s" , ch);
- }
- void add( char ch1[], char ch2[], char ch3[])
- {
- int len1, len2, len3, maxlen;
- int sum, flag;
- len1=strlen(ch1);
- len2=strlen(ch2);
- len3=maxlen=len1 >= len2 ? len1 : len2;
- flag=0; /* jin wei */
- while (len1>=1 && len2>=1)
- {
- sum=ch1[len1-1]-'0' + ch2[len2-1]- '0' + flag; /* char -> int to calculate sum */
- flag=0;
- if (sum>=10)
- {
- sum-=10;
- flag=1;
- }
- ch3[maxlen-1]=sum + '0' ;
- len1--;
- len2--;
- maxlen--;
- }
- while (len1>=1) /* if num1[] is longer or maxer */
- {
- sum=ch1[len1-1]-'0' + flag;
- flag=0;
- if (sum>=10)
- {
- sum-=10;
- flag=1;
- }
- ch3[maxlen-1]=sum + '0' ;
- len1--;
- maxlen--;
- }
- while (len2>=1) /* if num2[] is longer or maxer */
- {
- sum=ch2[len2-1]-'0' + flag;
- flag=0;
- if (sum>=10)
- {
- sum-=10;
- flag=1;
- }
- ch3[maxlen-1]=sum + '0' ;
- len2--;
- maxlen--;
- }
- if (flag != 0) /* if flag, then print gaowei(jinwei) */
- printf("%d" , flag);
- for ( int i=0; i<len3; i++)
- printf("%c" , ch3[i]);
- printf("/n" );
- }
- int main()
- {
- char ch1[MAX], ch2[MAX], ch3[MAX+1];
- memset(ch3, '0' , sizeof (ch3));
- input(ch1);
- input(ch2);
- add(ch1, ch2, ch3);
- return 0;
- }
运行结果:
思考: 请大家自己设计实现更复杂的大数减法、乘法、除法,求余、求幂、求最小公倍数等大数运算(提示:可用数组或链表)
==========================================================