注册 登录
编程论坛 数据结构与算法

[原创]数据结构与算法基本程序合集

cobby 发布于 2007-10-26 15:47, 13173 次点击

*/ --------------------------------------------------------------------------------------
*/ 出自: 编程中国 https://www.bc-cn.net
*/ 作者: cobby E-mail:jiaxuanyao1982@163.com QQ:51160333
*/ 时间: 2007-10-26 编程论坛首发
*/ 声明: 尊重作者劳动,转载请保留本段文字
*/ --------------------------------------------------------------------------------------

前言:这些是前几年我在大专教书时,数据结构课程中给学生写的学习例程,对于初学者有一定帮助。在此收集到一起,当个共享贴贡献给广大网友和编程爱好者。一般程序都不难也不大,并且所有例程均有较详细注释,适合自学。中间有一个“哈夫曼编码”,程序较大,希望能给大家一点启示。以下所有程序均在VC++6.0开发环境中调试通过,运行正常。有任何疑问可以“另外”发贴讨论。更多内容请访问我的博客http://jiaxuanyao.blogms.com
自认为本贴内容充实,对网友会所很大帮助,请版主或者管理员置顶加精,谢谢。

数据结构与算法基本程序目录
一、 线性表及其操作
1、 尾插法建立一个单链表,并按顺序输出
2、 单链表的元素查找,按内容查找
3、 元素插入操作
4、 按内容元素删除操作
5、 按位置删除元素
6、 建立双向链表
7、 单链表就地逆置
8、 约瑟夫环问题
二、 栈及其操作
1、 建立堆栈
2、 进栈与出栈
3、 栈的应用,括号匹配
三、 队及其操作
1、 链队列的建立
2、 入队和出队
3、 循环队列建立
4、 循环队列的入队和出队操作
四、 串及其操作
1、 串的朴素匹配
五、 树(二叉树)及其操作
1、 二叉排序树
2、 哈夫曼编码
六、 排序
1、 冒泡排序
2、 直接选择排序法

一、线性表及其操作
//All copyright are preserved by cobby
/*尾插法建立一个单链表,并按顺序输出*/
#define NULL 0 /*宏定义*/
typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}*L; /*类型重定义,即Node和*L和struct node等价*/
main()
{
L l,p,q; /*用指针类型定义三个结点类型的指针*/
char ch;
l=(L)malloc(sizeof(struct node)); /*分配内存空间*/
l->c='\0'; /*为头结点的数据域赋值,值为空*/
l->next=NULL; /*指明下一个结点目前不存在*/
q=l; /*q为游动指针,链表结点的连结要用*/
printf("Input a character:\n");
scanf("%c",&ch);
getchar(); //此语句用来吸收键盘输入的回车符,没有其它含义
while(ch!='!') /*输入!表示输入结束*/
{
p=(L)malloc(sizeof(struct node)); /*为新输入的数据分配内存空间*/
p->c=ch;
p->next=NULL; /*新输入的结点在链表的最后,即它的后面没有其它元素*/
q->next=p; /*q用于将上一个元素链接至当前新元素*/
q=p; /*q自己移到当前最后一个元素,以备继续链接所用*/
scanf("%c",&ch);
getchar();
}
q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
}

//All copyright are preserved bycobby
/*单链表的元素查找,按内容查找*/

#define NULL 0 /*宏定义*/
typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}*L; /*类型重定义,即Node和*L和struct node等价*/
main()
{
L l,p,q; /*用指针类型定义三个结点类型的指针*/
char ch;
int n;
l=(L)malloc(sizeof(struct node)); /*分配内存空间*/
l->c='\0'; /*为头结点的数据域赋值,值为空*/
l->next=NULL; /*指明下一个结点目前不存在*/
q=l; /*q为游动指针,链表结点的连结要用*/
printf("Input a character:\n");
scanf("%c",&ch);
getchar();
while(ch!='!') /*输入!表示输入结束*/
{
p=(L)malloc(sizeof(struct node)); /*为新输入的数据分配内存空间*/
p->c=ch;
p->next=NULL; /*新输入的结点在链表的最后,即它的后面没有其它元素*/
q->next=p; /*q用于将上一个元素链接至当前新元素*/
q=p; /*q自己移到当前最后一个元素,以备继续链接所用*/
scanf("%c",&ch);
getchar();
}
q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
/*--------以上为建立一个单链表-------------*/

printf("\nInput a character you wanna find\n");
scanf("%c",&ch);
printf("\nthe character you wanna find is %c\n",ch);
q=l->next; /*q移至头结点的后一个元素,即实际第一个数据点*/
n=1; //位置计数器
while(q!=NULL) /*若q不为空,即该结点存在*/
{
if(q->c==ch) /*字符匹配*/
printf("character found in position %d\n",n);
q=q->next; /*移至下一个元素继续查找*/
n++;
}
}

//All copyright are preserved bycobby
/*元素插入操作*/
#define NULL 0 /*宏定义*/
typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}Node,*L; /*类型重定义,即Node和*L和struct node等价*/
main()
{
L l,p,q; /*用指针类型定义三个结点类型的指针*/
char ch;
int pos,n;
l=(L)malloc(sizeof(Node)); /*分配内存空间*/
l->c='\0'; /*为头结点的数据域赋值,值为空*/
l->next=NULL; /*指明下一个结点目前不存在*/
q=l; /*q为游动指针,链表结点的连结要用*/
printf("Input a character:\n");
scanf("%c",&ch);
getchar();
while(ch!='!') /*输入!表示输入结束*/
{
p=(L)malloc(sizeof(Node)); /*为新输入的数据分配内存空间*/
p->c=ch;
p->next=NULL; /*新输入的结点在链表的最后,即它的后面没有其它元素*/
q->next=p; /*q用于将上一个元素链接至当前新元素*/
q=p; /*q自己移到当前最后一个元素,以备继续链接所用*/
scanf("%c",&ch);
getchar();
}
q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
/*以上为建立一个单链表*/
printf("Input the character and its position, such as s,3\n\n");
scanf("%c,%d",&ch,&pos);
q=l;
n=1;
while(n!=pos&&q->next!=NULL) /*未找到插入位置,且后面还有元素*/
{
q=q->next;
n++;
}
/*退出循环后,要么找到插入位置,要么表已到最后,输入的插入位置过大*/
if(n<pos) /*表已读完,仍未找到插入位置*/
printf("\n\nincorrect position, insert failed\n\n");
else /*找到插入位置*/
{
/*将进行插入操作*/
p=(L)malloc(sizeof(Node)); /*给新输入的数据分配内存空间*/
p->c=ch;
p->next=q->next;
q->next=p;
}
/*操作完成,然后输出新表*/

q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
}

