数据结构笔记 含代码.docx
《数据结构笔记 含代码.docx》由会员分享,可在线阅读,更多相关《数据结构笔记 含代码.docx(40页珍藏版)》请在冰豆网上搜索。
数据结构笔记含代码
1.二分查找的算法:
intBinSearch(LineListR[],intn,KeyTypek)
{
inti,low=0,high=n-1,mid;
intfind=0;
while(low<=high&&!
find)
{
mid=(low+high)/2;
if(khigh=mid-1;
elseif(k>R[mid].key)
low=mid+1;
else
{
i=mid;
find=1;
}
}
if(find==0)
return(-1);
else
return(i);
}
2.分块查找的算法:
intBlkSearch(LineListR[],IDXTypeidx[],intm,KeyTypek)
{
intlow=0,high=m-1,mid,i,j,find=0;
while(low<=high&&!
find)
{
mid=(low+high)/2;
if(khigh=mid-1;
elseif(k>idx[mid].key)
low=mid+1;
else
{
high=mid-1;
find=1;
}
}
if(low{
i=idx[low].low;
j=idx[low].high;
}
while(i=k)
i++;
if(i>=j)
return(-1);
else
return(i);
}
3.二叉排序树的类型定义
typedefstructtnode
{
KeyTypekey;
ElemTypedata;
structtnode*lchild,*rchild;
}BSTNode;
4.二叉排序树的基本运算如下
1.查找结点
BSTNode*BSTSearch(BSTNode*bt,KeyTypek)
{
BSTNode*p=bt;
while(p!
=NULL&&p->key!
=k)
{
if(kkey)
p=p->lchild;
else
p=p->rchild;
}
return(p);
}
2.插入结点BSTInsert(bt,k)
intBSTInsert(BSTNode*&bt,KeyNodek)
{
BSTNode*f,*p=bt;
while(p!
=NULL)
{
if(p->key==k)
return(0);
f=p;
if(p->key>k)
p=p->lchild;
else
p=p->rchild;
}
p=(BSTNode*)malloc(sizeof(BSTNode));
p->key=k;
p->lchild=p->rchild=NULL;
if(bt==NULL)
bt=p;
elseif(kkey)
f->lchild=p;
return
(1);
}
3.创建二叉排序树CreateBST(bt,str,n)
voidCreateBST(BSTNode*&bt,KeyTypestr[],intn)
{
bt=NULL;
inti=0;
while(i{
BSTInsert(bt,str[i]);
i++;
}
}
4.输出二叉排序树
voidDispBST(BSTNode*bt)
{
if(bt!
=NULL)
{
cout<key;
if(bt->lchild!
=NULL||bt->rchild!
=NULL)
{
cout<<"(";
DispBST(bt->lchild);
if(bt->rchild!
=NULL)cout<<",";
DispBST(bt->rchild);
cout<<")";
}
}
}
1.插入排序:
voidInsertSort(SqListR[],intn)
{
inti,j;
SqListtmp;
for(i=1;i{
tmp=R[i];
j=i-1;
while(j>=0&&tmp.key{
R[j+1]=R[j];
j--;
}
R[j+1]=tmp;
}
}
2.希尔排序
voidShellSort(SqListR[],intn)
{
inti,j,gap;
SqListtmp;
gap=n/2;
while(gap>0)
{
for(i=gap;i{
tmp=R[i];
j=i-gap;
while(j>=0&&tmp.key{
R[j+gap]=R[j];
j=j-gap;
}
R[j+gap]=tmp;
j=j-gap;
}
gap=gap/2;
}
}
3.选择排序
voidSelectSort(SqListR[],intn)
{
inti,j,k;
SqListtmp;
for(i=0;i{
k=i;
for(j=i+1;jif(R[j].keyk=j;
tmp=R[i];
R[i]=R[k];
R[k]=tmp;
}
}
4.堆排序
voidHeapSort(SqListR[],intn)
{
inti;
SqListtmp;
for(i=n/2;i>=1;i--)
Sift(R,i,n);
for(i=n;i>=2;i--)
{
tmp=R[i];
R[1]=R[i];
R[i]=tmp;
Sift(R,1,i-1);
}
}
voidSift(SqListR[],intlow,inthigh)
{
inti=low,j=2*i;
SqListtmp=R[i];
while(j<=high)
{
if(jj++;
if(tmp.key{
R[i]=R[j];
i=j;
j=2*i;
}
elsebreak;
}
R[i]=tmp;
}
5.冒泡排序
voidBubbleSort(SqListR[],intn)
{
inti,j,exchange;
SqListtmp;
for(i=0;i{
exchange=0;
for(j=n-1;j>i;j--)
if(R[j].key{
tmp=R[j];
R[j]=R[j-1];
R[j-1]=tmp;
exchange=1;
}
if(exchange==0)
return;
}
6.快速排序
voidQuickSort(SqListR[],ints,intt)
{
inti=s,j=t;
SqListtmp;
if(s{
tmp=R[s];
while(i!
=j)
{
while(j>i&&R[j].key>tmp.key)
j--;
if(i{
R[i]=R[j];
i++;
}
while(ii++;
if(i{
R[j]=R[i];
j--;
}
}
R[i]=tmp;
QuickSort(R,s,i-1);
QuickSort(R,i+1,t);
}
}
7.二路归并排序
voidMergeSort(SqListR[],intn)
{
intlength;
for(length=1;lengthMergePass(R,length,n);
}
voidMergePass(SqListR[],intlength,intn)
{
inti;
for(i=0;i+2*length-1Merge(R,i,i+length-1,i+2*length-1);
if(i+length-1Merge(R,i,i+length-1,n-1);
}
voidMerge(SqListR[],intlow,intmid,inthigh)
{
SqList*R1;
inti=low,j=mid+1,k=0;
R1=(SqList*)malloc((high-low+1)*sizeof(SqList));
while(i<=mid&&j<=high)
if(R[i].key<=R[j].key)
{
R1[k]=R[i];
i++;k++;
}
else
{
R1[k]=R[j];
j++;k++;
}
while(i<=mid)
{
R1[k]=R[i];
i++;k++;
}
while(j<=high)
{
R1[k]=R[j];
j++;k++;
}
for(k=0,i=low;i<=high;k++,i++)
R[1]=R1[k];
}
8.基数排序
#defineMAXE20
#defineMAXR10
#defineMAXD8
typedefstructnode
{
chardata[MAXD];
structnode*next;
}RecType;
voidRadixSort(RecType*&p,intr,intd)
{
RecType*head[MAXR],*tail[MAXR],*t;
inti,j,k;
for(i=d-1;i>=0;i--)
{
for(j=0;j>r;j++)
head[j]=tail[j]=NULL;
while(p!
=NULL)
{
k=p->data[i]-'0';
if(head[k]==NULL)
{
head[k]=p;
tail[k]=p;
}
else
{
tail[k]->next=p;
tail[k]=p;
}
p=p->next;
}
p=NULL;
for(j=0;jif(head[j]!
=NULL)
{
if(p==NULL)
{
p=head[j];
t=tail[j];
}
else
{
t->next=head[j];
t=tail[j];
}
}
t->next=NULL;
}
}1.树的定义:
树包含n个结点,当n=0时,称为空树。
树的定义如下:
T=(D,R)
其中,D为树中结点的有限集合,关系R满足一下条件:
1.有且仅有一个结点k0属于D,它对于关系R来说没有前趋结点,结点k0称作树的根结点。
2.除根结点k0外,D中的每个结点有且仅有一个前趋结点,但可以由多个后继结点。
3.D中可以有多个终端结点。
2.树的基本术语
1.结点的度:
树中每个结点具有的子树个数或者后继结点个数称为该结点的度。
2.树的度:
树中所有结点的度的最大值称之为树的度。
3.分支结点:
度大于0的结点称为分支结点或非终端结点。
4.叶子结点:
度为0的结点称为叶子结点或终端结点。
5.孩子结点:
一个结点的后继称之为该结点的孩子结点。
6.双亲结点:
一个结点称为其后继结点的双亲结点。
7.子孙结点:
一个结点的所有子树中的结点称之为该结点的子孙结点。
8.祖先结点:
从树根结点到达某个结点的路径上通过的所有结点称为该结点的祖先结点。
9.兄弟结点:
具有同一双亲的结点互相称之为兄弟结点。
10.结点层数:
树具有一种层次结构,根结点为第一层,其孩子结点为第二层,如此类推得到每个结点的层数。
11.树的深度:
树中结点的最大层数称为树的深度或高度。
12.有序树和无序树:
如果一棵树中各结点的各子树从左到右是有次序的,即若交换了某结点各子树的相对位置则构成了不同的树,那么称这棵树为有序树,反之则为无序树。
13.森林:
0个或多个不相交的树的集合称为森林。
3.二叉树的定义:
二叉树是指树的度为2的有序树。
4.二叉树的性质:
二叉树上叶子结点数等于度为2的结点数加1。
二叉树上第i层上至多有2的(i-1)次方个结点。
深度为h的二叉树至多有2的h次方-1个结点。
对完全二叉树中编号为i(1<=i<=n,n>=1,n为结点数)的结点有:
1.若2i<=n,则编号为i的结点为分支结点,否则为叶子结点。
2.若n为奇数,则每个分支结点都既有左孩子,又有右孩子;若n为偶数,则编号最大的分支结点只有左孩子,没有右孩子,其余分支结点左,右孩子都有。
3.若编号为i的结点有左孩子,则左孩子结点的编号为2i;若编号为i的结点有右孩子,则右孩子的结点编号为2i+1.
4.除树的根结点外,若一个结点的编号为i,则它的双亲结点的编号为i/2,也就是说,当i为偶数时,其双亲结点的编号为i/2,它是双亲结点的左孩子,当i为奇数时,其双亲结点的编号为(i-1)/2,它是双亲结点的右孩子。
5.二叉树顺序存储结构的类型定义如下:
typedefElemTypeSqBinTree[MaxSize];
6.二叉树的链式存储结构中,结点的类型定义如下:
typedefstructtnode
{
ElemTypedata;
structtnode*lchild,*rchild;
}BTNode;
7.二叉树的基本算法:
1.建立二叉链运算算法:
用ch扫描采用括号表示法表示二叉树的字符串str.
1.若ch='(',则将前面刚创建的结点作为双亲结点进栈,并置k=1,表示其后创建的结点将作为这个结点的左孩子结点;
2.若ch=')',表示栈中结点的左右孩子结点处理完毕,退栈;
3.若ch=',',表示其后创建的结点为右孩子结点;
4.其他情况,表示要创建一个结点,并根据k值建立它与栈中结点之间的联系,当k=1时,表示这个结点作为栈中结点的左孩子结点;当k=2时,表示这个结点作为栈中结点的右孩子结点。
如此循环直到str处理完毕。
算法中使用一个栈St保存双亲结点,top为其栈指针,k指定其后处理的结点是双亲结点的左孩子结点还是右孩子结点。
voidCreateBtree(BTNode*&bt,char*str)
{
BTNode*St[MaxSize],*p=NULL;
inttop=-1,k,j=0;
charch;
bt=NULL;
ch=str[j];
while(ch!
='\0')
{
switch(ch)
{
case'(':
top++;St[top]=p;k=1;break;
case')':
top--;break;
case',':
k=2;break;
default:
p=(BTNode*)malloc(sizeof(BTNode));
p->data=ch;p->lchild=p->rchild=NULL;
if(bt==NULL)
bt=p;
else
{
switch(k)
{
case1:
St[top]->lchild=p;break;
case2:
St[top]->rchild=p;break;
}
}
}
j++;
ch=str[j];
}
}
2.求二叉树的高度运算算法:
intBTHeight(BTNode*bt)
{
intlchilddep,rchilddep;
if(bt==NULL)return(0);
else
{
lchilddep=BTHeight(bt->lchild);
rchilddep=BTHeight(bt->rchild);
return(lchilddep>rchilddep)?
(lchilddep+1):
(rchilddep+1);
}
}
3.求二叉树结点个数运算算法
intNodeCount(BTNode*bt)
{
intnum1,num2;
if(bt==NULL)
return0;
else
{
num1=NodeCount(bt->lchild);
num2=NodeCount(bt->rchild);
return(num1+num2+1);
}
}
4.求二叉树叶子结点个数运算算法
intLeafCount(BTNode*bt)
{
intnum1,num2;
if(bt==NULL)
return0;
elseif(bt>lchild==NULL&&bt->rchild==NULL)
return1;
else
{
num1=LeafCount(bt->lchild);
num2=LeafCount(bt->rchild);
return(num1+num2);
}
}
5.以括号表示法输出二叉树运算算法
过程:
对于非空二叉树bt,先输出其元素值,当存在左孩子结点或右孩子结点时,输出一个“(”符号,然后递归处理左子树,输出一个“,”符号,递归处理右子树,最后输出一个“)”符号。
voidDispBTree(BTNode*bt)
{
if(bt!
=NULL)
{
cout<data;
if(bt->lchild!
=NULL||btrchild!
=NULL)
{
cout<<"(";
DispBTree(bt->lchild);
if(bt-=NULL)cout<<",";
DispTree(bt->rchild);
cout<<")";
}
}
}
6.以凹入表示法输出二叉树运算算法
采用先序遍历非递归的方法,用一个栈St保存树中结点指针,用Level数组保存栈中对应结点的输出长宽和该结点的类型。
先将根结点指针进栈,在栈不空时循环:
退栈一个结点,以对应的长宽输处之,退栈,并将当前结点的右孩子结点指针和左孩子结点指针进栈。
采用奥如法表示输出时,每个结点之前的括号中的标记表示是什么类型的结点,B表示是根结点,L表示是左结点。
voidDispTree1(BTNode*bt)
{
BTNode*St[MaxSize],*p;
intLevel[MaxSize][2],top=-1,n,i,width=4;
chartype;
if(bt!
=NULL)
{
top++;
St[top]=bt;//根结点入栈
Level[top][0]=width;
Level[top][1]=2;//2表示是根
while(top->-1)
{
p=St[top];//退栈并凹入显示该结点值
n=Level[top][0];
switch(Level[top][1])
{
case0:
type='L';break;//左节点之后输出(L)
case1:
type='R';break;//右结点之后输出(R)
case2:
type='B';break;//根结点之后输出(B)
}
for(i=1;i<=n;i++)//其中n为显示长宽,字符以右对其显示
cout<<"";
cout<data<<"("<for(i=n+1;i<=MaxWidth;i+=2)
cout<<"-";
cout<top--;
if(p->rchild!
=NULL)
{//将右子树根结点入栈
top++;
St[top]=p->rchild;
Level[top][0]=n+width;//长宽增width,即缩width格后再输出
Level[top][1]=1;
}
if(p->lchild!
=NULL)
{//将左子树根结点入栈
top++;
St[top]=p->lchild;
Level[top][0]=n+width;//显示长宽增width
Level[top][1]=0;//0表示是左子树
}
}
}
}
8.二叉树遍历:
1.先序遍历
1.访问根结点2.先序遍历左子树3.先序遍历右子树
voidPreOrder(BTNode*bt)
{
if(bt!
=NULL)
{
cout<data;
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
}
采用先序遍历得到的访问结点序列称为先序遍历序列,先序编列的特点是:
其第一个元素值为二叉树中跟结点的数据值
2.中序遍历
1.中序遍历左子树2.访问根结点3.中序遍历右子树
voidInOrder(BTNode*bt)
{
if(bt!
=NULL)
{
InOrder(bt->lchild);
cout<data;
InOrder(bt->rchild);
}
}
采用中序遍历得到的访问结点序列成为中序遍历序列,中序遍历序列的特点是:
若已知二叉树的根结点数值,以该数据值为界,将中序遍历序列分为两部分,前半部分为左子树的中序遍历序列,后半部分为右子树的中序遍历序列。
3.后序遍历
1.后序遍历左子树2.后序遍历右子树3.访问根结点
voidPostOrder(BTNode*bt)
{
if(bt!
=NULL)
{
PostOrder(bt->lchild);
PostOrder(bt->rchild);
cout<data;
}
}
特点是最后一个元素值为二叉树中根结点的数据值
9.假设以二叉链作为储存结构,设计一个算法求二叉树的宽度。
宽度是指二叉树中各层上具有结点个数最多的那一层上的结点总数
先采用先序遍历求出每层的宽度,放在a数组中,然后再求出最大宽度即二叉树的宽度
void