线性表、栈、队列和串、二叉树以及哈夫曼树的基本操作
目录
线性表的操作
顺序表基本运算的实现
假设ElemType
为char类型,使用自定义类型语句
typdef char ElemType;
数组大小一般定义为一个整型常量,例如,把MaxSize定义为50
#define MaxSize 50
定义结构体SqList
typedef struct
{ ElemType data[MaxSize]; //存放顺序表元素
int length; //存放顺序表的长度
} SqList; //顺序表的类型定义
1.建立顺序表
void CreatList(SqList *&L,ElemType a[],int n) //由a中的n个元素建立顺序表
{
int i=0,k=0;
L=(SqList *)malloc(sizeof(SqList));
while(i<n)
{
L->data[k]=a[i];
k++,i++;
}
L -> length=k;
}
2.初始化线性表InitList(&L)
void InitList(SqList *&L)
{
L=(SqList * )malloc(sizeof(SqList));
L -> length=0;
}
3.销毁线性表DestroyList(&L)
void DestroyList(SqList *&L)
{
free(L);
}
4.判断线性表是否为空表ListEmpty(L)
int ListEmpty(SqList *L)
{
return(L->length==0);
}
5.求线性表的长度ListLength(L)
int ListLength(SqList *L)
{
return(L->length);
}
6.输出线性表DispList(L)
void DispList(SqList *L)
{
for(int i= 0;i<L->length;i++)
{
printf("%c ",L->data[i]);
}
printf("\n");
}
7.求线性表中的某个数据元素值GetElem( L, i,&e)
bool GetElem(SqList * L,int i,ElemType &e)
{
if(i<1||i>L->length)
return false;
e=L->data[i-1];
return true;
}
8.按元素值查找LoceteElem( L,e)
int LoceteElem(Sqlist * L,ElemType e)
{
int i=0;
while(i<L->length&&L->data[i]!=e)
i++;
if(i>=L->length)
return 0;
else
return i+1;
}
9.插入数据元素ListInsert(&L, i,e)
bool ListInsert(SqList *&L,int i,ElemType e)
{
int j;
if(i<1||i>L->length+1||L->length==MaxSize)
return false;
i--;
for(j=L->length;j>i;j--)
L->data[j]=L->data[j-1];
L->data[i]=e;
L->length++;
return true;
}
9.删除数据元素ListDelete(&L, i,e)
bool ListDelete(SqList *&L,int i,ElemType e)
{
int j;
if(i<1||i>L->length)
return false;
i--;
e=L->data[i];
for(j=i;j<L->length-1;j++)
L->data[j]=L->data[j+1];
L->length--;
return true;
}
完整代码如下:
#include <stdio.h>
#include <malloc.h>
#define MaxSize 50
typedef char ElemType;
typedef struct
{ ElemType data[MaxSize]; //存放顺序表元素
int length; //存放顺序表的长度
} SqList; //顺序表的类型定义
//1.建立顺序表
void CreatList(SqList *&L,ElemType a[],int n) //由a中的n个元素建立顺序表
{
int i=0,k=0;
L=(SqList *)malloc(sizeof(SqList));
while(i<n)
{
L->data[k]=a[i];
k++,i++;
}
L -> length=k;
}
//2.初始化线性表
void InitList(SqList *&L)
{
L=(SqList * )malloc(sizeof(SqList));
L -> length=0;
}
//3.销毁线性表
void DestroyList(SqList *&L)
{
free(L);
}
//4.判断线性表是否为空表
int ListEmpty(SqList *L)
{
return(L->length==0);
}
//5.求线性表长度
int ListLength(SqList *L)
{
return(L->length);
}
//6.输出线性表
void DispList(SqList *L)
{
for(int i= 0;i<L->length;i++)
{
printf("%c ",L->data[i]);
}
printf("\n");
}
//7.求线性表中的某个数据元素值
bool GetElem(SqList * L,int i,ElemType &e)
{
if(i<1||i>L->length)
return false;
e=L->data[i-1];
return true;
}
//8.按元素值查找
int LocateElem(SqList *L,ElemType e)
{
int i=0;
while(i<L->length&&L->data[i]!=e)
i++;
if(i>=L->length)
return 0;
else
return i+1;
}
//9.插入数据元素
bool ListInsert(SqList *&L,int i,ElemType e)
{
int j;
if(i<1||i>L->length+1||L->length==MaxSize)
return false;
i--;
for(j=L->length;j>i;j--)
L->data[j]=L->data[j-1];
L->data[i]=e;
L->length++;
return true;
}
//10.删除数据元素
bool ListDelete(SqList *&L,int i,ElemType e)
{
int j;
if(i<1||i>L->length)
return false;
i--;
e=L->data[i];
for(j=i;j<L->length-1;j++)
L->data[j]=L->data[j+1];
L->length--;
return true;
}
int main()
{
SqList *L;
ElemType e;
//方法一:
InitList(L);
ListInsert(L,1,'a');
ListInsert(L,2,'b');
ListInsert(L,3,'c');
ListInsert(L,4,'d');
ListInsert(L,5,'f');
/*方法二:
ElemType b[]={'a','b','c','d','m'};
CreateList(L,b,5);*/
printf("刚建立的线性表元素如下:\n");
DispList(L);
printf("线性表的长度为:%d\n",ListLength(L));
GetElem(L,3,e);
printf("取到的第三个元素是:e=%c\n",e);
printf("LocateElem(L,'a')=%d\n",LocateElem(L,'a'));
ListInsert(L,4,'g');
DispList(L);
ListDelete(L,3,e);
DispList(L);
DestroyList(L);
return 0;
}
运行结果:
单链表基本运算的实现
(1)头插法建立单链表CreateListF(L,a,n)
void CreateListF(LinkNode *&L,ElemType a[],int n)//头插法建立单链表
{
LinkNode *s;int i;
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next=NULL;
for (i=0;i<n;i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode));//创建新结点
s->data=a[i];
s->next=L->next; //将*s插在原开始结点之前,头结点之后
L->next=s;
}
}
(2)尾插法建立单链表CreateListR(L,a,n)
void CreateListR(LinkNode *&L,ElemType a[],int n)
{
LinkNode *s,*r;int i;
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next=NULL;
r=L; //r始终指向终端结点,开始时指向头结点
for (i=0;i<n;i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode));//创建新结点
s->data=a[i];
r->next=s; //将*s插入*r之后
r=s;
}
r->next=NULL; //终端结点next域置为NULL
}
(3)初始化单链表InitList(&L)
void InitList(LinkNode *&L)
{
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next=NULL;
}
(4)销毁单链表DestroyList(&L)
void DestroyList(LinkNode *&L)
{
LinkNode *p=L,*q=p->next;
while (q!=NULL)
{ free(p);
p=q;
q=p->next;
}
free(p); //此时q为NULL,p指向尾结点,释放它
}
(5)判断单链表是否为空ListEmpty(L)
bool ListEmpty(LinkNode *L)
{
return(L->next==NULL);
}
(6)求单链表长度ListLength(L)
int ListLength(LinkNode *L)
{
LinkNode *p=L;int i=0;
while (p->next!=NULL)
{ i++;
p=p->next;
}
return(i);
}
(7)输出单链表DispList(L)
void DispList(LinkNode *L)
{
LinkNode *p=L->next;
while (p!=NULL)
{ printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
(8)求单链表中的某个数据元素值GetElem(L,i,&e)
bool GetElem(LinkNode *L,int i,ElemType &e)
{
int j=0;
LinkNode *p=L;
while (j<i && p!=NULL)
{ j++;
p=p->next;
}
if (p==NULL) //不存在第i个数据结点
return false;
else //存在第i个数据结点
{ e=p->data;
return true;
}
}
(9)按元素值查找LocateElem(L, e)
int LocateElem(LinkNode *L,ElemType e)
{
LinkNode *p=L->next;
int n=1;
while (p!=NULL && p->data!=e)
{ p=p->next;
n++;
}
if (p==NULL)
return(0);
else
return(n);
}
(10)插入数据元素ListInsert(&L,i,e)
bool ListInsert(LinkNode *&L,int i,ElemType e)
{
int j=0;
LinkNode *p=L,*s;
while (j<i-1 && p!=NULL) //查找第i-1个结点
{ j++;
p=p->next;
}
if (p==NULL) //未找到位序为i-1的结点
return false;
else //找到位序为i-1的结点*p
{ s=(LinkNode *)malloc(sizeof(LinkNode));//创建新结点*s
s->data=e;
s->next=p->next; //将*s插入到*p之后
p->next=s;
return true;
}
}
(11)删除数据元素ListDelete(&L,i,&e)
bool ListDelete(LinkNode *&L,int i,ElemType &e)
{
int j=0;
LinkNode *p=L,*q;
while (j<i-1 && p!=NULL) //查找第i-1个结点
{ j++;
p=p->next;
}
if (p==NULL) //未找到位序为i-1的结点
return false;
else //找到位序为i-1的结点*p
{ q=p->next; //q指向要删除的结点
if (q==NULL)
return false; //若不存在第i个结点,返回false
e=q->data;
p->next=q->next; //从单链表中删除*q结点
free(q); //释放*q结点
return true;
}
}
(12)删除最大节点(&L,e)
void delmaxnode(LinkNode *&L,ElemType &e)
{
LinkNode *p=L->next,*pre=L,*maxp=p,*maxpre=pre;
while(p!=NULL)
{
if(maxp->data<p->data)
{
maxp=p;
maxpre=pre;
}
pre=p;
p=p->next;
}
e=maxp->data;
maxpre->next=maxp->next;
free(maxp);
}
(13)递增排序ListSort(L)
void ListSort(LinkNode *&L)
{
LinkNode * p, * pre, *q;
p=L->next -> next;
L -> next -> next= NULL;
while (p!=NULL)
{
q=p-> next;
pre=L;
while (pre -> next!= NULL &&pre-> next->data< p -> data)
pre=pre->next;
p->next=pre->next;
pre->next=p;
p=q;
}
}
完整代码
#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LinkNode //定义单链表结点类型
{
ElemType data;
struct LinkNode *next; //指向后继结点
} LinkNode;
//头插法建立单链表
void CreateListF(LinkNode *&L,ElemType a[],int n)
{
LinkNode *s;int i;
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next=NULL;
for (i=0;i<n;i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode));//创建新结点
s->data=a[i];
s->next=L->next; //将*s插在原开始结点之前,头结点之后
L->next=s;
}
}
//尾插法建立单链表
void CreateListR(LinkNode *&L,ElemType a[],int n)
{
LinkNode *s,*r;int i;
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next=NULL;
r=L; //r始终指向终端结点,开始时指向头结点
for (i=0;i<n;i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode));//创建新结点
s->data=a[i];
r->next=s; //将*s插入*r之后
r=s;
}
r->next=NULL; //终端结点next域置为NULL
}
//初始化单链表
void InitList(LinkNode *&L)
{
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next=NULL;
}
//销毁单链表
void DestroyList(LinkNode *&L)
{
LinkNode *p=L,*q=p->next;
while (q!=NULL)
{ free(p);
p=q;
q=p->next;
}
free(p); //此时q为NULL,p指向尾结点,释放它
}
//判断单链表是否为空
bool ListEmpty(LinkNode *L)
{
return(L->next==NULL);
}
//求单链表长度
int ListLength(LinkNode *L)
{
LinkNode *p=L;int i=0;
while (p->next!=NULL)
{ i++;
p=p->next;
}
return(i);
}
//输出单链表
void DispList(LinkNode *L)
{
LinkNode *p=L->next;
while (p!=NULL)
{ printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
//求单链表中的某个数据元素值
bool GetElem(LinkNode *L,int i,ElemType &e)
{
int j=0;
LinkNode *p=L;
while (j<i && p!=NULL)
{ j++;
p=p->next;
}
if (p==NULL) //不存在第i个数据结点
return false;
else //存在第i个数据结点
{ e=p->data;
return true;
}
}
//按元素值查找
int LocateElem(LinkNode *L,ElemType e)
{
LinkNode *p=L->next;
int n=1;
while (p!=NULL && p->data!=e)
{ p=p->next;
n++;
}
if (p==NULL)
return(0);
else
return(n);
}
//插入数据元素
bool ListInsert(LinkNode *&L,int i,ElemType e)
{
int j=0;
LinkNode *p=L,*s;
while (j<i-1 && p!=NULL) //查找第i-1个结点
{ j++;
p=p->next;
}
if (p==NULL) //未找到位序为i-1的结点
return false;
else //找到位序为i-1的结点*p
{ s=(LinkNode *)malloc(sizeof(LinkNode));//创建新结点*s
s->data=e;
s->next=p->next; //将*s插入到*p之后
p->next=s;
return true;
}
}
//删除数据元素
bool ListDelete(LinkNode *&L,int i,ElemType &e)
{
int j=0;
LinkNode *p=L,*q;
while (j<i-1 && p!=NULL) //查找第i-1个结点
{ j++;
p=p->next;
}
if (p==NULL) //未找到位序为i-1的结点
return false;
else //找到位序为i-1的结点*p
{ q=p->next; //q指向要删除的结点
if (q==NULL)
return false; //若不存在第i个结点,返回false
e=q->data;
p->next=q->next; //从单链表中删除*q结点
free(q); //释放*q结点
return true;
}
}
//删除单链表中元素最大值节点
void delmaxnode(LinkNode *&L,ElemType &e)
{
LinkNode *p=L->next,*pre=L,*maxp=p,*maxpre=pre;
while(p!=NULL)
{
if(maxp->data<p->data)
{
maxp=p;
maxpre=pre;
}
pre=p;
p=p->next;
}
e=maxp->data;
maxpre->next=maxp->next;
free(maxp);
}
//将带头结点的单链表L,使其元素递增有序排列
void ListSort(LinkNode *&L)
{
LinkNode * p, * pre, *q;
p=L->next -> next;
L -> next -> next= NULL;
while (p!=NULL)
{
q=p-> next;
pre=L;
while (pre -> next!= NULL &&pre-> next->data< p -> data)
pre=pre->next;
p->next=pre->next;
pre->next=p;
p=q;
}
}
int main()
{
LinkNode *L;
ElemType e;
int n=10;
ElemType a[]={1,3,2,9,0,4,7,6,5,8};
CreateListR(L,a,n);
printf("(1)输出单链表L: ");
DispList(L);
printf("(2)单链表L长度L= %d\n",ListLength(L));
printf("(3)单链表L为 %s\n",ListEmpty(L)?"空":"非空");
GetElem(L,3,e);
printf("(4)单链表L的第3个元素是 %d\n",e);
printf("(5)元素0的位置为 %d\n",LocateElem(L,0));
printf("(6)在第4个元素位置上插入第11个元素\n");
ListInsert(L,4,11);
printf("(7)输出单链表L: ");
DispList(L);
printf("(8)删除L的第3个元素\n",ListDelete(L,3,e));
printf("(9)输出单链表L: ");
DispList(L);
delmaxnode(L,e);
printf("(10)删除单链表元素最大值节点为 %d\n",e);
printf("(11)删除最大节点后的单链表L: ");
DispList(L);
printf("(12)L排序: ");
ListSort(L);
DispList(L);
DestroyList(L);
return 0;
}
效果:
栈的基本操作
顺序栈的基本运算的实现
#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct linknode
{
ElemType data; //数据域
struct linknode *next; //指针域
} LiStack;
//1.初始化栈s
void InitStack(LiStack *&s)
{ s=(LiStack *)malloc(sizeof(LiStack));
s->next=NULL;
}
//2.销毁栈
void DestroyStack(LiStack *&s)
{ LiStack *p=s,*q=s->next;
while (q!=NULL)
{ free(p);
p=q;
q=p->next;
}
free(p); //此时p指向尾节点,释放其空间
}
//3.判断栈是否为空
bool StackEmpty(LiStack *s)
{
return(s->next==NULL);
}
//4.进栈
void Push(LiStack *&s,ElemType e)
{ LiStack *p;
p=(LiStack *)malloc(sizeof(LiStack));
p->data=e; //新建元素e对应的节点*p
p->next=s->next; //插入*p节点作为开始节点
s->next=p;
}
//5.出栈
bool Pop(LiStack *&s,ElemType &e)
{ LiStack *p;
if (s->next==NULL) //栈空的情况
return false;
p=s->next; //p指向开始节点
e=p->data;
s->next=p->next; //删除*p节点
free(p); //释放*p节点
return true;
}
//6.取栈顶元素
bool GetTop(LiStack *s,ElemType &e)
{ if (s->next==NULL) //栈空的情况
return false;
e=s->next->data;
return true;
}
int main()
{
ElemType e;
LiStack *s;
printf("链式栈S的基本运算如下:\n");
printf(" (1)初始化栈s\n");
InitStack(s);
printf(" (2)栈为%s\n",(StackEmpty(s)?"空":"非空"));
printf(" (3)依次进栈元素a,b,c,d,e,f\n");
char arr[6]={'a','b','c','d','e','f'};
for (int i = 0;i < 6;i++)
Push(*&s,arr[i]) ;
printf(" (4)栈为%s\n",(StackEmpty(s)?"空":"非空"));
printf(" (5)出栈序列:");
while (!StackEmpty(s))
{
Pop(s,e);
printf("%c ",e);
}
printf("\n");
printf(" (6)栈为%s\n",(StackEmpty(s)?"空":"非空"));
printf(" (7)释放栈\n");
DestroyStack(s);
return 0;
}
链栈的基本运算的实现
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct
{
ElemType data[MaxSize];
int top; //栈指针
} SqStack; //顺序栈类型定义
//1.初始化栈initStack(&s)
void InitStack(SqStack *&s)
{
s=(SqStack *)malloc(sizeof(SqStack));
s->top=-1;
}
//2.销毁栈ClearStack(&s)
void DestroyStack(SqStack *&s)
{
free(s);
}
//3.判断栈是否为空StackEmpty(s)
bool StackEmpty(SqStack *s)
{
return(s->top==-1);
}
//4.进栈Push(&s,e)
bool Push(SqStack *&s,ElemType e)
{
if (s->top==MaxSize-1) //栈满的情况,即栈上溢出
return false;
s->top++;
s->data[s->top]=e;
return true;
}
//5.出栈Pop(&s,&e)
bool Pop(SqStack *&s,ElemType &e)
{
if (s->top==-1) //栈为空的情况,即栈下溢出
return false;
e=s->data[s->top];
s->top--;
return true;
}
//6.取栈顶元素GetTop(s)
bool GetTop(SqStack *s,ElemType &e)
{
if (s->top==-1) //栈为空的情况,即栈下溢出
return false;
e=s->data[s->top];
return true;
}
int main()
{
SqStack *S;
ElemType e;
printf("顺序栈S的基本运算如下:\n");
printf(" (1)初始化栈\n");
InitStack(S);
printf(" (2)栈为%s\n",StackEmpty(S)?"空":"非空");
printf(" (3)依次进栈元素a,b,c,d,e,f\n");
char arr[6]={'a','b','c','d','e','f'};
for (int i = 0;i < 6;i++)
Push(*&S,arr[i]) ;
printf(" (4)栈为%s\n",StackEmpty(S)?"空":"非空");
printf(" (5)出栈序列:");
while (!StackEmpty(S))
{
Pop(S,e);
printf("%c ",e);
}
printf("\n");
printf(" (6)栈为%s\n",(StackEmpty(S)?"空":"非空"));
printf(" (7)释放栈\n");
DestroyStack(S);
return 0;
}
队列的基本操作
顺序队列的基本运算的实现
环形队列的基本运算的实现
#include <stdio.h>
#include <malloc.h>
#define MaxSize 6
typedef int ElemType;
typedef struct
{
ElemType data[MaxSize];
int front,rear; //队首和队尾指针
} SqQueue;
//1.初始化队
void InitQueue(SqQueue *&q)
{ q=(SqQueue *)malloc (sizeof(SqQueue));
q->front=q->rear=0;
}
//2.销毁队
void DestroyQueue(SqQueue *&q)
{
free(q);
}
//3.判断队为空
bool QueueEmpty(SqQueue *q)
{
return(q->front==q->rear);
}
//4.入队
bool enQueue(SqQueue *&q,ElemType e)
{ if ((q->rear+1)%MaxSize==q->front) //队满上溢出
return false;
q->rear=(q->rear+1)%MaxSize;
q->data[q->rear]=e;
return true;
}
//5.出队
bool deQueue(SqQueue *&q,ElemType &e)
{ if (q->front==q->rear) //队空下溢出
return false;
q->front=(q->front+1)%MaxSize;
e=q->data[q->front];
return true;
}
int main()
{
SqQueue *q;
ElemType e;
InitQueue(q);
printf("刚初始化队列:%s\n",QueueEmpty(q)?"为空":"非空");
enQueue(q,1);
enQueue(q,2);
enQueue(q,3);
enQueue(q,4);
enQueue(q,5);
printf("进队列后:%s\n",(QueueEmpty(q)?"为空":"非空"));
printf("出队顺序:");
while (!QueueEmpty(q))
{
deQueue(q,e);
printf("%d ",e);
}
printf("\n");
printf("出队列后:%s\n",(QueueEmpty(q)?"为空":"非空"));
DestroyQueue(q);
return 0;
}
串的基本操作
顺序串基本运算的实现
#include <stdio.h>
#define MaxSize 100 //最多的字符个数
typedef struct
{ char data[MaxSize]; //定义可容纳MaxSize个字符的空间
int length; //标记当前实际串长
} SqString;
//1.初始化串并赋值
void StrAssign(SqString &s,char cstr[]) //s为引用型参数
{ int i;
for (i=0;cstr[i]!='\0';i++)
s.data[i]=cstr[i];
s.length=i;
}
//2.串的复制
void StrCopy(SqString &s,SqString t) //s为引用型参数
{ int i;
for (i=0;i<t.length;i++)
s.data[i]=t.data[i];
s.length=t.length;
}
//3.判断长度是否相等
bool StrEqual(SqString s,SqString t)
{ bool same=true;
int i;
if (s.length!=t.length) //长度不相等时返回0
same=false;
else
for (i=0;i<s.length;i++)
if (s.data[i]!=t.data[i]) //有一个对应字符不相同时返回0
{ same=false;
break;
}
return same;
}
//4.求串长
int StrLength(SqString s)
{
return s.length;
}
//5.串的连接
SqString Concat(SqString s,SqString t)
{ SqString str;
int i;
str.length=s.length+t.length;
for (i=0;i<s.length;i++) //将s.data[0..s.length-1]复制到str
str.data[i]=s.data[i];
for (i=0;i<t.length;i++) //将t.data[0..t.length-1]复制到str
str.data[s.length+i]=t.data[i];
return str;
}
//6.求子串
SqString SubStr(SqString s,int i,int j)
{ SqString str;
int k;
str.length=0;
if (i<=0 || i>s.length || j<0 || i+j-1>s.length)
return str; //参数不正确时返回空串
for (k=i-1;k<i+j-1;k++) //将s.data[i..i+j]复制到str
str.data[k-i+1]=s.data[k];
str.length=j;
return str;
}
//7.串的插入
SqString InsStr(SqString s1,int i,SqString s2)
{ int j;
SqString str;
str.length=0;
if (i<=0 || i>s1.length+1) //参数不正确时返回空串
return str;
for (j=0;j<i-1;j++) //将s1.data[0..i-2]复制到str
str.data[j]=s1.data[j];
for (j=0;j<s2.length;j++) //将s2.data[0..s2.length-1]复制到str
str.data[i+j-1]=s2.data[j];
for (j=i-1;j<s1.length;j++) //将s1.data[i-1..s1.length-1]复制到str
str.data[s2.length+j]=s1.data[j];
str.length=s1.length+s2.length;
return str;
}
//8.串的删除
SqString DelStr(SqString s,int i,int j)
{ int k;
SqString str;
str.length=0;
if (i<=0 || i>s.length || i+j>s.length+1) //参数不正确时返回空串
return str;
for (k=0;k<i-1;k++) //将s.data[0..i-2]复制到str
str.data[k]=s.data[k];
for (k=i+j-1;k<s.length;k++) //将s.data[i+j-1..s.length-1]复制到str
str.data[k-j]=s.data[k];
str.length=s.length-j;
return str;
}
//9.串的替换
SqString RepStr(SqString s,int i,int j,SqString t)
{ int k;
SqString str;
str.length=0;
if (i<=0 || i>s.length || i+j-1>s.length) //参数不正确时返回空串
return str;
for (k=0;k<i-1;k++) //将s.data[0..i-2]复制到str
str.data[k]=s.data[k];
for (k=0;k<t.length;k++) //将t.data[0..t.length-1]复制到str
str.data[i+k-1]=t.data[k];
for (k=i+j-1;k<s.length;k++) //将s.data[i+j-1..s.length-1]复制到str
str.data[t.length+k-j]=s.data[k];
str.length=s.length-j+t.length;
return str;
}
//10.串的输出
void DispStr(SqString s)
{ int i;
if (s.length>0)
{ for (i=0;i<s.length;i++)
printf("%c",s.data[i]);
printf("\n");
}
}
int main()
{
SqString s,s1,s2,s3,s4,s5;
printf("顺序串的基本运算如下:\n");
printf(" (1)建立串s和串s1成功!!!\n");
StrAssign(s,"abcdefghijklmn");
StrAssign(s1,"123");
StrAssign(s5,"cd");
printf(" (2)输出串s:");DispStr(s);
printf(" (3)串s的长度:%d\n",StrLength(s));
printf(" (4)在串s的第9个字符位置插入串s1而产生串s2\n");
s2=InsStr(s,9,s1);
printf(" (5)输出串s2:");DispStr(s2);
printf(" (6)删除串s第2个字符开始的3个字符而产生串s2\n");
s2=DelStr(s,2,3);
printf(" (7)输出串s2:");DispStr(s2);
printf(" (8)将串s第2个字符开始的5个字符替换成串s1而产生串s2\n");
s2=RepStr(s,2,5,s1);
printf(" (9)输出串s2:");DispStr(s2);
printf(" (10)提取串s的第2个字符开始的10个字符而产生串s3\n");
s3=SubStr(s,2,10);
printf(" (11)输出串s3:");DispStr(s3);
printf(" (12)将串s1和串s2连接起来而产生串s4\n");
s4=Concat(s1,s2);
printf(" (13)输出串s4:");DispStr(s4);
return 0;
}
链式串基本运算的实现
#include <stdio.h>
#include <malloc.h>
typedef struct snode
{
char data;
struct snode *next;
} LiString;
//1.初始化串并赋值
void StrAssign(LiString *&s,char cstr[])
{ int i;
LiString *r,*p;
s=(LiString *)malloc(sizeof(LiString));
r=s; //r始终指向尾节点
for (i=0;cstr[i]!='\0';i++)
{ p=(LiString *)malloc(sizeof(LiString));
p->data=cstr[i];
r->next=p;r=p;
}
r->next=NULL;
}
2.串的复制
void StrCopy(LiString *&s,LiString *t)
{ LiString *p=t->next,*q,*r;
s=(LiString *)malloc(sizeof(LiString));
r=s; //r始终指向尾节点
while (p!=NULL) //将t的所有节点复制到s
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;
r->next=q;r=q;
p=p->next;
}
r->next=NULL;
}
//3.比较字符串
bool StrEqual(LiString *s,LiString *t)
{ LiString *p=s->next,*q=t->next;
while (p!=NULL && q!=NULL && p->data==q->data)
{ p=p->next;
q=q->next;
}
if (p==NULL && q==NULL)
return true;
else
return false;
}
//4.求串长
int StrLength(LiString *s)
{ int i=0;
LiString *p=s->next;
while (p!=NULL)
{ i++;
p=p->next;
}
return i;
}
//5.串的连接
LiString *Concat(LiString *s,LiString *t)
{ LiString *str,*p=s->next,*q,*r;
str=(LiString *)malloc(sizeof(LiString));
r=str;
while (p!=NULL) //将s的所有节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;
r->next=q;r=q;
p=p->next;
}
p=t->next;
while (p!=NULL) //将t的所有节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;
r->next=q;r=q;
p=p->next;
}
r->next=NULL;
return str;
}
//6.求子串
LiString *SubStr(LiString *s,int i,int j)
{ int k;
LiString *str,*p=s->next,*q,*r;
str=(LiString *)malloc(sizeof(LiString));
str->next=NULL;
r=str; //r指向新建链表的尾节点
if (i<=0 || i>StrLength(s) || j<0 || i+j-1>StrLength(s))
return str; //参数不正确时返回空串
for (k=0;k<i-1;k++)
p=p->next;
for (k=1;k<=j;k++) //将s的第i个节点开始的j个节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;
r->next=q;r=q;
p=p->next;
}
r->next=NULL;
return str;
}
//7.串的插入
LiString *InsStr(LiString *s,int i,LiString *t)
{ int k;
LiString *str,*p=s->next,*p1=t->next,*q,*r;
str=(LiString *)malloc(sizeof(LiString));
str->next=NULL;
r=str; //r指向新建链表的尾节点
if (i<=0 || i>StrLength(s)+1) //参数不正确时返回空串
return str;
for (k=1;k<i;k++) //将s的前i个节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;
r->next=q;r=q;
p=p->next;
}
while (p1!=NULL) //将t的所有节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p1->data;
r->next=q;r=q;
p1=p1->next;
}
while (p!=NULL) //将*p及其后的节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;
r->next=q;r=q;
p=p->next;
}
r->next=NULL;
return str;
}
//8.串的删除
LiString *DelStr(LiString *s,int i,int j)
{ int k;
LiString *str,*p=s->next,*q,*r;
str=(LiString *)malloc(sizeof(LiString));
str->next=NULL;
r=str; //r指向新建链表的尾节点
if (i<=0 || i>StrLength(s) || j<0 || i+j-1>StrLength(s))
return str; //参数不正确时返回空串
for (k=0;k<i-1;k++) //将s的前i-1个节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;
r->next=q;r=q;
p=p->next;
}
for (k=0;k<j;k++) //让p沿next跳j个节点
p=p->next;
while (p!=NULL) //将*p及其后的节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;
r->next=q;r=q;
p=p->next;
}
r->next=NULL;
return str;
}
//9.串的替换
LiString *RepStr(LiString *s,int i,int j,LiString *t)
{ int k;
LiString *str,*p=s->next,*p1=t->next,*q,*r;
str=(LiString *)malloc(sizeof(LiString));
str->next=NULL;
r=str; //r指向新建链表的尾节点
if (i<=0 || i>StrLength(s) || j<0 || i+j-1>StrLength(s))
return str; //参数不正确时返回空串
for (k=0;k<i-1;k++) //将s的前i-1个节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;q->next=NULL;
r->next=q;r=q;
p=p->next;
}
for (k=0;k<j;k++) //让p沿next跳j个节点
p=p->next;
while (p1!=NULL) //将t的所有节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p1->data;q->next=NULL;
r->next=q;r=q;
p1=p1->next;
}
while (p!=NULL) //将*p及其后的节点复制到str
{ q=(LiString *)malloc(sizeof(LiString));
q->data=p->data;q->next=NULL;
r->next=q;r=q;
p=p->next;
}
r->next=NULL;
return str;
}
//10.串的输出
void DispStr(LiString *s)
{ LiString *p=s->next;
while (p!=NULL)
{ printf("%c",p->data);
p=p->next;
}
printf("\n");
}
int main()
{
LiString *s,*s1,*s2,*s3,*s4;
printf("链串的基本运算如下:\n");
printf(" (1)建立串s和串s1\n");
StrAssign(s,"abcdefghijklmn");
StrAssign(s1,"123");
printf(" (2)输出串s:");DispStr(s);
printf(" (3)串s的长度:%d\n",StrLength(s));
printf(" (4)在串s的第9个字符位置插入串s1而产生串s2\n");
s2=InsStr(s,9,s1);
printf(" (5)输出串s2:");DispStr(s2);
printf(" (6)删除串s第2个字符开始的3个字符而产生串s2\n");
s2=DelStr(s,2,3);
printf(" (7)输出串s2:");DispStr(s2);
printf(" (8)将串s第2个字符开始的5个字符替换成串s1而产生串s2\n");
s2=RepStr(s,2,5,s1);
printf(" (9)输出串s2:");DispStr(s2);
printf(" (10)提取串s的第2个字符开始的10个字符而产生串s3\n");
s3=SubStr(s,2,10);
printf(" (11)输出串s3:");DispStr(s3);
printf(" (12)将串s1和串s2连接起来而产生串s4\n");
s4=Concat(s1,s2);
printf(" (13)输出串s4:");DispStr(s4);
return 0;
}
二叉树的基本操作
二叉树的基本运算的实现
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
//二叉链节点的类型定义
typedef struct node
{
ElemType data; //数据元素
struct node *lchild; //指向左孩子
struct node *rchild; //指向右孩子
} BTNode;
//由str串创建二叉链
void CreateBTNode(BTNode *&b,char *str)
{
BTNode *St[MaxSize],*p=NULL;
int top=-1,k,j=0;
char ch;
b=NULL; //建立的二叉树初始时为空
ch=str[j];
while (ch!='\0') //str未扫描完时循环
{
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 (b==NULL) //p指向二叉树的根节点
b=p;
else //已建立二叉树根节点
{
switch(k)
{
case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
}
}
}
j++;
ch=str[j];
}
}
//返回data域为x的节点指针
BTNode *FindNode(BTNode *b,ElemType x)
{
BTNode *p;
if (b==NULL)
return NULL;
else if (b->data==x)
return b;
else
{
p=FindNode(b->lchild,x);
if (p!=NULL)
return p;
else
return FindNode(b->rchild,x);
}
}
//返回*p节点的左孩子节点指针
BTNode *LchildNode(BTNode *p)
{
return p->lchild;
}
//返回*p节点的右孩子节点指针
BTNode *RchildNode(BTNode *p)
{
return p->rchild;
}
//求二叉树b的深度
int BTNodeDepth(BTNode *b)
{
int lchilddep,rchilddep;
if (b==NULL)
return(0); //空树的高度为0
else
{
lchilddep=BTNodeDepth(b->lchild); //求左子树的高度为lchilddep
rchilddep=BTNodeDepth(b->rchild); //求右子树的高度为rchilddep
return (lchilddep>rchilddep)? (lchilddep+1):(rchilddep+1);
}
}
//以括号表示法输出二叉树
void DispBTNode(BTNode *b)
{
if (b!=NULL)
{
printf("%c",b->data);
if (b->lchild!=NULL || b->rchild!=NULL)
{
printf("(");
DispBTNode(b->lchild);
if (b->rchild!=NULL) printf(",");
DispBTNode(b->rchild);
printf(")");
}
}
}
//求二叉树b的节点个数
int Nodes(BTNode *b)
{
int num1,num2;
if (b==NULL)
return 0;
else if (b->lchild==NULL && b->rchild==NULL)
return 1;
else
{
num1=Nodes(b->lchild);
num2=Nodes(b->rchild);
return (num1+num2+1);
}
}
//求二叉树b的叶子节点个数
int LeafNodes(BTNode *b)
{
int num1,num2;
if (b==NULL)
return 0;
else if (b->lchild==NULL && b->rchild==NULL)
return 1;
else
{
num1=LeafNodes(b->lchild);
num2=LeafNodes(b->rchild);
return (num1+num2);
}
}
//销毁二叉树
void DestroyBTNode(BTNode *&b)
{
if (b!=NULL)
{
DestroyBTNode(b->lchild);
DestroyBTNode(b->rchild);
free(b);
}
}
//主函数
int main()
{ BTNode *b,*p,*lp,*rp;;
CreateBTNode(b,"A(B(D(,G)),C(E,F))");
printf("二叉树的基本运算: \n");
printf(" (1) 输出二叉树b: ");
DispBTNode(b);
printf("\n");
printf(" (2) C节点: ");
p=FindNode(b,'C');
if (p!=NULL)
{ lp=LchildNode(p);
if (lp!=NULL)
printf("左孩子节点为%c ",lp->data);
else
printf("无左孩子节点 ");
rp=RchildNode(p);
if (rp!=NULL)
printf("右孩子节点为%c",rp->data);
else
printf("无右孩子节点 ");
}
printf("\n");
printf(" (3) 二叉树b的深度: %d\n",BTNodeDepth(b));
printf(" (4) 二叉树b的节点个数: %d\n",Nodes(b));
printf(" (5) 二叉树b的叶子节点个数: %d\n",LeafNodes(b));
printf(" (6) 释放二叉树b\n");
DestroyBTNode(b);
return 0;
}
二叉树的先序、中序和后序遍历
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node
{
ElemType data; //数据元素
struct node *lchild; //指向左孩子
struct node *rchild; //指向右孩子
} BTNode;
//由str串创建二叉链
void CreateBTNode(BTNode *&b,char *str)
{
BTNode *St[MaxSize],*p=NULL;
int top=-1,k,j=0;
char ch;
b=NULL; //建立的二叉树初始时为空
ch=str[j];
while (ch!='\0') //str未扫描完时循环
{
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 (b==NULL) //p指向二叉树的根节点
b=p;
else //已建立二叉树根节点
{
switch(k)
{
case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
}
}
}
j++;
ch=str[j];
}
}
//以括号表示法输出二叉树
void DispBTNode(BTNode *b)
{
if (b!=NULL)
{
printf("%c",b->data);
if (b->lchild!=NULL || b->rchild!=NULL)
{
printf("(");
DispBTNode(b->lchild);
if (b->rchild!=NULL) printf(",");
DispBTNode(b->rchild);
printf(")");
}
}
}
//销毁二叉树
void DestroyBTNode(BTNode *&b)
{
if (b!=NULL)
{
DestroyBTNode(b->lchild);
DestroyBTNode(b->rchild);
free(b);
}
}
//先序遍历的递归算法
void PreOrder(BTNode *b)
{
if (b!=NULL)
{
printf("%c ",b->data); //访问根节点
PreOrder(b->lchild); //递归访问左子树
PreOrder(b->rchild); //递归访问右子树
}
}
//中序遍历的递归算法
void InOrder(BTNode *b)
{
if (b!=NULL)
{
InOrder(b->lchild); //递归访问左子树
printf("%c ",b->data); //访问根节点
InOrder(b->rchild); //递归访问右子树
}
}
//后序遍历的递归算法
void PostOrder(BTNode *b)
{
if (b!=NULL)
{
PostOrder(b->lchild); //递归访问左子树
PostOrder(b->rchild); //递归访问右子树
printf("%c ",b->data); //访问根节点
}
}
int main()
{
BTNode *b;
CreateBTNode(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
printf("二叉树b:");
DispBTNode(b);
printf("\n\n");
printf("先序遍历: ");
PreOrder(b);
printf("\n");
printf("中序遍历: ");
InOrder(b);
printf("\n");
printf("后序遍历: ");
PostOrder(b);
printf("\n");
DestroyBTNode(b);
return 0;
}
哈夫曼树
哈夫曼编码
#include <stdio.h>
#include <string.h>
#define N 50 //叶子结点数
#define M 2*N-1 //树中结点总数
//哈夫曼树的节点结构类型
typedef struct
{
char data[5]; //结点值
int weight; //权重
int parent; //双亲结点
int lchild; //左孩子结点
int rchild; //右孩子结点
} HTNode;
每个节点哈夫曼编码的结构类型,存放哈夫曼码
typedef struct
{
char cd[N];
int start;
} HCode;
//构造哈夫曼树
void CreateHT(HTNode ht[],int n)
{
int i,k,lnode,rnode;
double min1,min2;
for (i=0;i<2*n-1;i++) //所有结点的相关域置初值-1
ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
for (i=n;i<2*n-1;i++) //构造哈夫曼树
{
min1=min2=32767; //lnode和rnode为最小权重的两个结点位置
lnode=rnode=-1;
for (k=0;k<=i-1;k++)
if (ht[k].parent==-1) //只在尚未构造二叉树的结点中查找
{
if (ht[k].weight<min1)
{
min2=min1;rnode=lnode;
min1=ht[k].weight;lnode=k;
}
else if (ht[k].weight<min2)
{
min2=ht[k].weight;rnode=k;
}
}
ht[i].weight=ht[lnode].weight+ht[rnode].weight;
ht[i].lchild=lnode;ht[i].rchild=rnode;
ht[lnode].parent=i;ht[rnode].parent=i;
}
}
//实现哈夫曼编码
void CreateHCode(HTNode ht[],HCode hcd[],int n)
{
int i,f,c;
HCode hc;
for (i=0;i<n;i++) //根据哈夫曼树求哈夫曼编码
{
hc.start=n;c=i;
f=ht[i].parent;
while (f!=-1) //循序直到树根结点
{
if (ht[f].lchild==c) //处理左孩子结点
hc.cd[hc.start--]='0';
else //处理右孩子结点
hc.cd[hc.start--]='1';
c=f;f=ht[f].parent;
}
hc.start++; //start指向哈夫曼编码最开始字符
hcd[i]=hc;
}
}
//输出哈夫曼编码
void DispHCode(HTNode ht[],HCode hcd[],int n)
{
int i,k;
int sum=0,m=0;
int j;
printf("输出哈夫曼编码:\n"); //输出哈夫曼编码
for (i=0;i<n;i++)
{
j=0;
printf(" %s: ",ht[i].data);
for (k=hcd[i].start;k<=n;k++)
{
printf("%c",hcd[i].cd[k]);
j++;
}
m+=ht[i].weight;
sum+=ht[i].weight*j;
printf("\n");
}
printf("\n带权路径长度: WPL=%d\n",sum);
}
int main()
{
int n=6,i; //n表示初始字符串的个数
char *str[]={"a","b","c","d","e","f"};
int fnum[]={2,3,4,7,8,9};
HTNode ht[M];
HCode hcd[N];
for (i=0;i<n;i++)
{
strcpy(ht[i].data,str[i]);
ht[i].weight=fnum[i];
}
CreateHT(ht,n);
CreateHCode(ht,hcd,n);
DispHCode(ht,hcd,n);
printf("\n");
return 0;
}
图的基本操作
//图的基本运算算法
#include <stdio.h>
#include <malloc.h>
//图的邻接矩阵存储结构
#define INF 32767 //定义∞
#define MAXV 100 //最大顶点个数
typedef char InfoType;
//以下定义邻接矩阵类型
typedef struct
{ int no; //顶点编号
InfoType info; //顶点其他信息
} VertexType; //顶点类型
typedef struct
{ int edges[MAXV][MAXV]; //邻接矩阵数组
int n,e; //顶点数,边数
VertexType vexs[MAXV]; //存放顶点信息
} MatGraph; //完整的图邻接矩阵类型
//------------------------------------------------------------
//----邻接矩阵的基本运算算法----------------------------------
//------------------------------------------------------------
void CreateMat(MatGraph &g,int A[MAXV][MAXV],int n,int e) //创建图的邻接矩阵
{
int i,j;
g.n=n; g.e=e;
for (i=0;i<g.n;i++)
for (j=0;j<g.n;j++)
g.edges[i][j]=A[i][j];
}
void DispMat(MatGraph g) //输出邻接矩阵g
{
int i,j;
for (i=0;i<g.n;i++)
{
for (j=0;j<g.n;j++)
if (g.edges[i][j]!=INF)
printf("%4d",g.edges[i][j]);
else
printf("%4s","∞");
printf("\n");
}
}
void InDs1(MatGraph g) //求出图G中每个顶点的度
{
int i,j,n;
printf("各顶点度:\n");
for(j=0;j<g.n;j++)
{
n=0;
for(i=0;i<g.n;i++)
if(g.edges[i][j]!=0)
n++; //n累计入度数
printf(" 顶点%d:%d\n",j,n);
}
}
int main()
{
MatGraph g;
int A[MAXV][MAXV]={{0,1,0,1,1},{1,0,1,1,0},
{0,1,0,1,1},{1,1,1,0,1},{1,0,1,1,0}};
int n=5, e=8;
CreateMat(g,A,n,e); //建立实验讲义中图的邻接矩阵
printf("图G的邻接矩阵:\n");
DispMat(g); //输出邻接矩阵g
InDs1(g);
return 1;
}