//All copyright are preserved bycobby
/*按内容元素删除操作*/
#include<malloc.h>
#include<stdio.h>
#define NULL 0 /*宏定义*/
typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}Node,*L; /*类型重定义,即Node和*L和struct node等价*/
main()
{
L l,p,q; /*用指针类型定义三个结点类型的指针*/
char ch;
int n;
l=(L)malloc(sizeof(Node)); /*分配内存空间*/
l->c='\0'; /*为头结点的数据域赋值,值为空*/
l->next=NULL; /*指明下一个结点目前不存在*/
q=l; /*q为游动指针,链表结点的连结要用*/
printf("Input a character:\n");
scanf("%c",&ch);
getchar();
while(ch!='!') /*输入!表示输入结束*/
{
p=(L)malloc(sizeof(Node)); /*为新输入的数据分配内存空间*/
p->c=ch;
p->next=NULL; /*新输入的结点在链表的最后,即它的后面没有其它元素*/
q->next=p; /*q用于将上一个元素链接至当前新元素*/
q=p; /*q自己移到当前最后一个元素,以备继续链接所用*/
scanf("%c",&ch);
getchar();
}
q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
/*以上为建立单链表*/
printf("input the character you wanna delete\n\n");
scanf("%c",&ch);
printf("the element you wanna delete is %c\n\n",ch);
q=l->next;
p=l;
n=1;
while(q!=NULL&&q->c!=ch)
{
p=q;
q=q->next;
n++;
}
/*退出循环时可能找到指定元素,也可能表读完,需要进一步判断*/

if(q==NULL)
printf("element not found, delete failed\n\n");
else
p->next=q->next;
q=l->next; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
}
//All copyright are preserved bycobby
/*按位置删除元素*/
#define NULL 0 /*宏定义*/
typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}Node,*L; /*类型重定义,即Node和*L和struct node等价*/
main()
{
L l,p,q; /*用指针类型定义三个结点类型的指针*/
char ch;
int pos,n;
l=(L)malloc(sizeof(Node)); /*分配内存空间*/
l->c='\0'; /*为头结点的数据域赋值,值为空*/
l->next=NULL; /*指明下一个结点目前不存在*/
q=l; /*q为游动指针,链表结点的连结要用*/
printf("Input a character:\n");
scanf("%c",&ch);
getchar();
while(ch!='!') /*输入!表示输入结束*/
{
p=(L)malloc(sizeof(Node)); /*为新输入的数据分配内存空间*/
p->c=ch;
p->next=NULL; /*新输入的结点在链表的最后,即它的后面没有其它元素*/
q->next=p; /*q用于将上一个元素链接至当前新元素*/
q=p; /*q自己移到当前最后一个元素,以备继续链接所用*/
scanf("%c",&ch);
getchar();
}
q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
/*以上为建立单链表*/
printf("Input the position\n");
scanf("%d",&pos);
p=l;
n=1;
while(p->next!=NULL&&n!=pos)
{
p=p->next;
n++;
}
/*退出循环后,可能找到删除的元素位置,可能表读完,需要进一步判断*/
if(n==pos) /*删除位置找到,删除该位置上的元素*/
{
p->next=p->next->next;
//free(p);
}
else
printf("incorrect position, delete failed\n");
q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
}
//建立双向链表
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define NULL 0
typedef struct dlnode
{
char ch;
struct dlnode *pri,*next;
}dnode,*dl;
main()
{
dl l,p,q;
char c;
l=(dl)malloc(sizeof(dnode));
l->ch='\0';
l->next=NULL;
l->pri=NULL;
q=l;
printf("输入字符建立双向链表\n");
scanf("%c",&c);
getchar();

while(c!='!')
{
p=(dl)malloc(sizeof(dnode));
p->ch=c;
p->pri=q;
p->next=NULL;
q->next=p;
q=p;
scanf("%c",&c);
getchar();
}
q=l;
while(q->next!=NULL)
{
q=q->next;
printf("%c-->",q->ch);
}

printf("\n");
while(q->pri!=NULL)
{
printf("%c-->",q->ch);
q=q->pri;
}
printf("\n");
}

[此贴子已经被作者于2007-10-27 22:27:09编辑过]

50 回复
#2
cobby2007-10-26 15:47

//单链表就地逆置

#define NULL 0 /*宏定义*/
typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}Node,*L; /*类型重定义,即Node和*L和struct node等价*/

main()
{
L l,p,q,r; /*用指针类型定义三个结点类型的指针*/
char ch;
l=(L)malloc(sizeof(Node)); /*分配内存空间*/
l->c='\0'; /*为头结点的数据域赋值,值为空*/
l->next=NULL; /*指明下一个结点目前不存在*/
q=l; /*q为游动指针,链表结点的连结要用*/
printf("Input a character:\n");
scanf("%c",&ch);
getchar();
while(ch!='!') /*输入!表示输入结束*/
{
p=(L)malloc(sizeof(Node)); /*为新输入的数据分配内存空间*/
p->c=ch;
p->next=NULL; /*新输入的结点在链表的最后,即它的后面没有其它元素*/
q->next=p; /*q用于将上一个元素链接至当前新元素*/
q=p; /*q自己移到当前最后一个元素,以备继续链接所用*/
scanf("%c",&ch);
getchar();
}
q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
printf("\n");

//以上完成了单链表的创建
q=l->next;
p=q->next;
r=p->next;
q->next=NULL;
while(r!=NULL)
{
p->next=q;
q=p;
p=r;
if(r->next!=NULL) //r后面还有结点,则逆置继续
r=r->next;
else
break;
}
r->next=q;
l->next=r; //头结点指向最后一个结点

q=l; /*输入整个链表前,先将q移到链表头,l一般不动*/
while(q->next!=NULL) /*若q所指向的元素后面还有其它元素,则将该元素的数据输出*/
{
printf("%c-->",q->next->c); /*q->next->c表示q所指向的下一个元素的数据*/
q=q->next; /*完成该元素的输出后,q移至下一个元素重复输出操作*/
}
printf("\n");
}


//约瑟夫环问题

#include<stdio.h>
#include<malloc.h>

typedef struct lnode
{
int num;
struct lnode *next;
}node,*L;

main()
{
int amount,start,circle,n,c;
L p,l,q;

printf("一共有几个人围成一圈?\n");
scanf("%d",&amount);
getchar();
printf("从第几个开始计数?\n");
scanf("%d",&start);
getchar();
printf("每几人一次循环?\n");
scanf("%d",&circle);
getchar();

l=(L)malloc(sizeof(node)); //头结点
l->next=NULL;
l->num=0;
q=l;
n=0;

while(n++<amount)
{
p=(L)malloc(sizeof(node));
p->next=NULL;
p->num=n;
q->next=p;
q=p;
}
q->next=l->next; //形成循环链表

//以上完成了单向循环链表的建立
p=l->next;
q=l;
n=1;
while(n++<start)
{
p=p->next;
q=q->next;
}
//退出循环时p,q分别位于指定位置

//接下去进行周期性结点删除,直到链表只余一个结点为止
n=1; //n计算被删除的结点的数量,当n=amount-1时删除结束
while(n++<amount)
{
c=1; //c作为循环临时变量
while(c++<circle)
{
p=p->next;
q=q->next;
}
//删除当前p指向的结点
printf("删除结点%d\t",p->num);
q->next=p->next;
p=p->next;
}
printf("\n最后剩下%d\n",p->num);
}

二、栈及其操作
//All copyright are preserved bycobby
/*建立堆栈*/

#include<stdio.h>
#include<malloc.h>
#define NULL 0

typedef struct node
{
char ch;
struct node *next;
}Snode,*stack;

main()
{
stack s,top,p;
char ch;

s=(stack)malloc(sizeof(Snode));
s->ch='\0';
s->next=NULL; /*建立栈底指针*/
top=s;
scanf("%c",&ch);
getchar();

while(ch!='!')
{
p=(stack)malloc(sizeof(Snode));
p->ch=ch;
p->next=top;
top=p;
scanf("%c",&ch);
getchar();
}

while(top->next!=NULL)
{
printf("%c-->",top->ch);
top=top->next;
}
printf("\n");
}


//All copyright are preserved bycobby
/*进栈与出栈*/

#include<stdio.h>
#include<malloc.h>
#define NULL 0

typedef struct node
{
char ch;
struct node *next;
}Snode,*stack;

