用c语言实现了二叉树的数据定义,二叉树的构建、销毁,以及先序、中序、后序的递归算法,非递归算法正在研究中。
/*--------------------------------------------------------------------------------------------*/
// 二叉树的二叉链表存储结构C语言实现。
// 实现了利用先序序列创建一棵二叉树,先序、中序、后序遍历算法的递归
// 和非递归算法。
// 版本: v1.0
// 环境:Visual C++ 6.0
// 作者: sunnyrain
// 日期: 2007-8-24
/*--------------------------------------------------------------------------------------------*/
//BiTree.h
struct BiTNode //采用二叉链表存储结构
{
char data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode;
struct BiTNode* CreateBiTree();
int DestroyBiTree(struct BiTNode* T);
int visit(char elem);
//递归遍历算法
int PreOrderTraverse_R(struct BiTNode* T, int (*visit)(char elem));
int InOrderTraverse_R(struct BiTNode* T, int (*visit)(char elem));
int PostOrderTraverse_R(struct BiTNode* T, int (*visit)(char elem));
//非递归遍历算法
void PreOrderTraverse(struct BiTNode* T, int (*visit)(char elem));
void InOrderTraverse(struct BiTNode* T, int (*visit)(char elem));
void PostOrderTraverse(struct BiTNode* T, int (*visit)(char elem));
//stack.h 堆栈数据结构,用于非递归算法中的附加空间
#define STACK_SIZE 256
struct stack
{
struct BiTNode* elem[STACK_SIZE];
int top; //top总是指向栈顶元素的上一个元素
int bottom; //恒0
};
void initStack(struct stack* s);
struct BiTNode* getTop(struct stack* s);
struct BiTNode* pop(struct stack* s);
void push(struct stack* s,struct BiTNode* p);
int isEmpty(struct stack* s);
//stack.c 堆栈的实现
#include<stdio.h>
#include<string.h>
#include "stack.h"
//初始化堆栈为0,栈指针为0
void initStack(struct stack* s)
{
memset(s->elem,0,STACK_SIZE);
s->top = s->bottom = 0;
}
//获取栈顶元素,栈顶指针不变
struct BiTNode* getTop(struct stack* s)
{
return s->elem[s->top-1];
}
//弹出&返回栈顶元素
struct BiTNode* pop(struct stack* s)
{
if(s->top == s->bottom) //若栈空
{
printf("Stack is empty!/n");
return 0;
}
--s->top;
return s->elem[s->top];
}
//将pB指针压入栈中
void push(struct stack* s,struct BiTNode* pB)
{
if(s->top<STACK_SIZE) //栈未满
{
s->elem[s->top] = pB;
++s->top;
}
else
printf("Stack is full!/n");
}
//判断栈是否为空,空返回非0
int isEmpty(struct stack* s)
{
return s->top == s->bottom;
}
//BiTree.c 二叉树创建、销毁、递归算法实现
#include<stdio.h>
#include<malloc.h>
#include "BiTree.h"
#include "stack.h"
struct BiTNode* CreateBiTree() //采用先序递归方法创建一棵二叉树
{
struct BiTNode* T;
char ch,tmp;
printf("please input the value of the node:/n");
scanf("%c",&ch);
tmp = getchar(); //忽略回车符
if(ch == '&') //输入&符号表示此节点为空
{
printf("Null BiTreeNode Created!/n");
T = NULL;
return NULL;
}
T = (struct BiTNode *)malloc(sizeof(BiTNode)); //为当前节点分配内存
if(!T)
{
printf("Allocate memory failed!/n");
return NULL;
}
T->data = ch; //为当前节点赋值
T->lchild = CreateBiTree(); //递归创建左子树
T->rchild = CreateBiTree(); //递归创建右子树
return T;
}
//销毁二叉树,销毁成功返回0,错误返回1
int DestroyBiTree(struct BiTNode* T)
{
if(T)
{
struct BiTNode* lchild = T->lchild;
struct BiTNode* rchild = T->rchild;
free(T);
if(0 == DestroyBiTree(lchild))
{
if(0 == DestroyBiTree(rchild))
return 0;
else
return 1;
}
}
return 0;
}
//访问节点元素
int visit(char elem)
{
if(elem == '&')
return 1;
printf("%c ",elem);
return 0;
}
//先序遍历递归算法,返回值为0表示遍历成功,1为失败
int PreOrderTraverse_R(struct BiTNode* T, int (*visit)(char elem))
{
if(T)
{
if(0 != visit(T->data)) //访问根节点
return 1;
if(T->lchild)
{
if(0 != InOrderTraverse_R(T->lchild,visit)) //递归遍历左子树
return 1;
}
if(T->rchild)
{
if(0 != InOrderTraverse_R(T->rchild,visit)) //递归遍历右子树
return 1;
}
}
return 0;
}
//中序遍历递归算法,返回值为0表示遍历成功,1为失败
int InOrderTraverse_R(struct BiTNode* T, int (*visit)(char elem))
{
if(T)
{
if(T->lchild)
{
if(0 != InOrderTraverse_R(T->lchild,visit)) //递归遍历左子树
return 1;
}
if(0 != visit(T->data)) //访问根节点
return 1;
if(T->rchild)
{
if(0 != InOrderTraverse_R(T->rchild,visit)) //递归遍历右子树
return 1;
}
}
return 0;
}
//后序遍历递归算法,返回0表示遍历成功,1为失败
int PostOrderTraverse_R(struct BiTNode* T, int (*visit)(char elem))
{
if(T)
{
if(T->lchild)
{
if(0 != PostOrderTraverse_R(T->lchild,visit)) //递归遍历左子树
return 1;
}
if(T->rchild)
{
if(0 != PostOrderTraverse_R(T->rchild,visit)) //递归遍历右子树
return 1;
}
if(0 != visit(T->data)) //访问根节点
return 1;
}
return 0;
}
//先序遍历非递归算法
void PreOrderTraverse(struct BiTNode* T, int (*visit)(char elem))
{
struct stack ss;
struct BiTNode* p = T;
initStack(&ss);
while(p||!isEmpty(&ss))
{
if(p)
{
visit(p->data);
push(&ss,p);
p=p->lchild;
}
else
{
p = getTop(&ss);
pop(&ss);
p = p->rchild;
}
}
}
//中序遍历非递归算法
void InOrderTraverse(struct BiTNode* T, int (*visit)(char elem))
{
struct stack ss;
struct BiTNode* p;
initStack(&ss);
push(&ss,T);
while(!isEmpty(&ss))
{
while(p = getTop(&ss))
push(&ss,p->lchild); //向左走到尽头
p = pop(&ss); //空指针退栈
if(!isEmpty(&ss))
{
p = pop(&ss);
visit(p->data); //访问节点
push(&ss,p->rchild); //向右一步
}
}
}
//后序遍历非递归算法
void PostOrderTraverse(struct BiTNode* T, int (*visit)(char elem))
{
struct stack ss;
struct BiTNode* p = T;
struct BiTNode* q;
initStack(&ss); //初始化空栈
while(p || !isEmpty(&ss))
{
if(p)
{
push(&ss,p);
p = p->lchild;
}
else
{
p =getTop(&ss);
if(p)
{
push(&ss,NULL);
p = p->rchild;
}
else
{
pop(&ss);
q = pop(&ss);
visit(q->data);
}
}
}
}
//main.c 测试主程序
#include<stdio.h>
#include "BiTree.h"
int main()
{
struct BiTNode* bt = 0;
bt = CreateBiTree(bt);
printf("先序遍历序列:/n");
PreOrderTraverse_R(bt,visit);
printf("/n中序遍历序列:/n");
InOrderTraverse_R(bt,visit);
printf("/n后序遍历序列:/n");
PostOrderTraverse_R(bt,visit);
printf("/n非递归先序遍历序列:/n");
PreOrderTraverse(bt,visit);
printf("/n非递归中序遍历序列:/n");
InOrderTraverse(bt,visit);
printf("/n非递归后序遍历序列:/n");
PostOrderTraverse(bt,visit);
DestroyBiTree(bt);
return 0;
}
根据书上的算法写的,书上算法以数组0下标元素做哨兵,考虑到输入数组的时候不可能留个哨兵位置,就改写了一点,可以从0下标开始进行插入排序。
/*================================================================================
功能:对可以使用<进行比较的元素数组进行直接插入排序
作者:sunnyrain
日期:2008-09-10
编译环境:VC++6.0
=================================================================================*/
#include<iostream>
using namespace std;
template<class T>
void InsertSort(T* p,size_t length)
{
T senti; //替代哨兵p[0]
int i,j;
for(i=1;i<length;++i)
{
if(p[i]<p[i-1])
{
senti = p[i];
for(j=i-1;senti<p[j] && j>=0;--j) //与有哨兵的相比这里多了j>=0,否则会越界错误
{
p[j+1] = p[j];
}
p[j+1] = senti;
}
}
}
int main()
{
int a[10] ; //= {4,12,35,62,11,2,4,99,65,1};
cout<<"Input ten integers :"<<endl;
for(int i=0;i<10;i++)
{
cin>>a[i];
}
cout<<endl;
InsertSort(a,10);
cout<<"After sort:"<<endl;
for(int j=0;j<10;j++)
{
cout<<a[j]<<" ";
}
return 0;
}
其实和直接插入排序没有太大区别,只是查找过程使用了折半查找,总时间复杂度还是O(n^2),借此复习一下折半查找而已。
/*================================================================================
功能:对可以使用<进行比较的元素数组进行折半插入排序
作者:sunnyrain
日期:2008-09-10
编译环境:VC++6.0
=================================================================================*/
#include<iostream>
using namespace std;
template<class T>
void BInsertSort(T* p,size_t length)
{
T senti; //替代哨兵p[0]
int i,j,low,high,mid;
for(i=1;i<length;++i)
{
low = 0;
high = i-1;
mid = (low + high)/2;
while(low <= high) //折半查找过程
{
if(p[i] > p[mid])
{
low = mid + 1;
mid = (low + high)/2;
}
else
{
high = mid - 1;
mid = (low + high)/2;
}
}
senti = p[i];
for(j=i-1; j>=mid;--j) //移动元素&插入
{
p[j+1] = p[j];
}
p[high+1] = senti; //这里要用high代替j,否则当插入元素比前面所有元素都大时会出错
}
}
int main()
{
int a[10] = {4,12,35,62,11,2,4,99,65,1};
/* cout<<"Input ten integers :"<<endl;
for(int i=0;i<10;i++)
{
cin>>a[i];
}*/
cout<<endl;
BInsertSort(a,10);
cout<<"After sort:"<<endl;
for(int j=0;j<10;j++)
{
cout<<a[j]<<" ";
}
return 0;
}
书上的表插入排序没有给算法,虽然看起来很简单,由于是个环形链表,还是折腾了半天才找到正确插入位置。后面的重排是书上算法,抄过来还是很容易的
/*================================================================================
功能:表插入排序c++实现
作者:sunnyrain
日期:2008-09-11
编译环境:VC++6.0
=================================================================================*/
#include<iostream>
using namespace std;
const int SIZE = 100;
template<class T>
struct SLNode{
T elem;
int next;
};
template<class T>
struct List{
SLNode<T> r[SIZE];
int length;
};
template<class T>
void tableSort(List<T>& list) //表插入排序
{
list.r[0].next = 1;
list.r[1].next = 0;
for(int i=2;i<list.length;i++)
{
int j = list.r[0].next;
int pre = 0; //记录当前结点的前一位置
while(list.r[i].elem >= list.r[j].elem && j>0) //找插入位置
{
pre = j;
j = list.r[j].next; //链表向前走一步
}
list.r[i].next = j; //插入的结点next域指向j结点
list.r[pre].next = i; //插入结点的前一个结点的next域指向插入结点
}
}
template<class T>
void Arrange(List<T>& list) //重排
{
int pre = list.r[0].next;
for(int i=1;i<list.length;i++)
{
while(pre<i)
pre = list.r[pre].next;
int q = list.r[pre].next;
if(pre != i)
{
SLNode<T> temp = list.r[pre];
list.r[pre] = list.r[i];
list.r[i] = temp;
list.r[i].next = pre;
}
pre = q;
}
}
int main()
{
List<int> list;
int length = 8;
// cout<<"请输入表长度:"<<endl;
// cin>>length;
list.length = length + 1;
// cout<<"请输入 "<<length<<" 个数字:"<<endl;
/* for(int i=1;i<list.length;i++)
{
cin>>list.r[i].elem;
}*/
list.r[1].elem = 49;
list.r[2].elem = 38;
list.r[3].elem = 65;
list.r[4].elem = 97;
list.r[5].elem = 76;
list.r[6].elem = 13;
list.r[7].elem = 27;
list.r[8].elem = 49;
for(int i=1;i<list.length;i++)
{
list.r[i].next = -1;
}
tableSort(list); //进行表插入排序
cout<<"排序结果(指针域顺序):"<<endl;
for(i=0;i<length+1;i++)
cout<<list.r[i].next<<"/t";
cout<<endl;
cout<<"重排结果:"<<endl;
Arrange(list); //重排静态链表
for(i=1;i<list.length;i++)
{
cout<<list.r[i].elem<<"/t";
}
cout<<endl;
for(i=1;i<list.length;i++)
{
cout<<list.r[i].next<<"/t";
}
cout<<endl;
return 0;
}
/*================================================================================
功能:shell排序c++实现
作者:算法都抄书上的,我就不算作者啦,作者严蔚敏吧,嘿嘿
日期:2008-09-11
编译环境:VC++6.0
=================================================================================*/
#include<iostream>
using namespace std;
template<class T>
void ShellInsert(T* p,size_t length,int dk) //一趟shell排序
{
T temp;
for(int i=dk;i<length;++i)
{
if(p[i]<p[i-dk])
{
temp = p[i];
for(int j=i-dk;j>=0 && temp<p[j];j-=dk) //一趟插入过程
p[j+dk] = p[j];
p[j+dk] = temp;
}
}
}
template<class T>
void ShellSort(T* p,size_t length, int dlta[],int t)
{
for(int k=0;k<t;++k)
{
ShellInsert(p,length,dlta[k]);
for(int j=0;j<length;j++) //打印每一趟排序后的结果
{
cout<<p[j]<<"/t";
}
cout<<endl;
}
}
int main()
{
int a[10] = {49,38,65,97,76,13,27,49,55,4};
int dlta[] = {9,5,3,1}; // dlta[k] = 2^(t-k)+1,t=3
/* cout<<"Input ten integers :"<<endl;
for(int i=0;i<10;i++)
{
cin>>a[i];
}
cout<<endl;*/
ShellSort(a,10,dlta,4);
cout<<"After sort:"<<endl;
for(int j=0;j<10;j++)
{
cout<<a[j]<<" ";
}
return 0;
}