main()
{
stack s,top,p;
char ch;
int choice;

s=(stack)malloc(sizeof(Snode));
s->ch='!';
s->next=NULL; /*建立栈底指针*/
top=s;
scanf("%c",&ch);
getchar();

while(ch!='!')
{
p=(stack)malloc(sizeof(Snode));
p->ch=ch;
p->next=top;
top=p;
scanf("%c",&ch);
getchar();
}

while(p->next!=NULL) //此处p可用top代替
{
printf("%c-->",p->ch);
p=p->next;
}
printf("\n");

/*以上建立了一个堆栈*/

printf("进栈或出栈?输入“1”为进栈,输入“2”为出栈,其它则退出程序\n");
scanf("%d",&choice);
getchar();
while(choice==1||choice==2) //若不是输入1或2,则不做任何操作
{
if(choice==1)
{
/*进栈*/
printf("\n输入要入栈的元素\n");
scanf("%c",&ch);
getchar();

p=(stack)malloc(sizeof(Snode));
p->ch=ch;
p->next=top;
top=p;
}
else if(choice==2)
{
if(top->next!=NULL)
top=top->next;
else
{
printf("栈已清空\n");
exit();
}
/*出栈*/
}
//printf("%c-->",top->ch);
p=top;
while(p->next!=NULL)
{
printf("%c-->",p->ch);
p=p->next;
}
printf("\n");
printf("进栈或出栈?输入“1”为进栈,输入“2”为出栈,其它则退出程序\n");
scanf("%d",&choice);
getchar();
}
}


//All copyright are preserved bycobby
//栈的应用,括号匹配
#include<stdio.h>
#include<malloc.h>
#define NULL 0
typedef struct node
{
char ch;
struct node *next;
}snode,*stack;

main()
{
stack s,top,p;
char *string,ch[100]="";

s=(stack)malloc(sizeof(snode)); //建立栈底元素
s->ch='\0';
s->next=NULL;
top=s;

printf("输入一个含括号的四则运算表达式:\n");
scanf("%s",ch);
string=ch;

while(*string!='\0')
{
if(*string=='('||*string=='['||*string=='{') //遇到左括号,入栈
{
p=(stack)malloc(sizeof(snode));
p->ch=*string;
p->next=top;
top=p;
}
else if(*string==')'||*string==']'||*string=='}') //遇到右括号
{
if(*string==')')
if(top->ch=='(') //括号匹配
top=top->next;
else
{
printf("小括号不匹配");
exit(0);
}
else if(*string==']')
if(top->ch=='[') //括号匹配
top=top->next;
else
{
printf("中括号不匹配");
exit(0);
}
else
if(top->ch=='{') //括号匹配
top=top->next;
else
{
printf("大括号不匹配");
exit(0);
}
}
string++;
}
if(top->ch!='\0')
printf("多出左括号%c\n",top->ch);

}

#3
cobby2007-10-26 15:48

三、队及其操作
//All copyright are preserved bycobby
//链队列的建立

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define NULL 0

typedef struct node //队列结点的基本数据结构,即队列中每个结点的类型
{
char c;
struct node *next;
}qnode,*basic_node;

typedef struct //队列实际上由头、尾两个结点指针构成,即头指针和尾指针唯一确定时,队列也被唯一确定
{
qnode *head;
qnode *rear;
}queue,*Q;

main()
{
Q q; //定义队列,结构体变量q中含有头指针head和尾指针rear,所以q是一个完整的队列(只不过队列为空)
//事实上,任何由Q定义的结构体变量都是一个独立完整的队列
basic_node p,l; //basic_node是基本结点类型,即是独立的结点,它是组成队列的基本元素。
//基本结点p,l和队列q的关系可由下图表示:
// (q->head)--->p--->l--->p--->l--->……--->p--->l--->(q->rear)
char ch;

q=(Q)malloc(sizeof(queue));
q->head=NULL; //初始化时队列为空
q->rear=NULL;

printf("输入队列元素:\n");
scanf("%c",&ch);
getchar();

while(ch!='!')
{
p=(qnode*)malloc(sizeof(qnode));
p->c=ch;
p->next=NULL; //新来的元素一定在队列的最后,它的后面没有其它元素
if(q->head==NULL)
{
q->head=p; //第一个元素入队时,队头指针指向它
l=q->head; //l指向第一个元素
}
l->next=p; //使前一个元素指向当前入队的新元素
l=p; //l移动到当前新元素,以备用下次入队操作
q->rear=p; //修改队尾指针,使其总是指向当前最后一个队列元素
scanf("%c",&ch);
getchar();
}
l=q->head;
while(l!=NULL)
{
printf("%c<--",l->c);
l=l->next;
}
printf("\n");
printf("头指针指向元素为%c\t尾指针指向元素为%c\n",q->head->c,q->rear->c );
}


//All copyright are preserved bycobby

//入队和出队

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define NULL 0

typedef struct node //队列结点的基本数据结构,即队列中每个结点的类型
{
char c;
struct node *next;
}qnode,*basic_node;

typedef struct //队列实际上由头、尾两个结点指针构成,即头指针和尾指针唯一确定时,队列也被唯一确定
{
qnode *head;
qnode *rear;
}queue,*Q;

main()
{
Q q; //定义队列,结构体变量q中含有头指针head和尾指针rear,所以q是一个完整的队列(只不过队列为空)
//事实上,任何由Q定义的结构体变量都是一个独立完整的队列
basic_node p,l; //basic_node是基本结点类型,即是独立的结点,它是组成队列的基本元素。
//基本结点p,l和队列q的关系可由下图表示:
// (q->head)--->p--->l--->p--->l--->……--->p--->l--->(q->rear)
char ch;
int choice;

q=(Q)malloc(sizeof(queue));
q->head=NULL; //初始化时队列为空
q->rear=NULL;

printf("输入队列元素:\n");
scanf("%c",&ch);
getchar();

while(ch!='!')
{
p=(qnode*)malloc(sizeof(qnode));
p->c=ch;
p->next=NULL; //新来的元素一定在队列的最后,它的后面没有其它元素
if(q->head==NULL)
{
q->head=p; //第一个元素入队时,队头指针指向它
l=q->head; //l指向第一个元素
}
l->next=p; //使前一个元素指向当前入队的新元素
l=p; //l移动到当前新元素,以备用下次入队操作
q->rear=p; //修改队尾指针,使其总是指向当前最后一个队列元素
scanf("%c",&ch);
getchar();
}
l=q->head;
while(l!=NULL)
{
printf("%c<--",l->c);
l=l->next;
}
printf("\n");
printf("头指针指向元素为%c\t尾指针指向元素为%c\n",q->head->c,q->rear->c );


//以上建立了一个队列

printf("输入1进行入队,输入2进行出队:\n");
scanf("%d",&choice);
getchar();

if(choice==1)
{
printf("\n输入要入队的元素:\n");
scanf("%c",&ch);
getchar();
p=(qnode*)malloc(sizeof(qnode)); //给新入队的元素分配内存空间
p->c=ch;
p->next=NULL; //新元素为最后一个元素
q->rear->next=p; //原来最后一个元素指向新入队的元素
q->rear=p; //修改队尾指针,使其指向当前最后一个元素
}
else if(choice==2)
q->head=q->head->next;
else
exit(0);

l=q->head;
while(l!=NULL)
{
printf("%c<--",l->c);
l=l->next;
}
printf("\n");
printf("头指针指向元素为%c\t尾指针指向元素为%c\n",q->head->c,q->rear->c );
}


//All copyright are preserved bycobby
//循环队列建立

#include<stdio.h>
#include<malloc.h>
#define MAX 8

typedef struct
{
char c[MAX]; //循环队列是顺序队列的一种,它的核心就是一个数组
int front; //整形变量,作为头指针用
int rear; //整形变量,作为尾指针用
}queue;

main()
{
queue *q;
char ch;
int i;

q=(queue*)malloc(sizeof(queue)); //生成一个空循环队列
for(i=0;i<MAX;i++)
q->c[i]='\0';
q->front=0;
q->rear=0;

printf("输入要入队的元素:\n");
scanf("%c",&ch);
getchar();
while(ch!='!')
{
if((q->rear+1)%MAX==q->front) //若队列已满
{
printf("队列已满,无法入队\n");
break;
}
else
{
q->c[q->rear]=ch; //rear指向当前可入队的数组元素位置

q->rear=(q->rear+1)%MAX; //修改尾指针,向后移动一个位置
//注意,不能简单使用q->rear++,不然会导致队列溢出
}
scanf("%c",&ch);
getchar();
}

for(i=q->front;i<q->rear;i=(i+1)%MAX) //能够用for循环,说明了顺序队列和链式队列的区别
printf("%c<--",q->c[i]);
printf("\n");
}


//All copyright are preserved bycobby
//循环队列的入队和出队操作

#include<stdio.h>
#include<malloc.h>
#define MAX 8

typedef structd
{
char c[MAX]; //循环队列是顺序队列的一种,它的核心就是一个数组
int front; //整形变量,作为头指针用
int rear; //整形变量,作为尾指针用
}queue;

main()
{
queue *q;
char ch;
int i,choice;

q=(queue*)malloc(sizeof(queue)); //生成一个空循环队列
for(i=0;i<MAX;i++)
q->c[i]='\0';
q->front=0;
q->rear=0;

printf("输入要入队的元素:\n");
scanf("%c",&ch);
getchar();
while(ch!='!')
{
if((q->rear+1)%MAX==q->front) //若队列已满
{
printf("队列已满,无法入队\n");
break;
}
else
{
q->c[q->rear]=ch; //rear指向当前可入队的数组元素位置

q->rear=(q->rear+1)%MAX; //修改尾指针,向后移动一个位置
//注意,不能简单使用q->rear++,不然会导致队列溢出
}
scanf("%c",&ch);
getchar();
}

printf("头指针指向元素为%d\t尾指针指向元素为%d\n",q->front,q->rear);

for(i=q->front;i<q->rear;i=(i+1)%MAX) //能够用for循环,说明了顺序队列和链式队列的区别
printf("%c-->",q->c[i]);
printf("\n");

//以上建立了一个循环队列
printf("输入1入队,输入2出队:\n");
scanf("%d",&choice);
getchar();

while(choice==1||choice==2)
{
if(choice==1)
{
printf("输入要入队的元素\n");
scanf("%c",&ch);
getchar();
if((q->rear+1)%MAX==q->front) //若队列已满
{
printf("队列已满,无法入队\n");
break;
}
else
{
q->c[q->rear]=ch; //rear指向当前可入队的数组元素位置
q->rear=(q->rear+1)%MAX; //修改尾指针,向后移动一个位置
//注意,不能简单使用q->rear++,不然会导致队列溢出
}
}
else if(choice==2)
{
if((q->front+1)%MAX!=q->rear) //队非空
{
q->c[q->front]='\0'; //删除元素
q->front=(q->front+1)%MAX; //修改队头指针
}
else
{
printf("队已清空\n");
break;
}
}

if(q->rear>q->front) //尾指针在头指针的右边
{
for(i=q->front;i<q->rear;i=(i+1)%MAX) //能够用for循环,说明了顺序队列和链式队列的区别
printf("%c<--",q->c[i]);
printf("\n");
}
else //尾指针在头指针的左边
{
for(i=q->front;i<(q->rear+MAX);i++) //能够用for循环,说明了顺序队列和链式队列的区别
printf("%c<--",q->c[i%MAX]);
printf("\n");
}
printf("头指针指向元素为%d\t尾指针指向元素为%d\n",q->front,q->rear);

printf("输入1入队,输入2出队:\n");
scanf("%d",&choice);
getchar();
}
}

四、串及其操作
//串的朴素匹配

#include<stdio.h>

main()
{
char str1[100],str2[100],*p;
int i=0,j=0,len_str1=0,len_str2=0,num=0;
printf("输入母串:\n");
scanf("%s",str1);
getchar();

printf("%输入子串:\n");
scanf("%s",str2);
getchar();

p=str1;
while(*p!='\0') //获取母串长度
{
len_str1++;
p++;
}

p=str2; //获取子串长度
while(*p!='\0')
{
len_str2++;
p++;
}

for(i=0;i<len_str1;i++) //i为母串下标
{
for(j=0;j<len_str2;j++) //j为子串下标
{
num++;
if(str1[i+j]!=str2[j])
break; //若当前字符不匹配,则指针向母串下一个字符移动
}
if(j==len_str2)
{
printf("子串在母串中的位置为%d\n",i+1);
//break; //若子串在母串中多次出现,则全部找到其位置。若恢复break语句则只找出最前的一个匹配子串
}
}
printf("母串长度为%d,子串长度为%d\n核心语句执行次数为%d\n",len_str1,len_str2,num);
}

#4
cobby2007-10-26 15:49

五、树(二叉树)及其操作
//二叉排序树

#include<stdio.h>
#include<stdlib.h>

typedef struct tnode
{
int num;
struct tnode *Lchild,*Rchild;
}Tnode,*Btree;

typedef struct snode
{
int num;
Btree r;
struct snode *next;
}Snode,*stack;

Btree root;

void describe_tree() //交互式显示哈夫曼树
{
Btree t;
stack s,top,temp;
int choice;

s=(stack)malloc(sizeof(Snode));
s->num=0;
s->next=NULL;
s->r=NULL;
top=s;

t=root;//t指向哈夫曼树的根结点

temp=(stack)malloc(sizeof(Snode)); //分配新栈结点
temp->num=t->num;
temp->next=top; //结点入栈
temp->r=t; //将当前二叉树结点指针给栈顶结点
top=temp; //修改栈顶指针

printf("输入1往左子树,输入2往右子树,输入3返回父结点,其它输入退出程序\n");
scanf("%d",&choice);
getchar();

while(choice==1||choice==2||choice==3)
{
if(choice==1) //往左子树
{
if(t->Lchild!=NULL)
{
t=t->Lchild;
temp=(stack)malloc(sizeof(Snode)); //分配新栈结点
//新结点入栈
temp->num=t->num;
temp->next=top; //结点入栈
temp->r=t; //将当前二叉树结点指针给栈顶结点
top=temp; //修改栈顶指针
printf("值为%d\n",t->num);
}
else //左子树不存在,当前结点已经是叶子结点
printf("无左孩子!\n");
}
else if(choice==2) //往右子树
{
if(t->Rchild!=NULL)
{
t=t->Rchild;
temp=(stack)malloc(sizeof(Snode)); //分配新栈结点
//新结点入栈
temp->num=t->num;
temp->next=top; //结点入栈
temp->r=t; //将当前二叉树结点指针给栈顶结点
top=temp; //修改栈顶指针
printf("值为%d\n",t->num);
}
else //右子树不存在,当前结点已经是叶子结点
printf("无右孩子!\n");
}
else if(choice==3) //返回父结点
{
if(top->next!=s) //栈非空
{
top=top->next;
t=top->r;
printf("值为%d\n",t->num);
}
else
printf("已经在根结点了!\n");
}

scanf("%d",&choice);
getchar();
}
}

void inorder(Btree r) //中序递归遍历
{
if(r!=NULL)
{
inorder(r->Lchild);
printf(" %d <",r->num);
inorder(r->Rchild);
}
}

main()
{
int array[100],n=0,i,choice;
Btree p,q;

for(i=0;i<100;i++)
array[i]=0;

printf("输入若干个整数,结束用\"0\"表示\n");
scanf("%d",&array[n++]);
getchar();
while(array[n-1]!=0)
scanf("%d",&array[n++]);

n=0;
if(array[n]!=0)
{
root=(Btree)malloc(sizeof(Tnode)); //建立二叉排序树的根结点
root->num=array[n];
root->Lchild=NULL;
root->Rchild=NULL;
n++;
}
else
exit(0);

while(array[n]!=0)
{
p=(Btree)malloc(sizeof(Tnode)); //依次给每个整数分配结点
p->num=array[n];
p->Lchild=NULL;
p->Rchild=NULL;

//分配完结点后,要插入到二叉树中合适的位置
q=root; //q初始化到根结点
while(q!=NULL)
{
if(q->num<p->num) //若新结点的值大于根结点的值,则往右子树
{
if(q->Rchild!=NULL) //当前结点有右孩子,则指针移向右孩子继续比较
q=q->Rchild;
else //当前结点没有右孩子,则新结点为当前结点的右孩子
{
q->Rchild=p;
break;
}
}
else
{
if(q->Lchild!=NULL) //当前结点有左孩子,则指针移向左孩子继续比较
q=q->Lchild;
else //当前结点没有左孩子,则新结点为当前结点的左孩子
{
q->Lchild=p;
break;
}
}
}
n++;
}


//建立二叉排序树完毕
//对其进行中序遍历

printf("\n哈夫曼树构造完成,是否查看哈夫曼树,输入1查看,其它输入跳过");
scanf("%d",&choice);
getchar();
if(choice==1)
describe_tree();

inorder(root);
printf("\n");
}

#5
cobby2007-10-26 15:50

哈夫曼算法程序太大,一个贴放不下,下面两个贴均为哈夫曼编码程序.

//2005/4/28
//All Copyright Are Reserved By cobby
//哈夫曼编码

#include<stdio.h>
#include<malloc.h>
#include<math.h>
#define NULL 0

typedef struct huff_code_node //存储编码的链表
{
char ch; //编码对应的字符
char code[100]; //字符对应的哈夫曼码
struct huff_code_node *next;
}hnode,*huff;

typedef struct tree_Node //二叉树结点
{
char ch; //字符内容
int amount; //字符在字符串中出现的次数
struct tree_Node *left,*right; //指向左子树与右子树
}tnode,*bt;

typedef struct list_node //链表结点
{
char ch; //存储字符串中的字符
int amount; //字符在字符串中出现的次数
tnode *son; //链表结点带有二叉子树的根结点指针
struct list_node *next; //指向链表中下一个结点
}Node,*L;

typedef struct stack_node
{
char ch; //存储字符
int amount; //出现次数
bt son; //指向二叉树的某结点
struct stack_node *next;
}snode,*stack;


char t[200],*str,*c; //用于存储和处理输入的字符串
bt root=NULL; //哈夫曼树
L l,p,q,new_node; //链表结点
huff hlist; //计算得到的编码表
int char_num; //输入的不同字符数量
int char_amount; //输入的所有字符数量
int code_sum; //哈夫曼编码总长


void initial() //初始化操作
{
l=(Node*)malloc(sizeof(Node)); //建立空链表
l->ch='\0';
l->amount=0;
l->son=NULL;
l->next=NULL;

str=t; //将字符串指针指向字符串的第一个位置
//键盘输入字符串
printf("输入字符串进行哈夫曼编码:\n");
scanf("%s",str);
getchar();
}

void pull_in_list()
{
int exist; //表示当前字符是否存在于链表中,0为不存在,1为已存在
int n; //计算输入不同字符的数量,计算后赋值给全局变量char_num
int m; //计算输入所有字符的数量,计算后赋值给全局变量char_amount

c=str; //c指向第一个字符

while(*c!='\0') //若字符串未读完
{
exist=0;
p=l; //p指向链表头结点
//寻找该字符是否已经在链表中
while(p->next!=NULL) //若链表非空
{
p=p->next;
if(p->ch==*c) //若当前字符已经在链表中
{
exist=1;
p->amount++; //字符出现次数加1
break;
}
}

if(exist==0) //若当前字符不存在于链表中,则分配一个结点入表
{
new_node=(Node*)malloc(sizeof(Node));
new_node->ch=*c;
new_node->amount=1;
new_node->next=NULL;
new_node->son=NULL;
p->next=new_node;
p=new_node;
}
c++; //读下一个字符
}

printf("统计结果:\n");
p=l;
n=0;
m=0;
while(p->next!=NULL)
{
n++;
p=p->next;
m+=p->amount;
printf("%c——%d\n",p->ch,p->amount);
}
char_num=n;
char_amount=m;
printf("一共有%d种字符输入,字符总数%d\n",char_num,char_amount);
}

int list_element_amount() //计算链表中结点的数量(不包括头结点)
{
L temp; //定义临时指针
int n=0; //结点数量
temp=l;
while(temp->next!=NULL) //后面还有结点
{
n++;
temp=temp->next;
}
return n;
}

bt create() //建立最优二叉树
{
//=========================================
//这些变量用于寻找最小结点
L min1_pos,min2_pos,t,min_pri;
bt min1_son,min2_son;
int min1,min2;
char min1_c,min2_c;
//=========================================

//=========================================
//这些变量用于构造二叉子树
bt left,right,root;
//==========================================

//==========================================
//这些变量用于将二叉子树信息插入链表
L made,temp_p;
//============================================

while(list_element_amount()>=2) //若表中还有两个或以上结点,则归并继续
{
//选择次数值最小的两个结点

//============================================================================
//先寻找第一个小结点
t=l->next;
min1=t->amount; //将第一个结点的次数值赋给min1
min1_pos=t; //将第一个结点的位置指针赋给min1_pos
min1_c=t->ch; //将第一个结点的字符赋值给min1_c
min1_son=t->son; //将第一个结点的二叉指针赋值给min1_son
min_pri=l; //min_pri始终指向最小结点的前驱,以方便删除最小结点

while(t->next!=NULL)
{
t=t->next;
if(min1>t->amount) //发现更小的结点
{
min1=t->amount; //将当前结点的次数值赋给min1
min1_pos=t; //将当前结点的位置指针赋给min1_pos
min1_c=t->ch; //将当前结点的字符赋值给min1_c
min1_son=t->son; //将当前结点的二叉指针赋值给min1_son
}
}//退出本循环时,最小结点的信息找出,将该结点删除

min_pri=l;
while(min_pri->next!=min1_pos)
min_pri=min_pri->next;
//退出循环时min_pri指向min1_pos的前驱
min_pri->next=min1_pos->next; //删除结点min1_pos
//寻找第一个小结点完成
//=================================================================

//=================================================================
//先寻找第二个小结点
t=l->next;
min2=t->amount; //将第二个结点的次数值赋给min2
min2_pos=t; //将第二个结点的位置指针赋给min2_pos
min2_c=t->ch;
min2_son=t->son;
min_pri=l; //min_pri始终指向最小结点的前驱,以方便删除最小结点

while(t->next!=NULL)
{
t=t->next;
if(min2>t->amount) //发现更小的结点
{
min2=t->amount; //将当前结点的次数值赋给min2
min2_pos=t; //将当前结点的位置指针赋给min2_pos
min2_c=t->ch;
min2_son=t->son;
}
}//退出本循环时,最小结点的信息找出,将该结点删除

min_pri=l;
while(min_pri->next!=min2_pos)
min_pri=min_pri->next;
//退出循环时min_pri指向min1_pos的前驱
min_pri->next=min2_pos->next; //删除结点min2_pos
//寻找第二个小结点完成
//=================================================================


//==================================================================
//两个最小结点找到,由这对结点级成一个二叉子树,将根结点插入链表中
if(min1_son==NULL) //该结点无二叉子树指针,则须新分配一个二叉树结点
{
left=(bt)malloc(sizeof(tnode)); //产生左孩子
left->amount=min1; //次数值复制
left->ch=min1_c; //字符复制
left->left=NULL;
left->right=NULL;
}
else //该结点为计算产生的结点,它已指向一个二叉子树
left=min1_son; //left直接指向已经生成的二叉子树的根结点

if(min2_son==NULL) //该结点无二叉子树指针,则须新分配一个二叉树结点
{
right=(bt)malloc(sizeof(tnode)); //产生右孩子
right->amount=min2; //次数值复制
right->ch=min2_c; //字符复制
right->left=NULL;
right->right=NULL;
}
else
right=min2_son; //left直接指向已经生成的二叉子树的根结点

root=(bt)malloc(sizeof(tnode));
root->amount=min1+min2;
root->ch='\0'; //对于计算产生的树结点,字符均为空
root->left=left;
root->right=right;
//二叉子树完成

//生成一个对应上面已产生二叉子树地址的链表结点
made=(L)malloc(sizeof(Node));
made->amount=root->amount;
made->ch=root->ch;
made->next=NULL;
made->son=root;

//将生成的链表结点插入链表中
temp_p=l;
while(temp_p->next!=NULL)
temp_p=temp_p->next;
//退出循环时temp_p指向链表最后一个结点
temp_p->next=made; //将生成的结点插入链表
}

temp_p=l->next;
return temp_p->son;
}

void encoding() //根据建立的哈夫曼树编码
{
stack code,top,temp,readcode;
bt r;
huff temp_huff,hp;
char huff[100]=""; //用于存储当前字符的哈夫曼编码串
int i,j,n=0;

hlist=(hnode*)malloc(sizeof(hnode));
hlist->ch='\0';
for(i=0;i<100;i++)
hlist->code[i]='\0';
hlist->next=NULL;
hp=hlist;

//建立空栈
code=(stack)malloc(sizeof(snode));
code->amount=0;
code->ch='\0';
code->next=NULL;
code->son=NULL; //栈的头结点指向树的根结点
top=code;

r=root;
temp=(stack)malloc(sizeof(snode)); //给哈夫曼树的根结点分配栈结点
temp->amount=r->amount;
temp->ch='0';
temp->next=top;
temp->son=r;
top=temp;

while(r!=NULL) //当前结点存在
{
if(r->left!=NULL&&r->left->amount!=-1) //当前结点有左孩子
{
r=r->left; //r转向左孩子
r->amount=-1;

temp=(stack)malloc(sizeof(snode)); //给左孩子分配栈结点
temp->amount=r->amount;
temp->ch='0';
temp->next=top;
temp->son=r;
top=temp;
}
else if(r->right!=NULL&&r->right->amount!=-1) //当前结点有右孩子
{
r=r->right; //r转向右孩子
r->amount=-1;

temp=(stack)malloc(sizeof(snode)); //给右孩子分配栈结点
temp->amount=r->amount;
temp->ch='1';
temp->next=top;
temp->son=r;
top=temp;
}
else //无未访问的孩子结点
{

if(r->left==NULL&&r->right==NULL) //当前结点为叶子结点
{
for(i=0;i<100;i++) //对哈夫曼编码数组初始化
huff[i]='\0';

//先输出该叶子结点的编码
printf("字符%c,编码为:",r->ch);
readcode=top;
i=0;

while(readcode!=code)
{
huff[i++]=readcode->ch; //将栈元素倒置入哈夫曼编码数组中
readcode=readcode->next;
}

temp_huff=(hnode*)malloc(sizeof(hnode)); //为当前字符及其编码创建结点
temp_huff->ch=r->ch; //存储编码的原字符
for(j=0;j<100;j++) //初始化编码串数组
temp_huff->code[j]='\0';

j=0;

for(i=i-2;i>=0;i--) //依次读出哈夫曼编码数组中的编码串
{
printf("%c",huff[i]);
temp_huff->code[j++]=huff[i];
}
temp_huff->next=NULL;
hp->next=temp_huff;
hp=temp_huff;

printf("\t\t");
if(++n%2==0)
printf("\n");
}

if(top->next!=code) //若栈非空
{
top=top->next;
r=top->son;
}
else
break;
}
}
}

#6
cobby2007-10-26 15:50

void describe_tree() //交互式显示哈夫曼树
{
bt t;
stack s,top,temp;
int choice;

s=(stack)malloc(sizeof(snode));
s->amount=0;
s->ch='\0';
s->next=NULL;
s->son=NULL;
top=s;

t=root;//t指向哈夫曼树的根结点

temp=(stack)malloc(sizeof(snode)); //分配新栈结点
temp->amount=t->amount;
temp->ch=t->ch;
temp->next=top; //结点入栈
temp->son=t; //将当前二叉树结点指针给栈顶结点
top=temp; //修改栈顶指针

printf("输入1往左子树,输入2往右子树,输入3返回父结点,输入4退出程序,其它输入无效\n");
scanf("%d",&choice);
getchar();

while(choice==1||choice==2||choice==3)
{
if(choice==1) //往左子树
{
if(t->left!=NULL)
{
t=t->left;
temp=(stack)malloc(sizeof(snode)); //分配新栈结点
//新结点入栈
temp->amount=t->amount;
temp->ch=t->ch;
temp->next=top; //结点入栈
temp->son=t; //将当前二叉树结点指针给栈顶结点
top=temp; //修改栈顶指针
printf("%c,%d\n",t->ch,t->amount);
}
else //左子树不存在,当前结点已经是叶子结点
printf("无左孩子!\n");
}
else if(choice==2) //往右子树
{
if(t->right!=NULL)
{
t=t->right;
temp=(stack)malloc(sizeof(snode)); //分配新栈结点
//新结点入栈
temp->amount=t->amount;
temp->ch=t->ch;
temp->next=top; //结点入栈
temp->son=t; //将当前二叉树结点指针给栈顶结点
top=temp; //修改栈顶指针
printf("%c,%d\n",t->ch,t->amount);
}
else //右子树不存在,当前结点已经是叶子结点
printf("无右孩子!\n");
}
else if(choice==3) //返回父结点
{
if(top->next!=s) //栈非空
{
top=top->next;
t=top->son;
printf("%c,%d\n",t->ch,t->amount);
}
else
printf("已经在根结点了!\n");
}
//else if(choice==4) //退出程序
// exit(0);

scanf("%d",&choice);
getchar();
}
}


void codeoutput() //输出原始字符串的哈夫曼编码串
{
huff hp;
//char *s;
int i;
c=str; //c指向原始字符串str的首位置
printf("\n\n原始字符串为:%s\n哈夫曼编码为:",c);
code_sum=0;
//在编码链表中找寻与c匹配的编码串
while(*c!='\0') //字符串未读完
{
hp=hlist->next; //hp指向编码链表的第一个字符编码组

while(hp->ch!=*c&&hp->next!=NULL) //尚未找到匹配字符且后面还有字符
hp=hp->next;
//退出循环的原因可能是找到了匹配字符,也可能是链表读完,需要进一步判断
if(hp->ch==*c) //找到匹配字符
{
i=0;
while(hp->code[i]!='\0')
printf("%c",hp->code[i++]);
}
code_sum+=i;
c++;
}
printf("\n\n");
}

void analyze() //编码性能分析
{
int n=0;
printf("\t\t\t性能分析中...\n\n");
while(pow(2,n)<char_num) //计算等长编码情况下需要的编码位数
n++;
printf("等长码需要 %d 位,编码总长 %d 位,本次哈夫曼编码总长 %d , 压缩比 %g\n",n,n*char_amount,code_sum,(float)code_sum/(n*char_amount));

}

main()
{
int choice;
//初始化,操作包括建立空链表和键盘输入字符串
initial();

//将接收的字符串依次读入链表中,并统计出现的次数
pull_in_list();

//建立最优二叉树
root=create();

//交互式显示哈夫曼树
if(root!=NULL)
{
printf("\n哈夫曼树构造完成,是否查看哈夫曼树,输入1查看,其它输入跳过");
scanf("%d",&choice);
getchar();

if(choice==1)
describe_tree();
}
else
{
printf("哈夫曼树未建立,查看字符串中是否只含一种字符,或者重试\n");
exit();
}

//要挟据建立的最优二叉树进行编码
encoding();

//将原始字符串的哈夫曼编码串输出
codeoutput();

//编码性能分析
analyze();

printf("\n\n\t\t\tAll Copyright Are Presevered By cobby\n\n输入任何键退出\n");
scanf("%d",&choice);
}

#7
cobby2007-10-26 15:50

六、排序
/* 冒泡排序 */

#include<stdlib.h>
#include<stdio.h>

main()
{
int i,j,temp,a[30000];
long TIME=0;
rand();

for(i=0;i<30000;i++)
{
a[i]=rand();
printf("%d\t",a[i]);
}

for(i=29999;i>=0;i--)
for(j=0;j<=i;j++)
if(a[j+1]<a[j])
{
TIME++;
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
}

for(i=0;i<=29999;i++)
printf("%d\t",a[i]);
printf("\n%d\n",TIME);
}


/* 直接选择排序法 */

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
//#include<time.h>

main()
{
int i,j,value,pos,temp,a[30000];
long TIME=0;

rand();
for(i=0;i<30000;i++) /* make up the rand numbers*/
{
a[i]=rand();
printf("%d\t",a[i]);
}

for(i=0;i<30000;i++) /* sort */
{
value=a[i];
pos=i;
for(j=i+1;j<30000;j++)
{
TIME++;
if(value>a[j])
{
value=a[j];
pos=j;
}
}
temp=a[i];
a[i]=a[pos];
a[pos]=temp;
}
for(i=0;i<30000;i++)
printf("%d\t",a[i]);
printf("\n\n%ld\n",TIME);
}

#8
cobby2007-10-26 15:51
完毕!!!!
#9
shlg12292007-10-26 16:19
回复:(cobby)完毕!!!![em05][em05][em05][em05...

好东西。顶~~~

#10
nuciewth2007-10-26 19:34
l=(L)malloc(sizeof(L)); /*分配内存空间*/
老师啊,这样也行?
#11
cobby2007-10-26 20:38
请指教,为什么不行?
#12
nuciewth2007-10-26 20:44
L是个什么东西呢?
#13
aipb20072007-10-26 21:40

以来是老师,有礼了!

#14
cobby2007-10-27 08:45
以下是引用nuciewth在2007-10-26 20:44:14的发言:
L是个什么东西呢?

版主大人,请您再指出错误前把程序看仔细了啊。。。


typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}*L; /*类型重定义,即Node和*L和struct node等价*/

L是个链表结点啊,汗啊。。。

#15
cobby2007-10-27 08:46
并且我已经说过了,以上所有程序均在VC++6.0环境下调试通过,运行正常
#16
nuciewth2007-10-27 11:36

我没有别的意思只是觉得l=(L)malloc(sizeof(L));
按理来说,申请的指针类型和分配空间的类型应该不一样吧。
像是这样的
p=(node*)malloc(sizeof(node))
我们老师是这样教的。所以我就是这样记的了。

#17
ink12192007-10-27 11:50

好东西,顶下

#18
cobby2007-10-27 12:00
以下是引用nuciewth在2007-10-27 11:36:22的发言:

我没有别的意思只是觉得l=(L)malloc(sizeof(L));
按理来说,申请的指针类型和分配空间的类型应该不一样吧。
像是这样的
p=(node*)malloc(sizeof(node))
我们老师是这样教的。所以我就是这样记的了。

呵呵,你们老师只讲了一半。当类型是实类型(非指针)时,是按你写的这样子的,实类型名后要加*;
当类型是指针类型的时候,名称后面的*就不要加了。至于sizeof函数中的参数,用实类型和指针类型都行。
呵呵,下次别忘了哦

#19
giant6112007-10-27 14:07
好是好,就是太冗余了,尤其是链表那一块,每次都建一下链表,提倡obj
#20
cobby2007-10-27 14:23
以下是引用giant611在2007-10-27 14:07:07的发言:
好是好,就是太冗余了,尤其是链表那一块,每次都建一下链表,提倡obj

楼上说的很对,从程序上说是这样的。不过这程序主要是以前给学生当课堂上的例程讲解的,所以每次都一步一步来的,不然大专学生听数据结构有点困难的。这些程序如果要去用的话可以根据自身情况加以修改的。

#21
nuciewth2007-10-27 16:29

真的啊.
老师你的意思是说sizeof(node)==sizeof(node*)
是这样的吗?

#22
cobby2007-10-27 16:31
以下是引用nuciewth在2007-10-27 16:29:22的发言:

真的啊.
老师你的意思是说sizeof(node)==sizeof(node*)
是这样的吗?

你还不理解我的意思。。。是前面那个不用加*号,如果它已经是指针类型。。。汗那。。。

#23
nuciewth2007-10-27 16:39
我这个学生很难教吧.
老师
#24
nuciewth2007-10-27 16:42
再跟老师说一遍.
我不是不懂用指针就可以.
我只是不懂,为什么这个申请空间的语句中前后都用L.
#25
cobby2007-10-27 17:14
呵呵,没事,讨论一下也好,版主你还是很有水平和见解的。我再仔细说一下吧。你看看想下呵。

首先我有如下定义:
#define NULL 0 /*宏定义*/
typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}*L; /*类型重定义,即Node和*L和struct node等价*/

注意最后一句注释,此时Node和*L和struct node等价

然后我用上面的链表结点定义指针:
L l,p,q; /*用指针类型定义三个结点类型的指针*/

这个时候L和*node是等价的对吗?

由于l是指针,在C中没有分配到内存,所以我要给它分配空间,即
l=(L)malloc(sizeof(L)); /*分配内存空间*/

这句话和
1、l=(node*)malloc(sizeof(L));
2、l=(node*)malloc(sizeof(node));
3、l=(L)malloc(sizeof(node));

都是等价的。

至于为什么我都用L而不用node,是因为在这类程序中,使用指针比较灵活,通常定义一个指针而不是直拉用实类型node。


这下应该明白了吧?

再不明白的话就建议你再复习下数据结构的教材了呵。
#26
succubus2007-10-27 18:00
l=(L)malloc(sizeof(L)); /*分配内存空间*/

这句话和
1、l=(node*)malloc(sizeof(L));
2、l=(node*)malloc(sizeof(node));
3、l=(L)malloc(sizeof(node));
-----------------------------------------------------
我和nuciewth有一样的疑问啊
为什么第二个L就换成node了?
应该也是node*啊

l=(L)malloc(sizeof(L));应该等价于l=(node*)malloc(sizeof(node*));这个吧?
如果是这样,岂不是有问题吗?

[此贴子已经被作者于2007-10-27 18:00:37编辑过]

#27
静思2007-10-27 18:48
我也有这样的问题:l=(L)malloc(sizeof(L))。
既然L为指针,那么指针变量的sizeof值与指针所指的对象(结构体)没有任何关系,所有的指针变量所占内存大小相等。
比如以下例子
typedef struct node
{
char c;
struct node *next;
}*L;
char* pc ="abc";
int* pi;
string* ps;
char** ppc = &pc;
void (*pf)(); // 函数指针
sizeof( pc ); // 结果为4
sizeof( pi ); // 结果为4
sizeof( ps ); // 结果为4
sizeof( ppc );// 结果为4
sizeof( pf ); // 结果为4
sizeof( L ); // 结果为4
#28
nuciewth2007-10-27 19:24
哈哈,如果有人和我有相同的意见.
我还是想说那句话,老师,我并不是不知道
L等价node*
按道理也 应该是这样写p=(L)malloc(sizeof(node))//后面是结点空间,而不是指针空间.
老师,我说对不对.
#29
cobby2007-10-27 20:57
静思的实验已经给出结果了。我再说明一下,大家看看是不是这样的。

l=(L)malloc(sizeof(L));

第一个参数(L)是类型,第二个参数(L)是大小,两个参数的意义和作用是不一样的。
当第一个参数为实类型时,如node,则需要用node*,而当第一个参数是指针类型时,如L,则不需要*,直接写L。对于这一点大家都没意见。

现在大家的问题在第二个参数上。第二个参数的作用是确定待分配内存空间的大小,仅此而已,和类型没有任何关系。如果你预先知道需要分配的空间大小(如4),你甚至可以直接写sizeof(4),所以后面的参数即可以用L,也可以用node,但不是node*,因为这个表示没有意义。


最后说明,如果大家还是有疑问,请把我的程序复制到VC++或者其它编译器中运行,你们可以试着把l=(L)malloc(sizeof(L))用我给出的四种不同形式替换,看看结果有没有问题。

对于这个问题我本人的讨论到此。
#30
nuciewth2007-10-27 21:17

我再也不发表任何意见了.
就这样吧.不讨论了.

#31
nuciewth2007-10-27 21:23
如果连学生提出的问题不能完全的替学生解决,那老师也不是很称职吧.
我有过用编译器编译,(C-FREE)编译的结果和我预测的一样,那条语句是编译错误.(貌似不能说完全错)
我有对帖子提出疑问的权利,对你想不想解释我没有办法.
我不发表我没有任何把握的想法,除非我看错内容了.
#32
cobby2007-10-27 21:38
小朋友言重了,年轻人容易激动呵。你有提问的权利,我也有不回答的权利嘛,而且我回答了好多次了,讲不明白我也没办法呀。你说是吧?
#33
succubus2007-10-27 21:46
[CODE]

#include <stdio.h>

#define NULL 0 /*宏定义*/

typedef struct node /*定义结点类型的数据结构*/
{
char c; /*数据域,类型为字符型*/
struct node *next; /*指针域,类型为本结构体类型*/
}*L; /*类型重定义,即Node和*L和struct node等价*/

int main()
{
printf("%d\n",sizeof(L));
printf("%d\n",sizeof(struct node));
return 0;
}

[/CODE]

我实在是忍不住想说几句了

楼主自己把这段代码运行下看是啥结果
在vc里面一个是4,一个是8;
知道这意味着什么吗?

我就想不明白了
不就是一处小错误吗
谁都有犯错的时候
老师也不例外
nuciewth发现了错误向你指出来了
你接受了改正一下不就成了吗
非要极力掩饰自己的错误
这样有意思吗?

就是因为面子上挂不住?
本来我上面的回复已经考虑到这个问题
为了照顾楼主您所在意的面子
已经很含蓄很隐晦的指出你的错误了
只是希望你能改正而已
没想到还是这样
那我只能把话说透了

其实这个nuciewth提出的这个错误在楼主这个帖子刚发出来的时候我一眼就看出来了
我当时并没有像nuciewth明确指出来
没指出来的原因就是因为看到楼主在正文里说自己曾是老师
怕说出来楼主面子上挂不住

但是现在想来,像nuciewth这样明确指出来是很有必要的
虽然我,静思,nuciewth以及其他对c,c++比较理解的人都不难看出这个错误
可是这个错误对新手的影响实在是很大的

行了
话就说到这里
还是那句
人无完人,孰能无过?
犯错了并不可怕
可怕的是明知道自己错了还不愿去正视这个错误
反而极力去掩饰自己错误的人

话已至此
只是就事论事,并不针对任何个人
从这里我也不再对此帖发表任何评论

[此贴子已经被作者于2007-10-27 22:02:31编辑过]

#34
cobby2007-10-27 22:23
关于程序中错误的郑重道歉
各位网友:
由于本人学识浅薄,加之操作疏忽,因而在上传之贴中存在一处严重的错误,即“l=(L)malloc(sizeof(L))”。由于本人知识储备不足,毕业及从教来一直认为L等价于struct node,造成程序潜在的错误。期间有多位网友不讹指正,但由于本人在执行这些程序中,所存在的错误一直没暴露出来,因而一直认为该程序正确无误而未加调试。
在此,对本人的愚昧无知和粗心大意表示最真诚的道歉!
感谢各位网友的严词批评,这对本人是一次很好的教育。在此仅想说明一点,本人不才,但从事学术研究也已四年有余,对于面子一说无从谈起,这次低级错误实为疏忽所致,敬请大家原谅。
本人会立即改正程序中中这个错误,并请大家继续批评指正,是为心声。



网友:cobby
#35
ljxu2008-10-23 10:34
牛!!!1
#36
geninsf0092008-10-23 10:59
牛...
#37
mysky1232008-10-25 00:18
拿下!
#38
yingwufenghua2008-10-25 00:36
对编程提不起兴趣!!!怎么办?
#39
yingwufenghua2008-10-25 01:20
怎么了?
#40
masterqq2008-10-27 19:55
下载学习了

谢谢lz分享
#41
buhongwei2008-10-31 21:00
怎么都有一个错误呢!运行不了啊。是不是我的电脑坏掉了。
#42
吸血鬼伯爵2008-11-02 22:16
爱你
我想我会记得你的。。。嘿嘿
#43
zhuimengR2008-11-23 18:09
楼主辛苦了
#44
leilong2008-11-25 02:19
回复 第40楼 masterqq 的帖子
看完了真么长的 回复真的是很有感慨,感谢 楼主cobby老师的 写的那么多代码。也同样感谢您的 错误,使我更了解malloc的用法。

最后,感谢 静思,nuciewth,succubus 你们真诚的指正,让我们这些初学者 找到了正确的东西。 由 楼主cobby老师 的错误,又由于 静思,nuciewth,succubus 的指正,使我们新手 真正明白了malloc的用法,

正由于你们的辩论,使得 这个帖子 十分,精彩。
#45
cr43152008-12-08 15:07
太好了,非常感谢你!!
#46
luo35328692009-08-04 11:58
呵呵,很好的帖子
#47
lj22602011-11-23 14:53
一个字牛
#48
iwtctw02012-08-06 10:46
  好东西,做的不错。楼主辛苦了。顶!
#49
RT00002012-10-15 12:22
辛苦了!!!
#50
lidonghaha2012-10-23 15:12
好流弊哦~~~~~
#51
chtian2012-12-05 23:14
学习。
1