数据结构(用c语言描述)
以下代码全在eclipse上调试通过
/*
============================================================================
Name : zhizhenAndshujujiegou.c
Author : AiGuo Shang
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
1.【通过指针变量访问整型变量】
/*通过指针变量访问整型变量*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a=100,b=10;//定义整型变量a,b,并初始化。
/*
int * point1,*point2;
point1=&a;
point2=&b;
*/
int *point1=&a;
int *point2=&b;
printf("a=%d,b=%d\n",a,b);
printf("*point1=%d,*point2=%d\n",*point1,*point2);
printf("address*point1=%d,address*point2=%d\n",point1,point2);
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
return 0;
}
调试结果:
a=100,b=10
*point1=100,*point2=10
address*point1=6422076,address*point2=6422072
!!!Hello World!!!
2.【通过指针访问数组元素】
/*通过指针引用数组元素*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a[10];
int i,*p;//p为指向整形存储单元首地址的指针变量
printf("Please input the integer numbers:");
printf("\n");
fflush(stdout);//解决C语言中printf后的scanf不执行问题
/*在每个最后不带\n的printf后面加fflush(stdout);
* 在每个不想接受缓冲区旧内容影响的scanf前面加rewind(stdin);*/
for(i=0;i<10;i++){
/*rewind(stdin);*/
scanf("%d",&a[i]);}
for(i=0;i<10;i++)
printf("%3d",*(a+i));//(a+i)是a数组中序号为i的元素的地址,*(a+i)是该元素的值
printf("\n");
printf("Use the pointer p to show this array a[10]:\n");
for(p=a;p<(a+10);p++)
printf("%3d",*p);
printf("\nOver");
return 0;
}
运行结果:
Please input the integer numbers:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
Use the pointer p to show this array a[10]:
1 2 3 4 5 6 7 8 9 10
Over
3. 【输出二维数组的有关数据和值】
/*输出二维数组的有关数据和值*/
#include <stdio.h>
#include <stdlib.h>
/*在C语言中,一维数组与二维数组在指针的使用上有所不同
*1.在一维数组a[n]中,a表示数组的首地址,a[i]表示特定的元素
*2.在二维数组a[m][n]中,a表示数组的首地址(数组中数组的首地址或整个储存空间的首地址),a[i]表示第i行的首地址
*3.C语言中 a[i]与*(a+i) 等价*/
int main(void) {
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
printf("%d,%d\n",a,*a);//0行首地址和0行0列元素地址
printf("%d,%d\n",a[0],*(a+0));//0行0列元素地址
printf("%d,%d\n",&a[0],&a[0][0]);//0行首地址和0行0列首地址
printf("%d,%d\n",a[1],a+1);//1行0列元素地址和1行首地址
printf("%d,%d\n",&a[1][0],*(a+1)+0);//1行0列元素地址
printf("%d,%d\n",a[2],*(a+2));//2行0列元素地址
printf("%d,%d\n",&a[2],a+2);//2行首地址
printf("%d,%d\n",a[1][0],**(a+1));//1行0列元素的值,同*(*(a+1)+0)
printf("%d,%d\n",*a[2],**(a+2));//2行0列元素的值
printf("%d,%d,%d\n",a,*a,**a);//test
return 0;
}
调试结果:
6422048,6422048
6422048,6422048
6422048,6422048
6422064,6422064
6422064,6422064
6422080,6422080
6422080,6422080
9,9
17,17
6422048,6422048,1
4. 【用指向数组的指针做函数参数】
/*用指向数组的指针做函数参数*/
#include <stdio.h>
/*int(*p)[m]表示p被定义为指向一维整形 数组的指针变量,这个一维数组有m个类型为int(*p)[m]的元素 */
#include <stdlib.h>
int main(void){
void average(float * p,int n);//函数声明
void search(float (*p)[],int n);//函数声明
float score[3][4]={{65,67,70,60},{80,87,90,81},{90,99,100,98}};
average(*score,12);//指针类型为float * score,传进来的形参为去掉类型名的*score
search(score,2);//函数search的形参p的类型是float(*)[4],传进来的形参为去掉类型名的p
return 0;
}
void average(float *p,int n){
float * p_end;
float sum=0,aver;
p_end=p+n-1;
for(;p<=p_end;p++)
sum+=*p;
aver=sum/n;
printf("average = %5.2f\n",aver);
}
void search(float(*p)[4],int n)
{//p是指向具有四个元素的一维数组的指针
int i;
printf("The score of NO.%d are:\n",n);
for(i=0;i<4;i++)
printf("%5.2f",*(*(p+n)+i));
printf("\n");
}
运行结果:
average = 82.25
The score of NO.2 are:
90.0099.00100.0098.00
【5】指向函数的指针
/*指向函数的指针 */
#include <stdio.h>
/*指向函数的指针变量的一个重要用途是把函数的地址作为参数传递到其他函数*/
#include <stdlib.h>
int main(void){
int max();
int min();
int (*p)(int,int);//指向函数的指针p类型为int(*)(int,int),返回值为类型名int
int a,b,c,n;
printf("please enter a and b:");
fflush(stdout);
scanf("%d %d",&a,&b);
printf("choose 1 or 2:");
fflush(stdout);
scanf("%d",&n);
if(n==1)p=max;//使用指向函数的指针变量需要把函数入口地址赋值给p
else if(n==2)p=min;
c=(*p)(a,b);//程序在执行的过程中,指针p指向max或者min函数,然后调用相应的函数。
printf("a=%d,b=%d\n",a,b);
if(n==1)printf("max=%d\n",c);
else printf("min=%d\n",c);
return 0;
}
int max(int x, int y){
int z;
if(x>y)z=x;
else z=y;
return z;
}
int min(int x, int y){
int z;
if(x<y)z=x;
else z=y;
return z;
}
调试结果:
please enter a and b:34 89
choose 1 or 2:1
a=34,b=89
max=89
【6】指向函数的指针做函数的参数
/*指向函数的指针做函数的参数 */
#include <stdio.h>
/*指向函数的指针变量的一个重要用途是把函数的地址作为参数传递到其他函数*/
#include <stdlib.h>
int main(void){
int max();
int min();
void fun(int x,int y,int(*p)(int,int));//也可以用int类型的函数类型
int add();
int a=34,b=-21,n;
printf("please choose 1,2 or 3,4:");
fflush(stdout);
scanf("%d",&n);
if(n==1)fun(a,b,max);
else if(n==2)fun(a,b,min);
else if(n==3)fun(a,b,add);
return 0;
}
void fun(int x,int y,int (*p)(int,int))
/*void也可以写成int,因为在调用max,min,add都有返回值fun函数正常执行*/
{
int result;
/*指针变量所对应的(*p)是函数实名,即(*p)(int,int)就是max(int x,int y),...
* 1.(*p)(x,y)相当于max/min/add(x,y)
* 2.在fun函数没有被调时,该函数的指针变量p并不占用内存空间,也不指向任何函数
* 3.函数fun被调用时,函数max/min/add的入口地址传送到fun函数,即指针p指向函数max/min/add
* 4.用指向函数的指针做函数参数的方法对于要调用"不固定函数"的函数是非常方便的*/
result=(*p)(x,y);
printf("%d\n",result);
}
int max(int x, int y){
int z;
if(x>y)z=x;
else z=y;
printf("max=");
return z;
}
int min(int x, int y){
int z;
if(x<y)z=x;
else z=y;
printf("min=");
return z;
}
int add(int x,int y){
int z;
z=x+y;
printf("sum=");
return z;
}
调试结果:
please choose 1,2 or 3,4:1
max=34
please choose 1,2 or 3,4:2
min=-21
please choose 1,2 or 3,4:3
sum=13
【7】返回指针的函数
/*返回指针的函数 */
#include <stdio.h>
/*1.float(*pointer)[n]会把从参数中传递进来的数据进行分行,n个数为一行
* 2.原数组score为4行3列(score标识)
* 3.执行float(*pointer)[4]后数组score被重新划分为3行4列(用pointer标识)*/
#include <stdlib.h>
int main(void){
float score[][3]={60,70,80,90,56,89,67,88,34,78,90,66};
float *search();
float *p;
int i,k;
printf("enter the number of student:");
fflush(stdout);
scanf("%d",&k);
printf("the score of No.%d are:\n",k);
p=search(score,k);//通过二维数组入口地址传递到*search()中去,数组进行分组,4个为一组,并用p标记pointer
for(i=0;i<4;i++)
printf("%5.2f\t",*(p+i));
printf("\n");
return 0;
}
float *search(float(*pointer)[4],int n)
{
float *pt;
pt=*(pointer+n);//划分后的数组是一个多维数组
return pt;
}
调试结果:
enter the number of student:2
the score of No.2 are:
34.00 78.00 90.00 66.00
【8】结构体指针
/*结构体指针 */
#include <stdio.h>
/*定义结构体,用变量和指针和指向运算符进行输出
*即stu1.成员,(*p).成员,p->成员,都可以输出结构体指针所指向的结构体变量的结构体成员*/
#include <stdlib.h>
#include<string.h>
int main(void){
struct Student{
long num;
char name[20];
char sex ;
float score;
}stu1,*p;//定义结构体变量与结构体指针,也可写为struct Student stu1,struct Student *p;
p=&stu1;//将变量的地址传给指针变量
stu1.num=10101;
strcpy(stu1.name,"Li Lin");
stu1.sex='M';
stu1.score=86.5;
printf("No:%1d\nname:%s\nsex:%c\nscore:%5.1f\n",stu1.num,stu1.name,stu1.sex,stu1.score);
printf("No:%1d\nname:%s\nsex:%c\nscore:%5.1f\n",(*p).num,(*p).name,(*p).sex,(*p).score);
printf("No:%1d\nname:%s\nsex:%c\nscore:%5.1f\n",p->num,p->name,p->sex,p->score);//p指向的结构体变量中的各个成员
return 0;
}
运行结果:
No:10101
name:Li Lin
sex:M
score: 86.5
No:10101
name:Li Lin
sex:M
score: 86.5
No:10101
name:Li Lin
sex:M
score: 86.5
【9】顺序表的插入与删除
/*顺序表的插入和删除*/
#include<stdio.h>
#include<stdlib.h>
#define Max 20
/*用typedef声明新类型名sequencelist,代表一个结构体类型,可用新类型名去定义变量
* 命名一个新的类型名sequencelist来代表结构体类型*/
typedef struct {
int a[Max];//线性表占用的数组最大空间
int last;//记录线性表最后一个元素的位置
}sequencelist;
int insert(sequencelist *Q, int i, int p)/*将Q定义成指向sequencelist类型的指针变量,在顺序表Q中的第i个元素之前插入p,i~【1,last+2】*/
{
int k;
if ((i < 1) || (i > Q->last + 2))
{
printf("error!");
return 0;
}
if (Q->last >= Max - 1)
{
printf("max to no insert");
return 0;
}
for (k = Q->last; k >= i - 1; k--)
Q->a[k + 1] = Q->a[k];
Q->a[i - 1] = p;
Q->last++;
printf("insert success!");
return 1;
}
int del(sequencelist *Q,int i)
{
int k;
if((i<1)||(i>Q->last-1))
printf("error!");
else{
for (k=i;k<=Q->last;k++)
{
Q->a[k-1]=Q->a[k];
}
}
Q->last--;
printf("delete to success!");
return 1;
}
void print(sequencelist *Q){
int i;
for (i = 0; i <10; i++)
{
printf("%3d", Q->a[i]);
}
printf("\n");
}
int main(void){
int i;
sequencelist *Q;//定义指向结构体类型sequencelist的指针Q
Q = (sequencelist*)malloc(sizeof(sequencelist*)*100);//开辟sizeof(sequencelist*)*100字节的临时分配域,函数值为其第一个字节的地址,并赋值给指针变量Q
Q->last = -1;//空表表长置为-1
printf("insert and delete to sequencelist:");
for (i = 0; i <10; i++)
{
Q->a[i] = i;
Q->last++;
printf("%2d", Q->a[i]);
}
printf("\n");
printf("Q->last:%d",(*Q).last);
printf("\n");
insert(Q, Q->last / 3, 12);
print(Q);
del(Q,5);
print(Q);
return 0;
}
运行结果:
insert and delete to sequencelist: 0 1 2 3 4 5 6 7 8 9
Q->last:9
insert success! 0 1 12 2 3 4 5 6 7 8
delete to success! 0 1 12 2 4 5 6 7 8 9
【10】顺序表的合并
/*顺序表的合并*/
#include<stdio.h>
#include<stdlib.h>
#define Max 20
/*用typedef声明新类型名sequencelist,代表一个结构体类型,可用新类型名去定义变量
* 命名一个新的类型名sequencelist来代表结构体类型*/
typedef struct {
int a[Max];//线性表占用的数组最大空间
int last;//记录线性表最后一个元素的位置
}sequencelist;
void print(sequencelist *Q){
int i;
for (i = 0; i <Q->last+1; i++)
{
printf("%3d", Q->a[i]);
}
printf("\n");
}
void mergelist(sequencelist*LA,sequencelist*LB,sequencelist*LC){
int i,j;
for(i=0;i<=LA->last;i++){
LC->a[i]=LA->a[i];
j=i;
LC->last++;
}
for(i=0;i<=LB->last;i++){
LC->a[j+1]=LB->a[i];
LC->last++;
j++;
}
}
int main(void){
int i;
sequencelist *LA;//定义指向结构体类型sequencelist的指针LA
sequencelist*LB;
sequencelist*LC;
LA = (sequencelist*)malloc(sizeof(sequencelist*)*20);//开辟sizeof(sequencelist*)*100字节的临时分配域,函数值为其第一个字节的地址,并赋值给指针变量LA
LA->last = -1;//空表表长置为-1
LB = (sequencelist*)malloc(sizeof(sequencelist*)*20);
LB->last = -1;
LC = (sequencelist*)malloc(sizeof(sequencelist*)*40);
LC->last = -1;
printf("connection LA and LB to LC:");
printf("\n");
printf("The list LA is:");
for (i = 0; i <10; i++)
{
LA->a[i] = i;
LA->last++;
printf("%2d", LA->a[i]);
}
printf("\nLA->last:%d\n",LA->last);
printf("The list LB is:");
fflush(stdout);
for (i = 0; i <10; i++)
{
scanf("%3d",&LB->a[i]);
LB->last++;
}
printf("LB->last:%d\n",LB->last);
mergelist(LA,LB,LC);
printf("The list LC is:\n");
print(LC);
printf("LC->last:%d\n",LC->last);
return 0;
}
运行结果:
connection LA and LB to LC:
The list LA is: 0 1 2 3 4 5 6 7 8 9
LA->last:9
The list LB is:10 11 12 13 14 15 16 17 18 19
LB->last:9
The list LC is:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
LC->last:19
【11】头插尾插创建单链表
/*头插尾插创建单链表*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define Max 20
typedef struct Node{
char data;
struct Node*next;
}Node,*Linklist;//声明Node为结构体类型,Linklist为结构体指针类型
/*
void Initiallist(Linklist* L)//建立空的单链表
{
/*1.L是指向单链表的头结点的指针,用来接收主程序中待初始化单链表的头指针变量的地址
* 2.*L相当于主程序中代初始化单链表的头指针变量
* 3.L可以通过*L的地址访问结构体指针类型*L,从而通过指向头结点的指针L访问结构体中的成员*/
/*
*L=(Linklist)malloc(sizeof(Node)*10);//*L中存放malloc函数返回的结构体指针类型的地址,这个地址又在L中存放着
(*L)->next=NULL;//这个节点的指针域置空
}
*/
Linklist initiallist(Linklist L){
L=(Linklist)malloc(sizeof(Node));//*L中存放malloc函数返回的结构体指针类型的地址,这个地址又在L中存放着
if(L==NULL)
printf("error!");
else
printf("success!\n");
L->next=NULL;
return L;
}
/*头插法建立单链表*/
void createhead(Linklist L){
/*L是带头节点的空链表头指针*/
Node*s;
char c;
int flag = 1;
while(flag)
{
fflush(stdout);
c=getchar();
if(c!='$'){
s=(Node*)malloc(sizeof(Node));
s->data=c;
s->next=L->next;
L->next=s;
}else flag=0;
}
}
void print(Linklist L){
Node *p=L->next;
while(p!=NULL)
{
printf("%2c",p->data);
p=p->next;
}
}
int main(){
Linklist L=initiallist(L);
createhead(L);
print(L);
return 0;
}
运行结果:
success!
sdf$
f d s
【12】查找单链表中的特定序列i,特定元素key
/*查找单链表中的特定序列i,特定元素key*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define Max 20
typedef struct Node{
char data;
struct Node*next;
}Node,*Linklist;//声明Node为结构体类型,Linklist为结构体指针类型
/*
void Initiallist(Linklist* L)//建立空的单链表
{
/*1.L是指向单链表的头结点的指针,用来接收主程序中待初始化单链表的头指针变量的地址
* 2.*L相当于主程序中代初始化单链表的头指针变量
* 3.L可以通过*L的地址访问结构体指针类型*L,从而通过指向头结点的指针L访问结构体中的成员*/
/*
*L=(Linklist)malloc(sizeof(Node)*10);//*L中存放malloc函数返回的结构体指针类型的地址,这个地址又在L中存放着
(*L)->next=NULL;//这个节点的指针域置空
}
*/
Linklist initiallist(Linklist L){
L=(Linklist)malloc(sizeof(Node));//*L中存放malloc函数返回的结构体指针类型的地址,这个地址又在L中存放着
if(L==NULL)
printf("error!");
else
printf("initial successful!\n");
L->next=NULL;
return L;
}
/*头插法建立单链表*/
void createhead(Linklist L){
/*L是带头节点的空链表头指针*/
Node*s;
char c;
int flag = 1;
while(flag)
{
fflush(stdout);
c=getchar();
if(c!='$'){
s=(Node*)malloc(sizeof(Node));
s->data=c;
s->next=L->next;
L->next=s;
}else flag=0;
}
}
/*尾插法建立单链表*/
void createtail(Linklist L){
char c;
Node*r,*s;
int flag=1;
r=L;//r指针动态指向链表的当前表尾,一边于做尾插入,其初值指向头结点
while(flag){
fflush(stdout);
c=getchar();
if(c!='$')
{
s=(Linklist)malloc(sizeof(Node));
s->data=c;
r->next=s;
r=s;//指针r后移
}
else
{
flag=0;
r->next=NULL;//将表的最后一个节点的next域置为空,表示链表的结束
printf("success create list L as following...\n");
}
}
}
void print(Linklist L){
Node *p=L->next;
while(p!=NULL)
{
printf("%2c",p->data);
p=p->next;
}
printf("\n");
}
/*查找第i个节点*/
Node* geti(Linklist L,int i){
printf("search the %d node is:",i);
if(i<0)return NULL;
int j=0;
Node*p=NULL;
p=L;//新建一个指向链表头结点的节点指针
while((p->next!=NULL)&&(j<i))
{
j++;
p=p->next;
}
if(j==i)
{
fflush(stdout);
printf("search successful!");
return p;
}
else return NULL;
}
/*求链表长度*/
int listlenght(Linklist L){
Node*p=L->next;
int j=0;
while(p!=NULL)
{
p=p->next;
j++;
}
return j;
}
/*按值查找*/
Node * valuekey(Linklist L,char key)
{
printf("\nstrat query:");
fflush(stdout);
Node*p=L->next;
printf("here");
fflush(stdout);
if(p->data!=key)
p=p->next;
else {
printf("OK");
fflush(stdout);
return p;
}
}
int main(void){
int i;
char key;
Node*p=NULL;
Node*m;
Linklist L=initiallist(L);//初始化单链表
createhead(L);//头插法建表
print(L);//输出表
printf("The length of this list is %d",listlenght(L));
/*
* 尾插法建表
createtail(L);
print(L);
*/
/*找表中第i个节点并输出*/
fflush(stdout);//立即输出
scanf("%d",&i);
getchar();
p=geti(L,i);
printf("%2c\n",p->data);
fflush(stdout);
free(p);
/*找表中值为key的节点并输出*/
system("cls");
printf("please input the key:");
fflush(stdout);
scanf("%c",&key);
getchar();
printf("%c",key);
fflush(stdout);
m=valuekey(L,key);
printf("Query successful!--%c--",m->data);
fflush(stdout);
return 0;
}
运行结果:
initial successful!
125485$
5 8 4 5 2 1
The length of this list is 62
search the 2 node is:search successful! 8
please input the key:8
8
strat query:hereQuery successful!--8--
【13】单链表的插入删除,与两表的和并
/*单链表的插入删除,与两表的合并*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define ERROR 0;
#define OK 1;
typedef struct Node{
char data;
struct Node*next;
}Node,*Linklist;
Linklist initiallist(Linklist L){
L=(Linklist)malloc(sizeof(Node));//*L中存放malloc函数返回的结构体指针类型的地址,这个地址又在L中存放着
if(L==NULL)
printf("error!");
else
printf("initial successful!\n");
L->next=NULL;
return L;
}
/*头插法建立单链表*/
void createhead(Linklist L){
/*L是带头节点的空链表头指针*/
Node*s;
char c;
int flag = 1;
while(flag)
{
fflush(stdout);
c=getchar();
if(c!='$'){
s=(Node*)malloc(sizeof(Node));
s->data=c;
s->next=L->next;
L->next=s;
}else flag=0;
}
}
/*尾插法建立单链表*/
void createtail(Linklist L){
char c;
Node*r,*s;
int flag=1;
r=L;//r指针动态指向链表的当前表尾,一边于做尾插入,其初值指向头结点
while(flag){
fflush(stdout);
c=getchar();
if(c!='$')
{
s=(Linklist)malloc(sizeof(Node));
s->data=c;
r->next=s;
r=s;//指针r后移
}
else
{
flag=0;
r->next=NULL;//将表的最后一个节点的next域置为空,表示链表的结束
printf("success create list L as following...\n");
}
}
}
void print(Linklist L){
Node *p=L->next;
while(p!=NULL)
{
printf("%2c",p->data);
fflush(stdout);
p=p->next;
}
printf("\n");
}
/*在带头结点的单链表L中第i个位置插入值为e的结点*/
int insertlist(Linklist L,int i,char e)
{
Node*pre,*s;
int k=0;
if(i<=0)return ERROR;
pre=L;//从头开始,查找第i-1个结点
while(pre!=NULL&&k<i-1){
pre=pre->next;
k++;
}//查找到i-1个结点
if(pre==NULL){
printf("illegal position to insert!");
fflush(stdout);
return ERROR;
}
s=(Node*)malloc(sizeof(Node));
s->data=e;
s->next=pre->next;
pre->next=s;
return OK;
}
void deletelist(Linklist L,int i)
{
Node*pre,*p;//p是pre的后驱结点
int k=0;
pre=L;
while(pre->next!=NULL&&k<i-1)
{
pre=pre->next;
k++;
}
if(pre->next==NULL)
{
printf("illegal to delete!");
}
p=pre->next;
pre->next=p->next;
free(p);//释放p所指的存储单元,p成为野指针
}
/*和并两个有序的单链表*/
Linklist mergelist(Linklist LA,Linklist LB){
Node *pa,*pb;//pa,pb指向LA和LB中的第一个节点
Node * r;//r始终指向表LC尾
Linklist LC;
pa=LA->next;
pb=LB->next;
LC=LA;
LC->next=NULL;//将LC表置空
r=LC;
/*当两个表均未处理完时,比较选择将较小结点插入到新表LC中去*/
while(pa!=NULL&&pb!=NULL)
{
if(pa->data<=pb->data)
{
r->next=pa;
r=pa;
pa=pa->next;
}
else
{
r->next=pb;
r=pb;
pb=pb->next;
}
}
if(pa)
r->next=pa;
else
r->next=pb;
return LC;
}
int main(void){
char c='A';
Linklist LA=initiallist(LA);//初始化单链表LA
Linklist LB=initiallist(LB);
Linklist LC;
printf("create list LA:");
fflush(stdout);
createhead(LA);//头插法建表
print(LA);//输出表
printf("create list LB:");
fflush(stdout);
createhead(LB);
print(LB);
printf("---------delete---------\n");
fflush(stdout);
deletelist(LA,2);
print(LA);
printf("---------insert---------\n");
fflush(stdout);
insertlist(LA,3,c);
print(LA);
printf("LA merge LB is LC as following...\n");
LC=mergelist( LA,LB);
print(LC);
return 0;
}
运行结果:
initial successful!
initial successful!
create list LA:zxcvbn$
n b v c x z
create list LB:edtgyhuj$
j u h y g t d e
---------delete---------
n v c x z
---------insert---------
n v A c x z
LA merge LB is LC as following...
j n u h v A c x y g t d e z
【14】循环单链表的插入删除,与两表的和并
/*循环单链表的插入删除,与两表的合并*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define ERROR 0;
#define OK 1;
typedef struct Node{
char data;
struct Node*next;
}Node,*Linklist;
Linklist initiallist(Linklist L){
L=(Linklist)malloc(sizeof(Node));//*L中存放malloc函数返回的结构体指针类型的地址,这个地址又在L中存放着
if(L==NULL)
printf("error!");
else
printf("initial successful!\n");
L->next=L;
return L;
}
/*头插法建立循环单链表*/
void createhead(Linklist L){
/*L是带头节点的空链表头指针*/
Node*s;
char c;
int flag = 1;
while(flag)
{
c=getchar();
if(c!='$'){
s=(Node*)malloc(sizeof(Node));
s->data=c;
s->next=L->next;
L->next=s;
}
else
{
flag=0;
s->next=L;//将表的最后一个节点的next域置为空,表示链表的结束
printf("success create list L as following...\n");
}
}
}
/*尾插法建立循环单链表*/
void createtail(Linklist L){
char c;
Node*r,*s;
int flag=1;
r=L;//r指针动态指向链表的当前表尾,一边于做尾插入,其初值指向头结点,最后指向表头
while(flag){
fflush(stdout);
c=getchar();
if(c!='$')
{
s=(Linklist)malloc(sizeof(Node));
s->data=c;
r->next=s;
r=s;//指针r后移
}
else
{
flag=0;
r->next=L;//将表的最后一个节点的next域置为空,表示链表的结束
printf("success create list L as following...\n");
}
}
}
/*求循环单链表的长度*/
int circlelistlength(Linklist L){
int i=0;
Linklist temp;
if(L==NULL)
return 0;
if(L->next==L)
return 1;
temp=L->next;
while(temp!=L)
{
i++;
temp=temp->next;
}
return i;
}
/*输出循环单链表*/
void print(Linklist L){
Node *p=L->next;
while(p!=NULL)
{
printf("%2c",p->data);
fflush(stdout);
p=p->next;
if(p->next==L)
break;
}
printf("\n");
}
/*在带头结点的循环单链表L中第i个位置插入值为e的结点*/
int insertlist(Linklist L,int i,char e)
{
Node*pre,*s;
int k=0;
if(i<=0)return ERROR;
pre=L->next;//从头开始,查找第i-1个结点
while(pre!=L&&k<i-1){
pre=pre->next;
k++;
}//查找到i-1个结点
if(pre==L){
printf("illegal position to insert!");
fflush(stdout);
return ERROR;
}
s=(Node*)malloc(sizeof(Node));
s->data=e;
s->next=pre->next;
pre->next=s;
return OK;
}
/*在带头结点的循环单链表删除第i个元素*/
void deletelist(Linklist L,int i)
{
Node*pre,*p;//p是pre的后驱结点
int k=0;
pre=L->next;
while(pre->next!=L&&k<i-1)
{
pre=pre->next;
k++;
}
if(pre->next==L)
{
printf("illegal to delete!");
}
p=pre->next;
pre->next=p->next;
free(p);//释放p所指的存储单元,p成为野指针
}
/*循环单链表合并算法*/
/*算法1*/
Linklist merge1(Linklist LA,Linklist LB)//LA,LB是链表的头指针
{
Node *p,*q;
p=LA;
q=LB;
while(p->next!=LA) p=p->next;//找到LA的表尾,用p指向它
while(q->next!=LB) q=q->next;
q->next=LA;
p->next=LB->next;//跳过头结点
free(LB);
return LA;
}
/*算法2*/
Linklist merge2(Linklist LA,Linklist LB)//LA,LB是链表的尾指针,尾指针指向头一个节点,头指针指向头结点
{
Node *p;
p=LA->next;
LA->next=LB->next->next;
free(LB->next);
LB->next=p;
return LB;
}
int main(void){
int i,j;
char c='A';
Linklist LA=initiallist(LA);//初始化单链表
Linklist LB=initiallist(LB);
printf("create circle-list LA:");
fflush(stdout);
createtail(LA);//不建议用头插法建立链表,头插法表头不好求
i=circlelistlength(LA);
printf("The length of this single-circle is %d\n",i);
fflush(stdout);
print(LA);//输出时表的最后一个元素不会输出,因为最后一个元素指向表头,程序不予识别
printf("create circle-list LB:");
fflush(stdout);
createtail(LB);//不建议用头插法建立链表,头插法表头不好求
j=circlelistlength(LB);
printf("The length of this single-circle is %d\n",j);
fflush(stdout);
print(LB);
printf("LA merge LB to LC as show following...\n");
fflush(stdout);
print(merge2(LA,LB));
printf("-------delete in circle-list LB-------\n");
fflush(stdout);
deletelist(LB,2);
print(LB);
printf("-------insert in circle-list LB-------\n");
fflush(stdout);
insertlist(LB,2,c);
print(LB);
return 0;
}
运行结果:
initial successful!
initial successful!
create circle-list LA:125368497$
success create list L as following...
The length of this single-circle is 9
1 2 5 3 6 8 4 9
create circle-list LB:wsedrftgyh$
success create list L as following...
The length of this single-circle is 11
w s e d r f t g y
LA merge LB to LC as show following...
1 2 5 3 6 8 4 9 7 0 w s e d r f t g y
-------delete in circle-list LB-------
1 2 3 6 8 4 9 7 0 w s e d r f t g y
-------insert in circle-list LB-------
1 2 A 3 6 8 4 9 7 0 w s e d r f t g y
【15】双向循环链表的插入删除,与两表的和并
/*双向链表的插入删除,与两表的合并*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define ERROR 0;
#define OK 1;
typedef struct Node{
char data;
struct Node*prior,*next;
}DNode,*DoubleLinklist;
DoubleLinklist initiallist(DoubleLinklist L){
L=(DoubleLinklist)malloc(sizeof(DNode));//*L中存放malloc函数返回的结构体指针类型的地址,这个地址又在L中存放着
if(L==NULL)
printf("error!");
else
printf("initial successful!\n");
L->next=L;
L->prior=L;
return L;
}
/*头插法建立双向循环单链表*/
void createhead(DoubleLinklist L){
/*L是带头节点的空链表头指针*/
DNode*s;
char c;
int flag = 1;
while(flag)
{
c=getchar();
if(c!='$'){
s=(DNode*)malloc(sizeof(DNode));
s->data=c;
s->next=L->next;//将L->next的地址放到s->next中去
L->next->prior=s;//让L右边的节点指向s节点
L->next=s;//L与s相互指向
s->prior=L;
}
else
{
flag=0;
printf("success create list L as following...\n");
fflush(stdout);
}
}
}
/*尾插法建立双向循环单链表*/
void createtail(DoubleLinklist L){
char c;
DNode*r,*s;
int flag=1;
r=L;//r指针动态指向链表的当前表尾,一边于做尾插入,其初值指向头结点,最后指向表头
while(flag){
fflush(stdout);
c=getchar();
if(c!='$')
{
s=(DoubleLinklist)malloc(sizeof(DNode));
s->data=c;
r->next=s;
s->prior=r;
r=s;//指针r后移
}
else
{
flag=0;
r->next=L;//将表的最后一个节点的next域指向头结点L,表示链表的结束
L->prior=r;
printf("success create list L as following...\n");
}
}
}
/*求双向循环单链表的长度*/
int circlelistlength(DoubleLinklist L){
int i=0;
DoubleLinklist temp;
if(L==NULL)
return 0;
if(L->next==L)
return 1;
temp=L->next;
while(temp!=L)
{
i++;
temp=temp->next;
}
return i;
}
/*输出双向循环单链表*/
void print(DoubleLinklist L){
DNode *p=L->next;
while(p!=NULL)
{
printf("%2c",p->data);
fflush(stdout);
p=p->next;
if(p->next==L)
break;
}
printf("\n");
}
/*在带头结点的双向循环单链表L中第i个位置插入值为e的结点*/
int insertlist(DoubleLinklist L,int i,char e)
{
DNode*pre,*s;
int k=0;
if(i<=0)return ERROR;
pre=L->next;//从头开始,查找第i-1个结点
while(pre!=L&&k<i-1){
pre=pre->next;
k++;
}//查找到i-1个结点
if(pre==L){
printf("illegal position to insert!");
fflush(stdout);
return ERROR;
}
s=(DNode*)malloc(sizeof(DNode));
s->data=e;
s->prior=pre->prior;//pre->prior指向s要插入位置的右节点,这个右节点原先指向s要插入的左节点
pre->prior->next=s;//让pre前面的节点指向s
s->next=pre;
pre->prior=s;
return OK;
}
/*在带头结点的双向循环链表删除第i个元素*/
void deletelist(DoubleLinklist L,int i)
{
DNode*pre;
int k=0;
pre=L->next;
while(pre->next!=L&&k<i-1)
{
pre=pre->next;
k++;
}
if(pre->next==L)
{
printf("illegal to delete!");
}
pre->prior->next=pre->next;//前一个节点指向后一个节点
pre->next->prior=pre->prior;//后一个节点指向前一个节点
free(pre);//释放p所指的存储单元,p成为野指针
}
/*递归合并
DoubleLinklist mergetwoList1(DoubleLinklist pHead1, DoubleLinklist pHead2)
{
if(pHead1 == NULL)
{
return pHead2;
}
else if (pHead2 == NULL)
{
return pHead1;
}
DoubleLinklist pMergeHead = NULL;
if (pHead1->data < pHead2->data)
{
pMergeHead = pHead1;
pMergeHead->next = mergetwoList(pHead1->next, pHead2);
pMergeHead->next->next->prior = pMergeHead->next;
}
else
{
pMergeHead = pHead2;
pMergeHead->next = mergetwoList(pHead1->next, pHead1);
pMergeHead->next->next->prior = pMergeHead->next;
}
return pMergeHead;
}
*/
/*合并两个双向循环链表*/
void mergetwoList2(DoubleLinklist La,DoubleLinklist Lb)
{
DoubleLinklist p=La->next;
while(p->next!=La)
{
p=p->next;
}
La->prior->next=Lb->next;
Lb->next->prior=La->prior;
Lb->prior->next=La;
La->prior=Lb->prior;
}
int main(void){
int i,j;
char c='A';
DoubleLinklist LA=initiallist(LA);//初始化单链表
DoubleLinklist LB=initiallist(LB);//初始化单链表
printf("create circle-list LA:");
fflush(stdout);
createtail(LA);//不建议用头插法建立链表,头插法表头不好求
i=circlelistlength(LA);
printf("The length of this double-circle is %d\n",i);
fflush(stdout);
print(LA);//输出时表的最后一个元素不会输出,因为最后一个元素指向表头,程序不予识别
printf("create circle-list LB:");
fflush(stdout);
createhead(LB);
j=circlelistlength(LB);
printf("The length of this double-circle is %d\n",j);
fflush(stdout);
print(LB);//输出时表的最后一个元素不会输出,因为最后一个元素指向表头,程序不予识别
printf("-------insert--------\n");
fflush(stdout);
insertlist( LA,2,c);
print(LA);
printf("-------delete--------\n");
fflush(stdout);
deletelist( LA,3);
print(LA);
printf("LA merge LB to LA as show following...\n");
fflush(stdout);
mergetwoList2(LA,LB);
print(LA);
return 0;
}
运行结果:
initial successful!
initial successful!
create circle-list LA:1253648592$
success create list L as following...
The length of this double-circle is 10
1 2 5 3 6 4 8 5 9
create circle-list LB:wsedrftgyh$
success create list L as following...
The length of this double-circle is 11
h y g t f r d e s w
-------insert--------
1 A 2 5 3 6 4 8 5 9
-------delete--------
1 A 5 3 6 4 8 5 9
LA merge LB to LA as show following...
1 A 5 3 6 4 8 5 9 h y g t f r d e s w
【16】静态链表
#include<stdio.h>
#define maxsize 30
typedef char elemtype;
typedef struct{
int cur;
elemtype data;
}slink,slinklist[maxsize];
void initspace_sl(slink *space)
{//将数据各分量链接成一个备用链表,space[0]代表头指针
int i;
for(i=0;i<maxsize-1;i++)
{
space[i].cur=i+1;
}//下标为i结点的后继为下标是i+1的结点
space[maxsize-1].cur=0;//0表示空指针
}
int malloc_sl(slink *space)
{//若备用链表非空,则返回分配节点下标,否则返回0。
int i;
i=space[0].cur;
if(space[0].cur)
{
space[0].cur=space[i].cur;//使头结点后继等于I结点的后继
}//既在备用链表中删除i节
return i;
}
void free_sl(slink *space,int k)
{//将下标为k的空闲节点回收到备用链表中
space[k].cur=space[0].cur;
space[0].cur=k;
}
void difference_sl(slink *space,int *k)
{
int q,w,r,t,y,u,a;
elemtype ch;
initspace_sl(space);
*k=malloc_sl(space);//k表示返回的头结点
q=*k;//q指向最后一个结点
scanf("%d%d",&w,&r);//输入A、B的大小
for(int i=1;i<=w;i++)//将集合A中的数据依次插入静态链表中
{
t=malloc_sl(space);
scanf("%c",&space[t].data);
space[q].cur=t;
q=t;
}
space[q].cur=0;//最后一个结点的后继为空指针
for(int j=1;j<=r;j++)//读取B集合的元素
{
scanf("%c",&ch);
y=*k;//y指向头结点
u=y;
while(space[y].data!=ch&&y!=space[q].cur)
{//查找ch
u=y;//u指向上一结点
y=space[y].cur;
}
if(y==space[q].cur)//未找到,做插入操作
{
a=malloc_sl(space);
space[a].data=ch;
space[a].cur=space[q].cur;
space[q].cur=a;
q=a;
}
else//找到,做删除操作
{
space[u].cur=space[y].cur;
free_sl(space,y);
if(y==q){
q=u;
}
}
}
}
int main()
{
slinklist space;
int x,y;
difference_sl(space,&x);
y=x;
while(y)
{//遍历静态链表
printf("%3d %c\n",y,space[y].data);
y=space[y].cur;
}
return 0;
}
调试结果:
4 5 asdfqwert
1
2
3 a
4 s
5 d
6 f
7 q
8 w
9 e
10 r
【17】顺序栈的实现
/*顺序栈的实现*/
#include<stdio.h>
#define stacksize 50
#define TRUE 1
#define FALSE 0
typedef struct{
char elem[stacksize];
int top;
}sequencestack;
/*顺序栈的初始化*/
void initial(sequencestack * S)
{
S->top=-1;//构造一个空栈
printf("initial sequence-stack success!\n");
fflush(stdout);
}
/*顺序栈进栈操作*/
int sequencepushstack(sequencestack *S)
{
char c;
int flag=1;
if(S->top==stacksize-1)
{
printf("The stack is full !");
fflush(stdout);
return FALSE;
}
else
{
while(flag)
{
c=getchar();
if(c!='$')
{
S->top++;
S->elem[S->top]=c;
}
else
{
flag=0;
printf("Stack success !\n");
fflush(stdout);
}
}
}
return TRUE;
}
/*弹出栈顶元素*/
int sequencepopstack(sequencestack *S)
{
if(S->top==-1)
{
printf("stack empty!\n");
fflush(stdout);
}
else
{
printf("The value of the stack top element is %c\n",S->elem[S->top]);
fflush(stdout);
S->top--;
}
return TRUE;
}
/*所有元素出栈*/
int popallelement(sequencestack *S)
{
if(S->top==-1)
{
printf("\n stack empty!\n");
fflush(stdout);
return TRUE;
}
else
{
printf("%2c",S->elem[S->top]);
fflush(stdout);
S->top--;
popallelement(S);
}
return FALSE;
}
int main(void)
{
sequencestack *S;
/*形参的星号是指指针,就是结构体类型的指针,函数形参是一个结构体指针,
* 实参也需要一个该结构体类型的指针,也就是要实参是一个地址传给形参
* 故在函数调用是使用的是&符号,就是区地址,将结构体变量的地址传过去
* 这样在函数里对于形参的修改就是对实参结构体变量的修改。*/
initial(&S);
printf("Please input the element to enter the stack and end with $ \n");
fflush(stdout);
sequencepushstack(&S);
sequencepopstack(&S);
printf("The out-of-stack elements are as follows... \n");
fflush(stdout);
popallelement(&S);
return 0;
}
运行结果:
initial sequence-stack success!
Please input the element to enter the stack and end with $
edrftgyhujikol123456plmjkn$
Stack success !
The value of the stack top element is n
The out-of-stack elements are as follows...
k j m l p 6 5 4 3 2 1 l o k i j u h y g t f r d e
stack empty!
【18】多栈共享操作
/*多栈共享操作*/
#include<stdio.h>
#define stacksize 50
#define TRUE 1
#define FALSE 0
typedef struct{
char elem[stacksize];
int top[2];
}doublesequencestack;
/*双端顺序栈的初始化*/
void initial(doublesequencestack * S)
{
S->top[0]=-1;//构造一个双端顺序空栈
S->top[1]=stacksize;
printf("initial double-sequence-stack success!\n");
fflush(stdout);
}
/*双端顺序栈进栈操作*/
int doublesequencepushstack(doublesequencestack *S,int i)
{
char c;
int flag=1;
if(S->top[0]==S->top[1])
{
printf("The stack is full !");
fflush(stdout);
return FALSE;
}
else
{
printf("Please enter the stack[%d] number you want to push elements !",i);
fflush(stdout);
switch(i)
{
case 1:
while(flag)
{
c=getchar();
if(c!='$')
{
S->top[0]++;
S->elem[S->top[0]]=c;
}
else
{
flag=0;
printf("Stack success !\n");
fflush(stdout);
}
}break;
case 2:
while(flag)
{
c=getchar();
if(c!='$')
{
S->top[1]--;
S->elem[S->top[1]]=c;
}
else
{
flag=0;
printf("Stack success !\n");
fflush(stdout);
}
}break;
}
}
return TRUE;
}
/*双端顺序栈弹出栈顶元素*/
int doublesequencepopstack(doublesequencestack *S,int i)
{
switch(i)
{
case 1:
if(S->top[0]==-1)
{
printf("stack empty!\n");
fflush(stdout);
}
else
{
printf("The value of the stack top element is %c\n",S->elem[S->top[0]]);
fflush(stdout);
S->top[0]--;
}break;
case 2:
if(S->top[1]==stacksize)
{
printf("stack empty!\n");
fflush(stdout);
}
else
{
printf("The value of the stack top element is %c\n",S->elem[S->top[1]]);
fflush(stdout);
S->top[1]++;
}break;
}
return TRUE;
}
/*双端顺序栈所有元素出栈*/
int popallelement(doublesequencestack *S,int i)
{
switch(i)
{
case 1:
if(S->top[0]==-1)
{
printf("\n stack empty!\n");
fflush(stdout);
return TRUE;
}
else
{
printf("%2c",S->elem[S->top[0]]);
fflush(stdout);
S->top[0]--;
popallelement(S,i);
}break;
case 2:
if(S->top[1]==stacksize)
{
printf("\n stack empty!\n");
fflush(stdout);
return TRUE;
}
else
{
printf("%2c",S->elem[S->top[1]]);
fflush(stdout);
S->top[1]++;
popallelement(S,i);
}break;
}
return FALSE;
}
int main(void)
{
doublesequencestack *S;
/*形参的星号是指指针,就是结构体类型的指针,函数形参是一个结构体指针,
* 实参也需要一个该结构体类型的指针,也就是要实参是一个地址传给形参
* 故在函数调用是使用的是&符号,就是区地址,将结构体变量的地址传过去
* 这样在函数里对于形参的修改就是对实参结构体变量的修改。*/
initial(&S);//初始化
printf("Please input the element to enter the stack[1] and end with $ \n");
fflush(stdout);
doublesequencepushstack(&S,1);//左端入栈
printf("Please input the element to enter the stack[2] and end with $ \n");
fflush(stdout);
doublesequencepushstack(&S,2);//右端入栈
doublesequencepopstack(&S,1);//左端栈顶元素出
doublesequencepopstack(&S,2);//右端栈顶元素出
printf("The out-of-stack[1] elements are as follows... \n");
fflush(stdout);
popallelement(&S,1);//左端元素全部出栈
printf("The out-of-stack[2] elements are as follows... \n");
fflush(stdout);
popallelement(&S,2);//右端元素全部出栈
return 0;
}
运行结果:
initial double-sequence-stack success!
Please input the element to enter the stack[1] and end with $
Please enter the stack[1] number you want to push elements !123456789$
Stack success !
Please input the element to enter the stack[2] and end with $
Please enter the stack[2] number you want to push elements !qawsedrftgyh$
Stack success !
The value of the stack top element is 9
The value of the stack top element is h
The out-of-stack[1] elements are as follows...
8 7 6 5 4 3 2 1
stack empty!
The out-of-stack[2] elements are as follows...
y g t f r d e s w a q
stack empty!
【19】链栈
/*链栈*/
/*相当于单链表的头插和头插删除*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define Max 20
typedef struct Node{
char data;
struct Node*next;
}Node,*LinkStack;
LinkStack initiallist(LinkStack L){
L=(LinkStack)malloc(sizeof(Node));
if(L==NULL)
printf("error!");
else
printf(" Link-Stack initial success!\n");
L->next=NULL;
return L;
}
/*链栈进栈操作*/
void pushlinklist(LinkStack L){
/*L是带头节点的空链表头指针*/
Node*s;
char c;
printf("Please input the element to enter the link-stack and end with $ \n");
fflush(stdout);
int flag = 1;
while(flag)
{
fflush(stdout);
c=getchar();
if(c!='$'){
s=(Node*)malloc(sizeof(Node));
s->data=c;
s->next=L->next;
L->next=s;
}else flag=0;
}
}
void sequenceprintlinklist(LinkStack L){
printf("Print the elements in the stack from the top to the bottom is as follows\n ");
fflush(stdout);
Node *p=L->next;
while(p!=NULL)
{
printf("%2c",p->data);
p=p->next;
}
if(p==NULL)
{
printf("\nPrint all elements in this link stack!");
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
void popelem(LinkStack L)
{
Node*pre,*p;//p是pre的后驱结点
pre=L;
if(pre->next==NULL)
{
printf("\nLink-Stack empty!");
fflush(stdout);
}
while(pre!=NULL)
{
p=pre->next;
pre->next=p->next;
printf("%2c",p->data);
fflush(stdout);
}
}
int main(){
LinkStack L=initiallist(L);
pushlinklist(L);//push in link stack
sequenceprintlinklist(L);//print elements from link stack
printf("The output of the elements in the stack from the top to the bottom is as follows\n");
fflush(stdout);
popelem( L);//pop elements from link stack
return 0;
}
运行结果:
Link-Stack initial success!
Please input the element to enter the link-stack and end with $
1253648edrftgy$
Print the elements in the stack from the top to the bottom is as follows
y g t f r d e 8 4 6 3 5 2 1
Print all elements in this link stack!
The output of the elements in the stack from the top to the bottom is as follows
y g t f r d e 8 4 6 3 5 2 1
Link-Stack empty!
【20】正则括号的判断(动态链栈)
/*正则括号的判断(动态链栈)*/
#include <stdio.h>
#include <stdlib.h>
#define STACKINCREAMENT 10
#define STACK_INIT_SIZE 100
#define OVERFLOW -2
#define OK 1
#define ERROR 0
typedef int status;
typedef char SElemtype;
typedef struct
{
SElemtype *base;
SElemtype *top;
status stacksize;
}sqstack;
//初始不带头结点的链栈
status Init(sqstack *s)
{
s->base = (SElemtype *)malloc(STACK_INIT_SIZE * sizeof(SElemtype));
if(!s->base)
exit(OVERFLOW);
s->top = s->base;
s->stacksize = STACK_INIT_SIZE ;
return OK;
}
//获取栈顶元素
status Gettop(sqstack *s, SElemtype e)
{
if(s->top == s->base)
return ERROR;
e = *(s->top-1);
return OK;
}
//压栈
status push(sqstack *s, SElemtype e)
{
if(s->top - s->base >= s->stacksize)
{
s->base = (SElemtype *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemtype));
if(!s->base)
exit(OVERFLOW);
s->top = s->base + s->stacksize;
s->stacksize += STACKINCREAMENT;
}
*s->top++ = e;
return OK;
}
//出栈
status pop(sqstack *s, SElemtype *e)
{
if(s->top == s->base)
return ERROR;
*e=*--s->top;
return OK;
}
//判断是否为空栈
status stackempty(sqstack *s)
{
if(s->top==s->base)
return OK;
return ERROR;
}
//清空栈
status clearstack(sqstack *s)
{
if(s->top == s->base)
return ERROR;
s->top = s->base;
return OK;
}
//括号匹配算法
status Parenthesis_match(sqstack *s,char *str)
{
int i=0, flag=0;
SElemtype e;
while(str[i] != '\0')
{
switch(str[i])
{
case '(':
push(s,str[i]);
break;
case '[':
push(s,str[i]);
break;
case ')':
{
pop(s,&e);
if(e != '(')
flag=1;
}
break;
case ']':
{
pop(s,&e);
if(e!='[')
flag=1;
}
break;
default:
break;
}
if(flag)
break;
i++;
}
if(!flag && stackempty(s))
printf("Brace match success!!\n");
else
printf("Brace match fail!\n");
return OK;
}
int main()
{
char str[100], enter;
sqstack s;
Init(&s);
printf("Please input the string you want check:\n");
fflush(stdout);
scanf("%s",str);
scanf("%c",&enter);
Parenthesis_match(&s,str);
return 0;
}
运行结果:
Please input the string you want check:
()
Brace match success!!
【20】顺序队列
/*----------------------------------------------------------------
设立一个队首指针front ,一个队尾指针rear ,分别指向队首和队尾元素。
◆ 初始化:front=rear=0。
◆ 队列为空:front=rear。
◆ 队满:rear=MaxSize。
◆ 入队:将新元素插入rear所指的位置,然后rear加1。
◆ 出队:删去front所指的元素,然后加1并返回被删元素。
◆ 取队首元素:返回fornt指向的元素值
-----------------------------------------------------------------*/
#include <stdio.h>
#include <assert.h>
#include <Windows.h>
#define MaxSize 10 //队列的最大容量
typedef char DataType; //队列中元素类型
typedef struct Queue
{
DataType Queue[MaxSize];
int front; //队头指针
int rear; //队尾指针
}SequenceQueue;
//队列初始化,将队列初始化为空队列
void initialqueue(SequenceQueue *Q)
{
Q->front = Q->rear = 0; //把对头和队尾指针同时置0
printf("initial sequence queue success!\n");
fflush(stdout);
}
//判断队列为空
int checkempty(SequenceQueue* Q)
{
if (Q->front == Q->rear)
{
printf("sequence queue is empty!\n ");
fflush(stdout);
return 1;
}
printf("sequence queue is not empty!\n");
fflush(stdout);
return 0;
}
//判断队列是否为满
int checkfull(SequenceQueue* Q)
{
if (Q->rear == MaxSize)
{
return 1;
}
printf("sequence queue is not full!\n ");
fflush(stdout);
return 0;
}
//入队,将元素data插入到队列SQ中
int enqueue(SequenceQueue *Q)
{
char c;
printf("Enter sequence queue front:%d\n",Q->front);
fflush(stdout);
printf("Enter sequence queue rear:%d\n",Q->rear);
fflush(stdout);
int flag=1;
if(checkfull(Q))//尾指针加1是否产生假溢出
{
printf("The sequence queue is full !");
fflush(stdout);
return 0;
}
else
{
while(flag)
{
c=getchar();
if(c!='$')
{
Q->Queue[Q->rear]=c;
Q->rear=Q->rear+1;//重新设置队尾指针
}
else
{
flag=0;
printf("Elements enter sequence queue success !\n");
fflush(stdout);
}
}
}
return 1;
}
//出队,将队列中队头的元素data出队,出队后队头指针front后移一位
int dequeue(SequenceQueue* Q)
{
if (checkempty(Q))
{
printf("queue is empty!\n");
return 0;
}
else
{
printf("Out elements is %2c\n" ,Q->Queue[Q->front]); //出队元素值
fflush(stdout);
Q->front = (Q->front)+1;
dequeue(Q);
}//队尾指针后移一位
return 1;
}
//获取队首元素
char GetHead(SequenceQueue* Q,DataType* data)
{
if (checkempty(Q))
{
printf("queue is empty!\n");
}
return *data = Q->Queue[Q->front];
}
//清空队列
void ClearQueue(SequenceQueue* Q)
{
Q->front = Q->rear = 0;
}
//打印队列中的与元素
void PrintQueue(SequenceQueue* Q)
{
assert(Q);//原型为void assert(int expression);assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
int i = Q->front;
printf("print this sequence queue as follows...\n");
fflush(stdout);
while(i<Q->rear)
{
printf("%3c", Q->Queue[i]);
fflush(stdout);
i++;
}
printf("\n");
}
int main(void)
{
SequenceQueue *sequencequeue;
DataType* data;
initialqueue(&sequencequeue);//初始化
enqueue(&sequencequeue);//入队
printf("print the first element in this sequence queue %2c\n", GetHead(&sequencequeue,& data));//打印队中首元素
fflush(stdout);
PrintQueue(&sequencequeue);//打印队列元素
dequeue(&sequencequeue);//元素出队
return 0;
}
运行结果:
initial sequence queue success!
Enter sequence queue front:0
Enter sequence queue rear:0
sequence queue is not full!
edrsftgy$
Elements enter sequence queue success !
sequence queue is not empty!
print the first element in this sequence queue e
print this sequence queue as follows...
e d r s f t g y
sequence queue is not empty!
Out elements is e
sequence queue is not empty!
Out elements is d
sequence queue is not empty!
Out elements is r
sequence queue is not empty!
Out elements is s
sequence queue is not empty!
Out elements is f
sequence queue is not empty!
Out elements is t
sequence queue is not empty!
Out elements is g
sequence queue is not empty!
Out elements is y
sequence queue is empty!
【21】循环队列
/*循环队列*/
#include <stdio.h>
#include <stdlib.h>
#define queuemaxsize 50
#define OVERFLOW -2
#define OK 1
#define ERROR 0
typedef int status;
typedef struct
{
status front;
status rear;
char data[queuemaxsize];
}SequenceQueue;
/*1、循环队列的优点:
可以有效的利用资源。用数组实现队列时,如果不移动,随着数据的不断读写,会出现假满队列的情况。即尾数组已满但头数组还是空的;循环队列也是一种数组,只是它在逻辑上把数组的头和尾相连,形成循环队列,当数组尾满的时候,要判断数组头是否为空,不为空继续存放数据。
2、循环队列的缺点:
循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"是"满"。
3、拓展知识:
为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列。
*/
/*初始化队列*/
void initialqueue(SequenceQueue * Q)
{
Q->front=Q->rear=queuemaxsize-1;//从最大到最小
printf("initial sequence queue success!\n");
fflush(stdout);
}
/*判空*/
int checkempty(SequenceQueue * Q)
{
if(Q->front==Q->rear)
{
printf("This circle sequence queue is empty!\n ");
fflush(stdout);
return ERROR;
}
else
{
printf("This circle sequence queue is not empty!\n ");
fflush(stdout);
return OK;
}
}
/*入队*/
int enqueue(SequenceQueue *Q)
{
char c;
printf("Enter circle sequence queue front:%d\n",Q->front);
fflush(stdout);
printf("Enter circle sequence queue rear:%d\n",Q->rear);
fflush(stdout);
int flag=1;
if(Q->front==(Q->rear+1)%queuemaxsize)//尾指针加1是否产生假溢出
{
printf("The circle sequence queue is full !");
fflush(stdout);
return ERROR;
}
else
{
while(flag)
{
c=getchar();
if(c!='$')
{
Q->rear=(Q->rear+1)%queuemaxsize;//重新设置队尾指针 ,溢出取模后还在定义范围内
Q->data[Q->rear]=c;
}
else
{
flag=0;
printf("Elements enter circle sequence queue success !\n");
fflush(stdout);
}
}
}
return OK;
}
/*出队*/
int dequeue(SequenceQueue *Q)
{
printf("Out circle sequence queue front:%d\n",Q->front);
fflush(stdout);
printf("Out circle sequence queue rear:%d\n",Q->rear);
fflush(stdout);
if(!checkempty(Q))
{
printf("This circle sequence queue is empty!\n");
fflush(stdout);
return OK;
}
else
{
Q->front=(Q->front+1)%queuemaxsize;//头指针向后指,不在标记出队的存储空间,可以防止假溢出现象
printf("Dequeue element %2c\n",Q->data[Q->front]);
fflush(stdout);
dequeue(Q);
}
return ERROR;
}
int main(void){
SequenceQueue *sequencequeue;
initialqueue(&sequencequeue);//初始化
printf("Please enter the element to enter the circle sequence queue!\n ");
fflush(stdout);
enqueue(&sequencequeue);
printf("The out-of-queue elements are as follows...\n");
fflush(stdout);
dequeue(&sequencequeue);
return 0;
}
运行结果:
initial sequence queue success!
Please enter the element to enter the circle sequence queue!
Enter circle sequence queue front:49
Enter circle sequence queue rear:49
edrftgyhujik$
Elements enter circle sequence queue success !
The out-of-queue elements are as follows...
Out circle sequence queue front:49
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element e
Out circle sequence queue front:0
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element d
Out circle sequence queue front:1
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element r
Out circle sequence queue front:2
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element f
Out circle sequence queue front:3
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element t
Out circle sequence queue front:4
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element g
Out circle sequence queue front:5
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element y
Out circle sequence queue front:6
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element h
Out circle sequence queue front:7
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element u
Out circle sequence queue front:8
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element j
Out circle sequence queue front:9
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element i
Out circle sequence queue front:10
Out circle sequence queue rear:11
This circle sequence queue is not empty!
Dequeue element k
Out circle sequence queue front:11
Out circle sequence queue rear:11
This circle sequence queue is empty!
This circle sequence queue is empty!
【22】链队列
/*链队列*/
#include <stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<time.h>
#define true 1
#define false 0
typedef char QueueElementType;
typedef struct {
QueueElementType data;
struct LinkQueueNode *next;
}LinkQueueNode;
typedef struct{
LinkQueueNode *front,*rear;
}LinkQueue;
/*初始化链队列*/
int initiallistqueue(LinkQueue *Q)
{
/*将Q初始为空队列*/
Q->front=(LinkQueueNode*)malloc(sizeof(LinkQueueNode));
if(Q->front!=NULL)
{
Q->rear=Q->front;
Q->front->next=NULL;
printf("Link queue initial success!\n");
fflush(stdout);
return true;
}
else
{
printf("Link queue initial fail!\n");
fflush(stdout);
return false;
}
}
/*链队列入队算法*/
int enterlistqueue(LinkQueue*Q)
{
char c;
int flag=1;
LinkQueueNode*newnode;
while(flag)
{
c=getchar();
if(c!='$')
{
newnode=(LinkQueueNode*)malloc(sizeof(LinkQueueNode));
newnode->data=c;
newnode->next=NULL;
Q->rear->next=newnode;
Q->rear=newnode;
}
else
{
flag=0;
printf("Elements enter link queue success !\n");
fflush(stdout);
return true;
}
}
return false;
}
/*求队列的长度*/
int lengthlistqueue(LinkQueue*Q)
{
int count =0;
LinkQueueNode*p=Q->front->next;//指向第一个节点
while(p!=NULL)//也可以用尾指针rear来做判断条件
{
count++;
p=p->next;
}
return count;
}
/*遍历打印该链表*/
void printlinklist(LinkQueue*Q)
{
printf("print this link queue as follows...\n");
fflush(stdout);
LinkQueueNode*p=Q->front->next;
while(p)
{
printf("%3c",p->data);
fflush(stdout);
p=p->next;
}
printf("\n");
fflush(stdout);
}
/*链队列的出队操作*/
int deletelinkqueue(LinkQueue*Q)
{
LinkQueueNode*p;
if(Q->front==Q->rear)
{
printf("Link queue is empty!\n");
fflush(stdout);
return true;
}
else
{
p=Q->front->next;
Q->front->next=p->next;
if(Q->rear==p)
Q->rear=Q->front;
printf("Out element in link queue is %2c\n",p->data);
fflush(stdout);
deletelinkqueue(Q);
}
return false;
}
int main(void)
{
int start,end,t,second,minute,hour;
start = time(NULL);
LinkQueue*linkqueue;
initiallistqueue(&linkqueue);
printf("Please enter the element to enter the link queue!\n ");
fflush(stdout);
enterlistqueue(&linkqueue);
printf("The length of this link queue is %2d\n",lengthlistqueue(&linkqueue));
fflush(stdout);
printlinklist(&linkqueue);
printf("The out-of-queue elements are as follows...\n");
fflush(stdout);
deletelinkqueue(&linkqueue);
end = time(NULL);
t = difftime(end, start);
second = t % 60; //求出秒
minute = t / 60; //总分数
hour = minute / 60; //求出小时
minute = minute % 60; //求出分
printf("Take time is :%d h %d m %d s",hour,minute,second);
fflush(stdout);
//显示寻找最短路径所花费的时间
return 0;
}
运行结果:
Link queue initial success!
Please enter the element to enter the link queue!
azsxd@#fg%&*2531$
Elements enter link queue success !
The length of this link queue is 16
print this link queue as follows...
a z s x d @ # f g % & * 2 5 3 1
The out-of-queue elements are as follows...
Out element in link queue is a
Out element in link queue is z
Out element in link queue is s
Out element in link queue is x
Out element in link queue is d
Out element in link queue is @
Out element in link queue is #
Out element in link queue is f
Out element in link queue is g
Out element in link queue is %
Out element in link queue is &
Out element in link queue is *
Out element in link queue is 2
Out element in link queue is 5
Out element in link queue is 3
Out element in link queue is 1
Link queue is empty!
Take time is :0 h 0 m 14 s
【23】定长顺序串
/*定长顺序串
* 1.定长顺序串是将串设计成一种静态结构类型
* 2.串的存储分配是在编译时完成的*/
#include <stdio.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
#define MAXLEN 40
typedef struct {
char ch[MAXLEN];
int len;
} SString,*sstring;
/*构造串S*/
void StrAssign(SString *S)
{
printf("Please enter the char elements with end of char('$')\n");
fflush(stdout);
char c;
int i=0;
int flag = 1;
S->len=0;//一定要初始化
while(flag)
{
c=getchar();
if(c!='$')
{
S->ch[i]=c;
S->len++;
i++;
}
else
{
flag=0;
printf("Assign this string success!\n");
fflush(stdout);
printf("The length of this string is %2d\n",S->len);
fflush(stdout);
}
}
}
void StrAssignAnother(sstring S)
{
printf("Please enter the char elements in another string with end of char('$') \n");
fflush(stdout);
char c;
int i=0;
int flag = 1;
S->len=0;
while(flag)
{
c=getchar();
if(c!='$')
{
S->ch[i]=c;
S->len++;
i++;
}
else
{
flag=0;
printf("Assign this string success!\n");
fflush(stdout);
printf("The length of this string is %2d\n",S->len);
fflush(stdout);
}
}
}
/*插入函数*/
/*在串S中下标为pos的字符之前插入串t*/
int StrInsert(SString *S, int pos, sstring t) {
int i;
if(pos < 0 || pos > S->len) return ERROR;
printf("%2d . %2d\n",S->len ,t->len);
if(S->len + t->len <= MAXLEN)
{
for (i = S->len+t->len - 1; i >=t->len + pos; i--)
{
S->ch[i] = S->ch[i - t->len] ;
}
for (i = 0; i < t->len; i++)
{
S->ch[pos + i] = t->ch[i];
}
S->len = S->len + t->len;
}
else if(pos + t->len <= MAXLEN)
{
for(i = MAXLEN - 1; i >=t->len+ pos-1; i-- )
{
S->ch[i]=S->ch[i - t->len];
}
for(i = 0; i < t->len; i++)
{
S->ch[pos + i] = t->ch[i];
}
S->len = MAXLEN;
}
else {
for(i = 0; i < MAXLEN - pos; i++)
{
S->ch[pos + i] = t->ch[i];
}
S->len = MAXLEN;
}
return OK;
}
/*删除函数*/
/*在串S中删除从下标pos起len个字符*/
/*S->len-1表示最后一个下标,S->len-1-pos表示从最后一个下标到下标pos间的元素个数*/
int StrDelete(SString *S, int pos, int len) {
int i;
if(pos < 0 || len < 1 || pos > (S->len - len)) {
return ERROR; //从pos起最多删除S->len-1-pos+1 个字符
}
for(i = pos +len; i < S->len; i++) {
S->ch[i - len] = S->ch[i];
}
S->len = S->len - len;
return OK;
}
/*串复制函数*/
/*将串t的值复制到串S中*/
void StrCopy(SString *S, SString t) {
int i;
for(i = 0; i < t.len; i++) {
S->ch[i] = t.ch[i];
}
S->len = t.len;
}
/*判空函数*/
int StrEmpty(SString S) {
if (S.len == 0) return 1;
else return 0;
/*return!(s.len)*/
}
/*串比较函数*/
/*比较规则与字符串的比较相同*/
int StrCompare(SString S, SString t) {
int i;
for(i = 0; i < S.len && i < t.len; i++) {
if(S.ch[i] != t.ch[i]) {
return(S.ch[i] - t.ch[i]);
}
}
return(S.len - t.len); /*包含三种情况*/
}
/*求串长函数*/
int StrLength(SString*S) {
return S->len;
}
/*清空函数*/
void StrClear(SString *S) {
S->len = 0;
}
/*连接函数*/
/*将串连接在串S的后面,*/
int StrCat(SString *S, sstring t) {
int i,flag;
if(S->len + t->len <= MAXLEN) { /*连接后串长小于MAXLEN,正常插入*/
for(i = S->len; i < S->len + t->len; i++) {
S->ch[i] = t->ch[i - S->len];
}
S->len += t->len;
flag = 1;
}
else if(S->len < MAXLEN) { /*连接后串长大于MAXLEN,t部分被舍去*/
for (i = S->len; i < MAXLEN; i++) {
S->ch[i] = t->ch[i - S->len];
}
S->len = MAXLEN;
}
else {
flag = 0;
}
return flag; //flag = 0表示非正常连接,t部分被舍弃或全部被舍弃
}
/*求字串函数*/
/*将串S中下标pos起len个字符串复制到sub中*/
int SubString(SString *sub, sstring S, int pos, int len) {
int i;
if(pos < 0 || pos >S->len - 1 || len <1 || len > S->len - pos) {
sub->len = 0;
return OK;
}
else {
for(i = 0; i < len; i++) {
sub->ch[i] = S->ch[pos + i];
}
sub->len = len;
return OK;
}
}
/*定位函数即Brute-Force算法*/
/*求主串S的pos位置起,串t第一次出现的位置,成功返回位置序号,失败返回-1*/
int StrIndex(SString S, int pos, sstring t) {
int j, i, start;
if(t->len == 0) { //t为空串时,是任意串的匹配
return -1;
}
start = pos; i = start; j = 0; //主串从pos开始,t从头开始
while(i < S.len && j < t->len) {
if(S.ch[i] == t->ch[j]) {
i++; j++;
}
else {
start++; /*当前对应字符不等时回溯*/
i = start;
j = 0; /*回溯,主串起始位置+1,t从头开始*/
}
if(j > t->len) {
return start; /*匹配成功,返回匹配起始位置*/
}
else return -1; /*匹配不成功,返回-1*/
}
}
/*打印串的算法*/
void StrPrint(SString *S)
{
printf("Print the element in this string as show following...\n");
fflush(stdout);
int i;
for(i=0;S->ch[i]!='\0';i++)
{
printf("%2c",S->ch[i]);
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
void StrPrintAnother(sstring S)
{
printf("Print the element of another string as show following...\n");
fflush(stdout);
int i;
for(i=0;S->ch[i]!='\0';i++)
{
printf("%2c",S->ch[i]);
fflush(stdout);
}
printf("\n");
fflush(stdout);
}
int main(void)
{
int pos=3;
SString *S;
sstring S1;
StrAssign(&S);
StrPrint(&S);
printf("Please input another String :\n");
fflush(stdout);
StrAssignAnother(S1);
StrPrintAnother(S1);
StrInsert(&S,pos, S1);
StrPrint(&S);
StrDelete(&S, 5, 2);
StrPrint(&S);
return 0;
}
运行结果:
Please enter the char elements with end of char('$')
azsxdcf$
Assign this string success!
The length of this string is 7
Print the element in this string as show following...
a z s x d c f
Please input another String :
Please enter the char elements in another string with end of char('$')
1234$
Assign this string success!
The length of this string is 5
Print the element of another string as show following...
1 2 3 4
7 . 5
Print the element in this string as show following...
a z s
1 2 3 4 x d c f
Print the element in this string as show following...
a z s
1 4 x d c f c f
【24】堆串
/*堆串
* 1.字符串包括串名和串值两部分,串值采用堆栈存储方法存储,串名采用字符表存储
* 2.堆栈存储方法:以一组地址连续的存储单元顺序存放串中的字符,但他们的存储空间是在程序执行过程中动态分配的
* 3.系统将一个连续的,容量很大的存储空间作为字符串的可用空间
* 4.每当建立一个新串时,系统就会从这个空间中分配一个大小和字符串长度相同的空间用于存储新串的串值
* 5.串名符号表:所有串名的存储映像构成一个符号表,借助此结构可在串名和串值之间建立一个对应关系,称为串名的存储映像
* 6.出自weixin_33923148(堆串)*/
#include<stdio.h>
#include<stdlib.h>
typedef struct{
char *ch;
int len;
}HString;
/*函数声明如下*/
HString *InitHStr();//初始化
int HStrAssign(HString *S, char *chars);//赋值
int HStrInsert(HString *s, int pos, HString *t);//插入
int HStrDelete(HString *s, int pos, int len);//删除
int HStrCat(HString *s, HString *t);//连接
int SubHString(HString *t, HString *s, int pos, int len);//子串
void HStrPrint(HString *s);//打印堆串
int main(){
HString *h = InitHStr();//初始化空堆串h
char strA[]="hello world!";//初始化字符数组
//赋值
HStrAssign(h,strA);
HStrPrint(h);
printf("\n");
//插入
HStrInsert(h,7,h);
HStrPrint(h);
printf("\n");
//删除
HStrDelete(h,1,6);
HStrPrint(h);
printf("\n");
//连接
char strB[] = " and hello C!";
HString *h2 = InitHStr();
HStrAssign(h2,strB);
HStrCat(h,h2);
HStrPrint(h);
printf("\n");
//子串
HString *h3 = InitHStr();
SubHString(h3,h,7,5);
HStrPrint(h);
printf("\n");
HStrPrint(h3);
printf("\n");
return 0;
}
/*初始化
* 构造空堆串
* */
HString *InitHStr()
{
HString *p = (HString *)malloc(sizeof(HString));
p->ch = NULL;
p->len = 0;
return p;
}
/*赋值
* 将chars指向的字符数组赋值给S*/
int HStrAssign(HString *S, char *chars)
{
int i = 0;
if (chars == NULL || S == NULL) return 0;//字符数组或堆串为空,直接退出
while (chars[i] != '\0') i++;//读至字符数组的末端,记录chars字符串的长度
S->len = i;
if (S->len != 0)
{
if (S->ch != NULL) free(S->ch);//要为ch分配存储空间
S->ch = (char*)malloc((S->len + 1) * sizeof(char));//为ch分配与要读入字符串大一的存储空间,因为有'\0'
if (S->ch == NULL) return 0;
for (i = 1; i <= S->len; i++)
S->ch[i] = chars[i - 1];//依次读入
}
else
{
S->ch = NULL;
}
return 1;
}
/*插入
* 在堆串s中的pos位置中插入堆串t*/
int HStrInsert(HString *s, int pos, HString *t)
{
int i;
char *temp;
if (s == NULL || s->ch == NULL || t->ch == NULL || pos > s->len || pos < 1)
return 0;
temp = (char*)malloc((s->len + t->len + 1) * sizeof(char));//开辟插入后的空间
if(temp == NULL) return 0;
for (i = 1; i < pos; i++)//插入点之前的字符串,就复制过来
temp[i] = s->ch[i];
for (i = pos; i < pos + t->len; i++)//要插入的字符串,紧接着pos插入t
temp[i] = t->ch[i - pos + 1];
for (i = pos + t->len; i <= s->len + t->len; i++)//剩余的原字符串,原先在pos的位置都插在pos+t->len的位置
temp[i] = s->ch[i - t->len];
free(s->ch);
s->ch = temp;
s->len = s->len + t->len;
return 1;
}
/*删除
* 在堆串s中删除pos至len的字符*/
int HStrDelete(HString *s, int pos, int len)
{
int i;
char *temp;
if (s == NULL || s->ch == NULL || len < 0 || pos < 1 || len > s->len - pos + 1)
return 0;
temp = (char*)malloc((s->len - len + 1) * sizeof(char));
if(temp == NULL) return 0;
for(i = 1; i < pos; i++)
temp[i] = s->ch[i];
for(i = pos; i < s->len - len; i++)
temp[i] = s->ch[i + len];
free(s->ch);
s->ch = temp;
s->len = s->len - len;
return 1;
}
/*将t复制到s后面*/
int HStrCat(HString *s, HString *t)
{
int i;
if(s == NULL || s->ch == NULL || t->ch == NULL)
return 0;
s->ch = (char*)realloc(s->ch, (s->len + t->len + 1) * sizeof(char));//在malloc的基础上重新分配存储空间,s->ch的值不变
if(s->ch == NULL) return 0;
for(i = s->len + 1; i <= t->len + s->len; i++)
s->ch[i] = t->ch[i - s->len];
s->len = s->len + t->len;
return 1;
}
/*求堆栈s的pos至len的字串t*/
int SubHString(HString *t, HString *s, int pos, int len)
{
int i;
if(t == NULL || s->ch == NULL || len < 0 || len > s->len - pos + 1 || pos < 1 || pos > s->len)
return 0;
t->len = len;
if(t->ch != NULL) free(t->ch);
t->ch = (char*)malloc((t->len + 1) * sizeof(char));
if(t->ch == NULL) return 0;
for(i = 1; i <= t->len; i++){
t->ch[i] = s->ch[pos + i - 1];
}
return 1;
}
/*打印堆串*/
void HStrPrint(HString *s)
{
int i;
for(i = 1; i <= s->len; i++)
printf("%c", s->ch[i]);
}
运行结果:
hello world!
hello hello world!world!
hello world!world
hello world!world and hello c!
hello world!world and hello c!
World
【25】块链串
/*块链串*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BLOCKSIZE 4
#define true 1
#define flase 0
char blank='#';//用于填补空余
typedef struct{
char ch[BLOCKSIZE];
struct Block * next;
}Block;
typedef struct{
Block * head,*tail;
int len;
}BlockLinkString;
void initialblocklinkstring(BlockLinkString * T)
{
(*T).len=0;
(*T).head=NULL;
(*T).tail=NULL;
printf("initial this block/chunk link string success!\n");
fflush(stdout);
}
int blocklinkstring(BlockLinkString*T,char*chars)
{
int i,j,k,l;
Block*p,*q;
i=strlen(chars);
if(!i||strchr(chars,blank)) return 0;
(*T).len=i;
j=i/BLOCKSIZE;//j为块链的结点数,即为块的个数
if(i%BLOCKSIZE) j++;
for(k=0;k<j;k++)
{
p=(Block*)malloc(sizeof(Block));
if(!p) return 0;
if(k==0) (*T).head=q=p;
else
{
q->next=p;
q=p;
}
for(l=0;l<BLOCKSIZE&&*chars;l++)
{
*(q->ch+l)=*chars++;//*(q->ch+l)等同于指向ch[l]的地址所对应的存储单元
}
if(!*chars)
{
(*T).tail=q;
q->next=NULL;
for(;l<BLOCKSIZE;l++)
{
*(q->ch+l)=blank;
}
}
}
printf("Assign block link string success!\n");
fflush(stdout);
return 1;
}
/*返回串长*/
int blocklinkstringlength(BlockLinkString *T)
{
return T->len;
}
// 由串S复制到串T(连填补空余的字符一块拷贝)
int blocklinkStringCopy(BlockLinkString *T,BlockLinkString* S)
{
Block *h=S->head,*p,*q;
(*T).len=S->len;
if(h)
{
p=(*T).head=(Block*)malloc(sizeof(Block));
*p=*h; // 复制1个结点
h=h->next;
while(h) //没到队尾,继续复制块
{
q=p;
p=(Block*)malloc(sizeof(Block));
q->next=p;
*p=*h;
h=h->next;
}
p->next=NULL;
(*T).tail=p;
return 1;
}
else
return 0;
}
void BLStringPrint(BlockLinkString *T)
{
int i=0,j;
Block *h;
h=T->head;
while(i<T->len)
{
for(j=0;j<BLOCKSIZE;j++)
if(h->ch[j]!='#')
{
printf("%2c",h->ch[j]);
fflush(stdout);
i++;
}
h=h->next;
}
printf("\n");
fflush(stdout);
}
int SubString(BlockLinkString *Sub, BlockLinkString * S,int pos,int len)
{
Block *p,*q;
int i,k,n,
flag=1; //用来标志复制是否完成,1完成,0未完成
if(pos<1||pos>S->len||len<0||len>S->len-pos+1)
return 0;
n=len/BLOCKSIZE;
if(len%BLOCKSIZE)
n++; // n为块的个数
p=(Block*)malloc(sizeof(Block));
Sub->head=p; // 生成空的Sub串
for(i=1;i<n;i++)
{
q=(Block*)malloc(sizeof(Block));
p->next=q;
p=q;
}
p->next=NULL;
Sub->tail=p;
Sub->len=len;
for(i=len%BLOCKSIZE; i<BLOCKSIZE; i++)
*(p->ch+i)=blank; // 填充Sub尾部的多余空间
q=Sub->head; // q指向Sub串即将复制的块
i=0; // i指示即将复制的字符在块中的位置
p=S->head; // p指向S串的当前块
n=0; // n指示当前字符在串中的序号
while(flag)
{
for(k=0; k<BLOCKSIZE; k++) // k指示当前字符在块中的位置
if(*(p->ch+k)!=blank)
{
n++;
if(n>=pos&&n<=pos+len-1) // 复制
{
if(i==BLOCKSIZE)
{ // 到下一块
q=q->next;
i=0;
}
*(q->ch+i)=*(p->ch+k);
i++;
if(n==pos+len-1) // 复制结束
{
flag=0;
break;
}
}
}
p=p->next;
}
return 1;
}
int main(void)
{
char *s1="qwertyuiop";
BlockLinkString *t;
BlockLinkString *sub;
initialblocklinkstring(&t);
initialblocklinkstring(&sub);
blocklinkstring(&t,s1);
printf("The length of the one block link string is %2d\n ",blocklinkstringlength(&t));
fflush(stdout);
BLStringPrint(&t);
printf("The Substring of the one block link string as show following...\n ");
fflush(stdout);
SubString(&sub,&t,2,7);
BLStringPrint(&sub);
}
运行结果:
initial this block/chunk link string success!
initial this block/chunk link string success!
Assign block link string success!
The length of the one block link string is 10
q w e r t y u i o p
The Substring of the one block link string as show following...
w e r t y u
【26】稀疏矩阵的转置(顺序)
/*稀疏矩阵*/
/*稀疏矩阵的顺序存储
* 大多数元素为零的矩阵
* 非零元个数低于总数的30%*/
#include<stdio.h>
#include<stdlib.h>
#define Max 100
typedef int ElemType;
typedef struct{
int row,col;//行号,列号
ElemType val;//元素值
}Triple;
typedef struct{
Triple data[Max];//存储的三元数组
int m,n,len;//行数,列数,非零元个数
}ThreeSparseMatrix;
/*初始化稀疏矩阵*/
void initialSparseMatrix(ThreeSparseMatrix *M)
{
M->m=0;//零行
M->n=0;//零列
M->len=0;//零个非零元
printf("Initial Sparse Matrix success!\n");
fflush(stdout);
}
/*输入稀疏矩阵*/
void inputSparseMatrix(ThreeSparseMatrix * M,int m,int n){
int k = 0;
int row,col;
ElemType val;
M->m=m;//行数
M->n=n;//列数
printf("Please input Triple:Format is (row column value):end of(0,0,0)\n");
fflush(stdout);
scanf("%d,%d,%d",&row,&col,&val);
while(row!=0)
{
k++;
M->data[k].row=row;
M->data[k].col=col;
M->data[k].val=val;
printf("input next Triple:");
fflush(stdout);
scanf("%d,%d,%d",&row,&col,&val);
}
M->len=k;//非零元的个数
}
/*输出稀疏矩阵*/
void outputSparseMatrrx(ThreeSparseMatrix * M)
{
int i;
printf("(");
fflush(stdout);
for(i=1;i<M->len;i++)
{
printf("(%d,%d,%d)",M->data[i].row,M->data[i].col,M->data[i].val);
fflush(stdout);
}
if(M->len!=0)
{
printf("(%d,%d,%d)",M->data[i].row,M->data[i].col,M->data[i].val);
fflush(stdout);
}
printf(")\n");
fflush(stdout);
}
/*稀疏矩阵转置*/
ThreeSparseMatrix* TransposeSparseMatrix(ThreeSparseMatrix* M)
{
int m, n, len;
int k, i, col;
ThreeSparseMatrix* S; //用S暂存转置后的结果
S = malloc(sizeof(ThreeSparseMatrix));
initialSparseMatrix(S);
m = M->m;
n = M->n;
len = M->len;
S->m = n; //M的列数作为S的行数CrossNode
S->n = m; //M的行数作为S的列数
S->len = len;
if (len == 0) //若是零矩阵
return S;
k = 1; //用k指示S->sm数组的下标
for (col = 1; col <= n; col++) //以列为循环量,扫描所有三元组,并将对应的行列号互换
{
for (i = 1; i <= len; i++)
{
if (M->data[i].col == col)
{
S->data[k].row = col;
S->data[k].col = M->data[i].row;
S->data[k].val = M->data[i].val;
k++;
}
}
}
return S;
}
int main(void)
{
int m=4;
int n=4;
ThreeSparseMatrix M;
initialSparseMatrix(&M);
inputSparseMatrix(&M, m, n);
outputSparseMatrrx(&M);
printf("The Transpose Matrix as show follows\n");
fflush(stdout);
outputSparseMatrrx(TransposeSparseMatrix(&M));
}
运行结果:
Initial Sparse Matrix success!
Please input Triple:Format is (row column value):end of(0,0,0)
1,1,2
input next Triple:1,2,3
input next Triple:4,2,9
input next Triple:2,4,6
input next Triple:1,2,5
input next Triple:0,0,0
((1,1,2)(1,2,3)(4,2,9)(2,4,6)(1,2,5))
The Transpose Matrix as show follows
Initial Sparse Matrix success!
((1,1,2)(2,1,3)(2,4,9)(2,1,5)(4,2,6))
【27】函数的积分求解
#include <stdio.h>
#include <stdlib.h>
#include <math.h>//引入sin x,cos x,e^x的库
//使用指向函数的指针变量来复用一个通用函数
int main()
{
int i,j,k,n,m;
float res;
float (*fun)(float);//定义指向函数的指针变量
float integral (float a,float b,float (*fun)(float),int n);//n为将积分区间(b-a)分成n等分,当n的值越大的时候结果越精确,数学上的定义是取无穷大
float fsin(float);//sin x函数的声明
float fcos(float);//cos x函数的声明
float fexp(float);//e^x 函数的声明
printf ("please input integral lower limit\n");
fflush(stdout);
scanf ("%d",&m);
printf ("please input integral upper limit\n");
fflush(stdout);
scanf ("%d",&n);
printf("please input the whole f(x)\n");
printf("1.sin(x) 2.cos(x) 3.e^x\n");
fflush(stdout);
scanf ("%d",&i);
switch(i)
{
case 1:
fun=fsin;//函数地址(入口)交给指针变量,灵活性强
break;
case 2:
fun=fcos;
break;
case 3:
fun=fexp;
}
res=(fun)(2.00);
//printf("xxxx=%f\n",res);
printf ("caculate the result is \n");
res=integral(m,n,fun,200000);
printf("res=%f",res);
return 0;
}
float fsin(float x)
{
// printf("fsinx=%f\n",x);
return sin(x);
}
float fcos(float x)
{
//printf("fcosx=%f\n",x);
return cos(x);
}
float fexp(float x)
{
//getchar();
//printf("fexp=%f\n",x);
return exp(x);
}
float integral(float a,float b,float (*fun)(float),int n)
{
//矩形法计算,定积分转换为连续求和的形式
int i=0;
float x=a,s=0;
float h=(b-a)/n;
for (i=1;i<=n;i++)
{
x=x+h;
s=s+((*fun)(x)*h);
}
return s;
}
运行结果:
please input integral lower limit
2
please input integral upper limit
4
please input the whole f(x)
1.sin(x) 2.cos(x) 3.e^x
1
caculate the result is
res=0.235111
【28】读文件txt中的数据
/*将文件txt的数据放到数组中*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
float a[401][2];
int i,j;
FILE*fp=fopen("D:\\EclipseForCandC++\\Cworkspace\\f3.txt","r"); //打开文件
if(fp==NULL)
{
printf("no file");
return 0;
}
for(i=0;i<401;i++)
{
for(j=0;j<2;j++)
{
fscanf(fp,"%f",&a[i][j]);/*每次读取一个数,fscanf函数遇到空格或者换行结束*/
}
fscanf(fp,"\n");
}
fclose(fp);
for(i=0;i<401;i++)
{
for(j=0;j<2;j++)
{
printf("%.2f\t",a[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
0.00 1538.40
0.50 1540.80
1.00 1543.30
1.50 1545.70
2.00 1548.20
2.50 1550.60
3.00 1553.10
3.50 1555.60
4.00 1558.00
4.50 1560.50
5.00 1563.00
5.50 1565.50
6.00 1568.00
6.50 1570.50
7.00 1573.00
7.50 1575.50
8.00 1578.00
8.50 1580.60
9.00 1583.10
9.50 1585.60
10.00 1588.20
10.50 1590.70
11.00 1593.30
11.50 1595.90
12.00 1598.40
12.50 1601.00
13.00 1603.60
【29】指针数组形式的链式三元组
/*链式三元组结点类型*/
#include<stdio.h>
#include<stdlib.h>
#define ElemType int
#define MaxRow 100
/*定义三元组结点类型*/
struct TripleNode
{
int row,col;
ElemType val;
struct TripleNode *next;
};
typedef struct{
struct TripleNode * LA[MaxRow];//存储单链表行的数组指针,指向这一行的元素结点,初始值为1
int m,n,len;
}LinkThreeSparseMatrix;
/*初始化链式三元组*/
void initialLinkTriple(LinkThreeSparseMatrix *M)
{
int i;
M->m=0;
M->n=0;
M->len=0;
for(i=1;i<MaxRow;i++)
{
M->LA[i]=NULL;
}
printf("initial link three sparse matrix success!\n");
fflush(stdout);
}
/*创建链式三元组*/
void createLinkTriple(LinkThreeSparseMatrix * M,int m,int n)
{
int k=0;
int row,col;
ElemType val;
M->m=m;//行数
M->n=n;//列数
printf("Please input Triple:Format is (row,column,value):end of(0,0,0)\n");
fflush(stdout);
scanf("%d,%d,%d",&row,&col,&val);
while(row!=0)//结束
{
k++;
struct TripleNode * nowp,*newp;//nowp指针找到需要插入的位置,newp生成新的三元组结点
newp=malloc(sizeof(struct TripleNode));
newp->row=row;//行
newp->col=col;//列
newp->val=val;//值
newp->next=NULL;//结点空域
nowp=M->LA[row];//让nowp指向数组指针+row的偏移量
if(nowp==NULL)//初始化全部为空,所以这里直接进入第row行进行指向新的结点
M->LA[row]=newp;//指向新生成的节点
else
{
while(nowp->next!=NULL)//nowp指向LA[MaxRow]指针数组,而这个指针数组指向这行的第一个结点元素,如果这个位置已经有节点插入了,就把当前结点的next域赋值给当前指针nowp
nowp=nowp->next;//找到当前行的最后一个结点,用当前指针标记
nowp->next=newp;//当前结点的next域指向新的结点,完成插入
}
printf("input next Triple:");
fflush(stdout);
scanf("%d,%d,%d",&row,&col,&val);
}
M->len=k;
}
void outputLinkTriple(LinkThreeSparseMatrix * M)
{
int i;
struct TripleNode * p;
printf("(");
fflush(stdout);
for(i=1;i<=M->m;i++)
{
for(p=M->LA[i];p!=NULL;p=p->next)
{
if((i==M->m)&&p->next == NULL)
{printf("(%d,%d,%d)",p->row,p->col,p->val);
fflush(stdout);}
else
{printf("(%d,%d,%d),",p->row,p->col,p->val);
fflush(stdout);}
}
}
printf(")\n");
}
int main(void)
{
int m=10;
int n=10;
LinkThreeSparseMatrix M;
initialLinkTriple(&M);
createLinkTriple(&M,m,n);
outputLinkTriple(&M);
}
运行结果:
initial link three sparse matrix success!
Please input Triple:Format is (row,column,value):end of(0,0,0)
1,1,3
input next Triple:1,4,5
input next Triple:2,3,2
input next Triple:3,1,1
input next Triple:0,0,0
((1,1,3),(1,4,5),(2,3,2),(3,1,1),)
【30】十字链表
/*十字链表实现三元组*/
#include<stdio.h>
#include<stdlib.h>
#define ElemType int
#define MaxRow 100//最大列数
#define MaxCol 100//最大行数
/*十字链表实现三元组*/
struct CrossNode
{
int row,col;//行号,列号
ElemType val;//元素值
struct CrossNode *down,*right;//定义指向下方和右方的节点
};
typedef struct
{
int m,n,c;//行数,列数,非零元个数
struct CrossNode * UP[MaxCol];//指向列的数组指针 ,下标从1开始
struct CrossNode * LEFT[MaxRow];//指向行的数组指针,下表从1开始
}CrossLinkThreeTriple;//定义十字链表的结构体
/*初始化十字链表*/
void initialCLTriple(CrossLinkThreeTriple * M)
{
int i;
M->n=0;
M->m=0;
M->c=0;
for(i=1;i<=MaxCol;i++)
{
M->UP[i]=NULL;
}
for(i=1;i<=MaxRow;i++)
{
M->LEFT[i]=NULL;
}
printf("initial cross link three sparse matrix success!\n");
fflush(stdout);
}
/*创建十字链表*/
void creatCLTriple(CrossLinkThreeTriple * M,int m,int n)
{
int k=0;
int row,col;
ElemType val;
M->m=m;//行数
M->n=n;//列数
printf("Please input Triple:Format is (row,column,value):end of(0,0,0)\n");
fflush(stdout);
scanf("%d,%d,%d",&row,&col,&val);
while(row!=0)//结束
{
k++;
struct CrossNode * nowp,*newp;//nowp指针找到需要插入的位置,newp生成新的三元组结点
newp=malloc(sizeof(struct CrossNode));
newp->row=row;//行
newp->col=col;//列
newp->val=val;//值
newp->right=newp->down=NULL;//结点空域,向上向右指向域为空
nowp=M->LEFT[row];//让nowp指向数组指针+row的偏移量[搜索行]
if(nowp==NULL)//初始化全部为空,所以这里直接进入第row行进行指向新的结点
M->LEFT[row]=newp;//指向新生成的节点(结论)
else
{
while(nowp->right!=NULL)//nowp指向LA[MaxRow]指针数组,而这个指针数组指向这行的第一个结点元素,如果这个位置已经有节点插入了,就把当前结点的right域赋值给当前指针nowp
nowp=nowp->right;//找到当前行的最后一个结点,用当前指针标记
nowp->right=newp;//当前结点的next域指向新的结点,完成插入(结论)
}
nowp=M->UP[col];//[搜索列]
if(nowp==NULL)
M->UP[col]=newp;//(结论)
else
{
while(nowp->down!=NULL)
nowp=nowp->down;
nowp->down=newp;//(结论)
}
printf("input next Triple:");
fflush(stdout);
scanf("%d,%d,%d",&row,&col,&val);
}
M->c=k;
}
void outputCLTriple(CrossLinkThreeTriple * M)
{
int i;
struct CrossNode *p;
printf("(");
fflush(stdout);
for(i=1;i<=M->m;i++)//行搜索,也可列搜索
{
for(p=M->LEFT[i];p!=NULL;p=p->right)//以行遍历
{
if((i==M->m)&&(p->right=NULL))//行的 最后一个元素
{
printf("(%d,%d,%d)",p->row,p->col,p->val);
fflush(stdout);}
else
{
printf("(%d,%d,%d),",p->row,p->col,p->val);
fflush(stdout);
}
}
}
printf(")");
fflush(stdout);
}
int main(void)
{
int m=5;
int n=5;
CrossLinkThreeTriple M;
initialCLTriple(&M);
creatCLTriple(&M,m,n);
outputCLTriple(&M);
}
运行结果:
initial cross link three sparse matrix success!
Please input Triple:Format is (row,column,value):end of(0,0,0)
1,1,2
input next Triple:1,3,5
input next Triple:2,1,4
input next Triple:4,2,1
input next Triple:3,0,5
input next Triple:2,2,5
input next Triple:0,0,0
((1,1,2),(1,3,5),(2,1,4),(2,2,5),(3,0,5),(4,2,1),)
【31】广义链表
/*广义表*/
#include<stdio.h>
#include<stdlib.h>
typedef char ElemType; //ElemType类型定义
struct GNode //广义表结点类型定义
{
int tag; //标志域
union
{
ElemType data; //值域
struct GNode* sublist; //子表的表头指针域
};
struct GNode* next; //指向后继结点的指针域
};
//1、建立广义表
//假定广义表的元素类型ElemType为字符类型char,每个单元素的值被限定为英文字母,
//输入格式为: (a,(#),b,(d,(e)));
//整个表最后以分号作为结束符,#表示空表
//建立广义表需要进行子表递归和后继表递归
void CreateGList_char(struct GNode** GL)
{
char ch;
scanf("%c", &ch);
if (ch == '#') //若输入为空格,则置表头指针为空
*GL = NULL;
else if (ch == '(') //若输入为左括号则建立由*GL所指向的子表结点并递归构造子表
{
*GL = malloc(sizeof(struct GNode));
(*GL)->tag = 1;
CreateGList_char(&((*GL)->sublist)); //递归
}
else //若输入为字符则建立由*GL所指向的单元素结点
{
*GL = malloc(sizeof(struct GNode));
(*GL)->tag = 0;
(*GL)->data = ch;
}
scanf("%c", &ch); //此处读入的字符必为逗号、括号或分号
if (*GL == NULL); //若*GL为空,什么都不做
else if (ch == ',')//若输入为逗号则递归构造后续表
CreateGList_char(&((*GL)->next)); //递归
else if (ch == ')' || ch == ';') //若输入为右括号或分号则置*GL的后继指针域为空
(*GL)->next = NULL;
}
//2、打印输出广义表
//打印输出上面的广义表同样需要递归子表和递归后继表
void PrintfGList_char(struct GNode* GL)
{
if (GL->tag == 1) //表结点的处理情况
{
printf("%c", '('); //先输出左括号,作为开始符号
fflush(stdout);
if (GL->sublist == NULL) //若子表为空
{printf("%c", '#');
fflush(stdout);}
else
PrintfGList_char(GL->sublist); //递归
printf("%c", ')'); //当一个子表输出结束后,输出一个右括号终止符
fflush(stdout);
}
else //单元素结点的处理情况
{printf("%c", GL->data);
fflush(stdout);}
if (GL->next != NULL) //若结点还有后继表,则递归输出
{
printf("%c", ','); //先输出逗号分隔符
fflush(stdout);
PrintfGList_char(GL->next); //递归
}
}
//3、求广义表的长度
//广义表中,同一层次的每个结点是通过next域链接起来的,所以可把它看做是由next域链接起来的单链表。
//这样求广义表的长度就是求单链表的长度
//如单链表非空,其长度等于1加其后继单链表的长度,若单链表为空,则长度为0,这是递归的终止条件
int LenthGList(struct GNode* GL)
{
if (GL != NULL)
return 1 + LenthGList(GL->next);
else
return 0;
}
//4、求广义表的深度
//广义表深度的递归定义是它等于所有子表中的最大深度加1,若一个表为空或仅由单元素组成,则深度为1
int DepthGList(struct GNode* GL)
{
int max = 0; //所有子表中最大深度,初始值为0
while (GL != NULL)
{
if (GL->tag == 1)
{
int dep = DepthGList(GL->sublist); //递归调用求出一个子表的深度,用dep表示任一子表的深度
if (dep > max)
max = dep; //让max始终为同一层所求过的子表中深度的最大值
}
GL = GL->next; //使GL指向同一层的下一个结点
}
return max + 1; //返回表的深度
}
//主函数
int main(void)
{
struct GNode* gl;
printf("Input Generalized list,format is: (a,(#),b,(d,(e))); \n");
fflush(stdout);
CreateGList_char(&gl);
printf("Print Generalized list:\n");
fflush(stdout);
PrintfGList_char(gl);
fflush(stdout);
printf("\n");
fflush(stdout);
printf("The length of this generalized list is\t");
fflush(stdout);
printf("%d\n", LenthGList(gl->sublist));
fflush(stdout);
printf("The depth of this generalized list is\t");
fflush(stdout);
printf("%d\n", DepthGList(gl->sublist));
fflush(stdout);
return 0;
}
运行结果:
Print Generalized list,format is: (a,(#),b,(d,(e)));
((#),(e),(a,(b,c,d)));
Print Generalized list:
((#),(e),(a,(b,c,d)))
The length of this generalized list is 3
The depth of this generalized list is 3
【32】二叉树的遍历
#include<stdio.h>
#include<stdlib.h>
#define QueueMaxSize 20 //定义队列数组长度
#define StackMaxSize 10 //定义栈数组长度
typedef char ElemType; //定义ElemType类型
struct BTreeNode //结点类型定义
{
ElemType data; //值域
struct BTreeNode* left; //左指针域
struct BTreeNode* right; //右指针域
};
//1、初始化二叉树
void InitBTree(struct BTreeNode** BT)
{
*BT = NULL; //把树根指针置空
printf("initial BTree success!\n");
}
//2、建立二叉树,采用广义表表示的输入法,如:A(B(C,D),E(,F(G)))
void CreateBTree(struct BTreeNode** BT, char* string)
{
struct BTreeNode* p;
struct BTreeNode* s[StackMaxSize]; //定义s数组作为存储根结点的指针的栈使用(定义指向树节点的指针数组)
int top = -1; //栈顶指针置为-1,表示空栈
int k; //k作为处理结点的标志,k=1处理左子树,k=2处理右子树
int i = 0; //用i扫描数组string中存储的二叉树广义表字符串,初值为0
*BT = NULL; //把树根指针置空,即从空树开始建立二叉树
while (string[i])
{
switch (string[i])
{
case ' ':;break;//如果是空字串,则什么都不做
case '('://开始插入新的左子树
{
if (top == StackMaxSize - 1)//判断指针数组是否满
{
printf("Stack too small!\n");
exit(1);
}
top++;//s[0];
s[top] = p;//标记结点为根节点
k = 1;//左子树
break;
}
case ')':
{
if (top == -1)//判断指针数组是否为空
{
printf("binary tree that format is generalized table take error!\n");
exit(1);
}
top--;//右子树以存储完毕,回溯上一根节点
break;
}
case ',':k = 2;break;//进行右子树存储
default:
{
p = malloc(sizeof(struct BTreeNode));
p->data = string[i];
p->left = p->right = NULL;
if (*BT == NULL)
*BT = p;
else
{
if (k == 1)
s[top]->left = p;
else
s[top]->right = p;
}
}
}//switch end
i++;
}//while end
}
//3、检查二叉树是否为空
int BTreeEmpty(struct BTreeNode* BT)
{
if (BT == NULL)
return 1;
else
return 0;
}
//4、求二叉树深度
int BTreeDepth(struct BTreeNode* BT)
{
if (BT == NULL)
return 0;
else
{
int dep1 = BTreeDepth(BT->left); //计算左子树深度
int dep2 = BTreeDepth(BT->right);//计算右子树深度
if (dep1 > dep2)
return dep1 + 1;
else
return dep2 + 1;
}
}
//5、从二叉树中查找值为x的结点,若存在则返回元素存储位置,否则返回空值(算法类似于前序遍历)
ElemType* FindBTree(struct BTreeNode* BT, ElemType x)
{
if (BT == NULL)
return NULL;
else
{
if (BT->data == x)
return &(BT->data);
else
{
ElemType* p;
if (p == FindBTree(BT->left, x))
return p;
if (p == FindBTree(BT->right, x))
return p;
return NULL;
}
}
}
//6、输出二叉树,可在前序遍历的基础上修改。采用广义表输出格式:A(B(C,D),E(,F(G)))
void PrintBTree(struct BTreeNode* BT)
{
if (BT != NULL)
{
printf("%c", BT->data); //输出根结点的值
if (BT->left != NULL || BT->right != NULL)
{
printf("(");
PrintBTree(BT->left); //输出左子树
if (BT->right != NULL)
printf(",");
PrintBTree(BT->right); //输出右子树
printf(")");
}
}
}
//7、清除二叉树,使之变为一棵空树,算法类似于后序递归遍历
void ClearBTree(struct BTreeNode** BT)
{
if (*BT != NULL)
{
ClearBTree(&((*BT)->left));//删除左子树
ClearBTree(&((*BT)->right));//删除右子树
free(*BT); //释放根结点
*BT = NULL; //置根指针为空
}
}
//8、前序遍历
void Preorder(struct BTreeNode* BT)
{
if (BT != NULL)
{
printf("%c,", BT->data);
Preorder(BT->left);
Preorder(BT->right);
}
}
//9、中序遍历(BT->left=BT,BT->right=BT)
void Inorder(struct BTreeNode* BT)
{
if (BT != NULL)
{
Inorder(BT->left);
printf("%c,", BT->data);//根节点
Inorder(BT->right);
}
}
//10、后序遍历
void Postorder(struct BTreeNode* BT)
{
if (BT != NULL)
{
Postorder(BT->left);
Postorder(BT->right);
printf("%c,", BT->data);
}
}
//11、按层遍历
//按层遍历算法需要使用一个队列,开始时把整个树的根结点入队,然后每从队列中删除一个结点并输出该结点时,
//都把它的非空的左右孩子结点入队,当队列为空时算法结束。
//算法中,队列的最大长度不会超过二叉树中相邻两层的最大结点数,
//所以在提前在程序开始处定义最大队列长度QueueMaxSize大于队列的最大长度,就无需考虑队满溢出的事了
void Levelorder(struct BTreeNode* BT)
{
struct BTreeNode* p;
struct BTreeNode* q[QueueMaxSize];//定义队列所使用的数组空间,元素类型为指向结点的指针类型
int front = 0;
int rear = 0;
if (BT != NULL)//将树根指针入队
{
q[rear] = BT;
rear = (rear + 1) % QueueMaxSize;
}
while (front != rear)//当队列非空时执行循环
{
p = q[front];//保存队首元素
front = (front + 1) % QueueMaxSize;//删除队首元素,使队首指针指向队首元素
printf("%c,", p->data);//输出队首元素
if (p->left != NULL)//若结点存在左孩子,则左孩子结点指针入队
{
q[rear] = p->left;
rear = (rear + 1) % QueueMaxSize;
}
if (p->right != NULL)//若结点存在右孩子,则左孩子结点指针入队
{
q[rear] = p->right;
rear = (rear + 1) % QueueMaxSize;
}
}
}
//主函数
void main()
{
struct BTreeNode* bt;
char b[50];
ElemType x, *px;
InitBTree(&bt);
printf("Please enter a string of binary tree that format is generalized table!\n");
fflush(stdout);
scanf("%s", b);
CreateBTree(&bt, b);
PrintBTree(bt);
printf("\n");
printf("Preorder:");
Preorder(bt);
printf("\n");
printf("Infixorder:");
Inorder(bt);
printf("\n");
printf("Postorder:");
Postorder(bt);
printf("\n");
printf("Levelorder/Tier:");
Levelorder(bt);
printf("\n");
printf("Please input the char that you may seek!\n");
fflush(stdout);
scanf(" %c", &x); //格式串中的空格可以跳过任何空白符
px = FindBTree(bt, x);
if (px)
printf("find success:%c\n", *px);
else
printf("find failure!\n");
printf("The depth of this binaty tree is:");
printf("%d\n", BTreeDepth(bt));
ClearBTree(&bt);
}
运行结果:
initial BTree success!
Please enter a string of binary tree that format is generalized table!
a(b(c,d),e(,f(g)))
a(b(c,d),e(,f(g)))
Preorder:a,b,c,d,e,f,g,
Infixorder:c,b,d,a,e,g,f,
Postorder:c,d,b,g,f,e,a,
Levelorder/Tier:a,b,e,c,d,f,g,
Please input the char that you may seek!
a
find success:a
The depth of this binaty tree is:4
【33】二叉树的非递归遍历
#include <stdio.h>
#include <stdlib.h>
#define N 20
//二叉树结点的结构体表示形式
typedef struct tree
{
char ch;
struct tree *lchild;
struct tree *rchild;
}BitTree;
//创建二叉树,利用递归的方法
//按前序次序输入。 如 A # #(#表示空树)
BitTree *CreateTree()
{
BitTree *bt;
char str;
scanf("%c",&str);
if (str=='#')
return NULL;
else
{
bt=(BitTree *)malloc(sizeof(BitTree));
bt->ch=str;
bt->lchild=CreateTree();//递归创建二叉树
bt->rchild=CreateTree();
return bt;
}
}
//前序遍历的非递归实现
/*
思想:利用栈来实现;根结点进栈,之后栈非空,弹出,接着根节点的右结点进栈,
之后,左节点进栈;接着,弹出栈顶元素(输出),
此结点的右结点进栈,之后左节点进栈,弹出栈顶元素(输出)...一直这样下去,
直到栈为空。
*/
void PreOrder(BitTree *bt)
{
BitTree **s;
BitTree *p;
int top=-1;
//创建栈;
s=(BitTree **)malloc((N+1)*sizeof(BitTree *));
//初始化栈;
s[++top]=bt;
//非递归前序遍历;
while(top!=-1)
{
p=s[top--];
printf("%c ",p->ch); //栈的特点,先进后出;
if(p->rchild)
s[++top]=p->rchild;
if(p->lchild)
s[++top]=p->lchild;
}
free(s);
}
//中序遍历,非递归实现
/*
思想:利用栈。从根节点开始循环,只要有左子节点则进栈,直到左子节点为空。
接着弹出栈顶输出,判断该结点是否有右子节点,
若有则进栈,若没有继续弹栈。有右子节点的情况,判断该节点是否有左子节点,
有则进栈,直到左子节点为空;若该右子节点没有
左子节点,则弹栈;判断弹出的节点,是否有右子节点,若有则进栈,没有继续弹栈;
接着又要判断刚进栈的这个节点,是否有左子节点,
有则进栈,没有则继续弹栈。重复下去....
栈空,是判定条件。
*/
void InOrder(BitTree *bt)
{
BitTree **s;
BitTree *p,*q;
int top=-1;
//创建栈;
s=(BitTree **)malloc((N+1)*sizeof(BitTree *));
//非递归中序遍历;
if(bt)
{
while(bt) //一直遍历左子树直到该结点的左孩子空为止;
{
s[++top]=bt; //将所有左孩子存入栈中;
bt=bt->lchild; //指向下一个左子树;
}
while(top!=-1) //栈空时结束循环;
{
p=s[top--];//刚开始将最p指向左下角的左孩子,并且移向该结点的父结点;
printf("%c ",p->ch); //输出左下角的结点;
while(p->rchild) //遍历移动后结点有没有右结点;
{
s[++top]=p->rchild; //将这个结点的右子树入栈;
q=p->rchild; //这个右子树结点赋给q;
while(q->lchild) //判断结点q有没有左子树;
{
s[++top]=q->lchild; //有左子树,将与这个结点相连的所有左子树都入栈;
q=q->lchild;
}
break; //结束当前循环,回到第二个while循环继续刚才的步骤;
}
}
}
}
//后序遍历,非递归实现
/*
算法思想:利用栈来实现。从根结点开始,只要左子节点非空,则进栈,直到左子节点
为空为止。取出栈顶元素(只是取,并非弹栈),判断:
1:取出的栈顶元素是否有右子节点,或者右子节点是否被访问过,若满足条件(无右子
节点,或者右子节点被访问过),则输出该结点,同时弹栈,并且记录下该访问的节点。
2:取出的栈顶元素,若有右子节点,且未被访问过,则指针继续移动到右子节点,
将右子节点压栈,然后出栈输出。
*/
void PostOrder(BitTree *bt)
{
BitTree **s;
BitTree *p;
int top=-1;
//创建栈;
s=(BitTree **)malloc((N+1)*sizeof(BitTree *));
//非递归后序遍历;
do
{
while(bt) //一直遍历左子树直到该左子树的左孩子空为止;
{
s[++top]=bt; //将所有左孩子存入栈中;
bt=bt->lchild; //指向下一个左子树;
}
p=NULL;
while(top!=-1)
{
bt=s[top];//压栈未访问右子节点
if(bt->rchild==p) //p:表示为null,或者右子节点被访问过了;
{
printf("%c ",bt->ch); //输出结点数据域;
top--; //输出以后,top--;
p=bt; //p记录下刚刚访问的节点;
}
else
{
bt=bt->rchild; //访问右子树结点;
break;
}
}
}while(top!=-1);
}
int main()
{
printf("Please enter a string of binary tree that format is (# show this child node is NULL):\n");
fflush(stdout);
BitTree *btr=CreateTree();
printf("Preorder:");
PreOrder(btr);
printf("\n");
printf("Infixorder:");
InOrder(btr);
printf("\n");
printf("Postorder:");
PostOrder(btr);
printf("\n");
return 0;
}
运行结果:
Please enter a string of binary tree that format is (# show this child node is NULL):
ADGC##H##E##C#F##
Preorder:
A D G C H E C F
Infixorder:
C G H D E A C F
Postorder:
C H G E D F C A
【34】一个简单的词法分析器
#include<stdio.h>
#include<string.h>
#define bool int
#define true 1
#define false 0
#define MAX 11
char ch = ' ';
char* keyWord[11] = {"include","main","void","break","int","float","if","else","while","printf","for"};
char token[20];//定义获取的字符
//判断是否是关键字
bool isKey(char * token)
{
for(int i = 0;i < MAX;i++)
{
if(strcmp(token,keyWord[i]) == 0)
return true;
}
return false;
}
//判断是否是字母
bool isLetter(char letter)
{
if((letter >= 'a' && letter <= 'z')||(letter >= 'A' && letter <= 'Z'))
return true;
else
return false;
}
//判断是否是数字
bool isDigit(char digit)
{
if(digit >= '0' && digit <= '9')
return true;
else
return false;
}
//词法分析
/*从文件指针fpin(stream)指向的文件读取一个字符,读取一个字节后,光标位置后移一个字节
* format: int fgetc(FILE*stream)
* 函数返回得到的字符值
* 读到结尾或者读到错误,返回EOF
* EOF是一个有效的整型值
* 二进制文件使用feof函数进行结束检测
* 用ferror函数进行出错检查
*/
void analyze(FILE *fpin)
{
while((ch = fgetc(fpin)) != EOF){
if(ch == ' '||ch == '\t'||ch == '\n'){}//读到空字符,空格,换行符什么都不做
else if(isLetter(ch)){
char token[20]={'\0'};
int i=0;
while(isLetter(ch)||isDigit(ch)){
token[i] = ch;
i++;
ch = fgetc(fpin);//读下一个字符
}
//回退一个指针
/*int fseek(FILE*stream,long offset,int fromwhere),调整文件当前指针
* 若果函数成功执行,stream指针将指向以fromwhere为基准,偏移offset个字节的位置,函数返回0
* 若果函数执行失败(offset的值大于等于2*1024*1024*1024,即long的整数范围为2G),函数返回非零值*
* 偏移起始位置:文件头0(SEEK_SET)
* 当前位置:当前位置1(SEEK_CUR)
* 文件尾2(SEEK_END)*/
fseek(fpin,-1L,SEEK_CUR);//文件指针停留在空字符,空格,换行符的位置上
if(isKey(token)){
//关键字
int i,j;
for( i = 0;i < MAX;i++)
{
if(strcmp(token,keyWord[i]) == 0)j=i;
} printf("%s\t%d\tkeyword\n",token,j);
}
else{
//标识符
printf("%s\t4\tidentify_char\n",token);
}
}
else if(isDigit(ch)||(ch == '.'))
{
int i=0;
char token[20]={'\0'};//清空缓冲数组;但文件指针还在;即读入下一个字符
while(isDigit(ch)||(ch == '.'&&isDigit(fgetc(fpin))))
{
if(ch == '.')fseek(fpin,-1L,SEEK_CUR);
token[i] = ch;
i++;
ch = fgetc(fpin);
}
fseek(fpin,-1L,SEEK_CUR);
//属于无符号常数
printf("%s\t11\tconstant\n",token);
fflush(stdout);
}
else switch(ch){
//运算符
case '+':{
ch = fgetc(fpin);
if(ch == '+')
{
printf("++\t12\toperator\n");
fflush(stdout);
}
else {
printf("+ \t13\toperator\n");
fflush(stdout);
fseek(fpin,-1L,SEEK_CUR);
}
}break;
case '-':{
ch = fgetc(fpin);
if(ch == '-')
{
printf("--\t14\toperator\n");
fflush(stdout);
}
else {
printf("- \t15\toperator\n");
fflush(stdout);
fseek(fpin,-1L,SEEK_CUR);
}
}break;
case '*':printf("%c\t16\toperateor\n",ch);break;
case '/':printf("%c\t17\toperateor\n",ch);break;
//分界符
case '(':printf("%c\t18\tboundary\n",ch);break;
case ')':printf("%c\t19\tboundary\n",ch);break;
case '[':printf("%c\t20\tboundary\n",ch);break;
case ']':printf("%c\t21\tboundary\n",ch);break;
case ';':printf("%c\t22\tboundary\n",ch);break;
case '{':printf("%c\t23\tboundary\n",ch);break;
case '}':printf("%c\t24\tboundary\n",ch);break;
case '#':printf("%c\t25\tboundary\n",ch);break;
//运算符
case '=':{
ch = fgetc(fpin);
if(ch == '=')printf("==\t26\toperator\n");
else {
printf("= \t27\toperator\n");
fseek(fpin,-1L,SEEK_CUR);
}
}break;
case ':':{
ch = fgetc(fpin);
if(ch == '=')printf(":=\t28\toperator\n");
else {
printf(": \t29\toperator\n");;
fseek(fpin,-1L,SEEK_CUR);
}
}break;
case '>':{
ch = fgetc(fpin);
if(ch == '=')printf(">=\t30\toperator\n");
else {
printf("> \t31\toperator\n");;
fseek(fpin,-1L,SEEK_CUR);
}
}break;
case '<':{
ch = fgetc(fpin);
if(ch == '=')printf("<=\t32\toperator\n");
else {
printf("< \t33\toperator\n");
fseek(fpin,-1L,SEEK_CUR);
}
}break;
//无识别
default: printf("%c\t34\tno_recognition\n",ch);
}
}
}
int main(){
char input[30];
FILE *fpin;
printf("Please input the path of file that you want to compile:(C:\...)\n ");
fflush(stdout);
scanf("%s",input);
if((fpin = fopen(input,"r")) != NULL)
{
printf("File open success!\n");
}
else
{
printf("Path Error!\n\n");
fflush(stdout);
}
printf("****************Lexical analysis start*********************\n");
analyze(fpin);
printf("****************Lexical analysis finish********************\n");
fclose(fpin);
printf("File close success!");
return 0;
}
运行结果:
Please input the path of file that you want to compile:(C:...)
D:\\testfile.txt
File open success!
****************Lexical analysis start*********************
# 25 boundary
include 0 keyword
< 33 operator
stdio 4 identify_char
11 constant
h 4 identify_char
> 31 operator
int 4 keyword
main 1 keyword
( 18 boundary
) 19 boundary
{ 23 boundary
int 4 keyword
i 4 identify_char
; 22 boundary
for 10 keyword
( 18 boundary
i 4 identify_char
= 27 operator
1 11 constant
; 22 boundary
i 4 identify_char
<= 32 operator
10 11 constant
; 22 boundary
i 4 identify_char
++ 12 operator
) 19 boundary
printf 9 keyword
( 18 boundary
" 34 no_recognition
hello 4 identify_char
world 4 identify_char
" 34 no_recognition
) 19 boundary
; 22 boundary
return 4 identify_char
0 11 constant
; 22 boundary
} 24 boundary
****************Lexical analysis finish********************
File close success!
【35】二叉树的中序线索化
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
/*
线索存储标志位
Link(0):表示指向左右孩子的指针
Thread(1):表示指向前驱后继的线索
*/
typedef enum {Link, Thread} PointerTag;//枚举类型
typedef struct BiThrNode{
ElemType data;
struct BiThrNode *lchild, *rchild;
PointerTag ltag;
PointerTag rtag;
}BiThrNode, *BiThrTree;
//全局变量,始终指向刚刚访问过的节点
BiThrTree pre;
//创建一棵二叉树,约定用户遵照前序遍历方式输入数据
void createBiThrTree(BiThrTree *T){
char c;
scanf("%c", &c);
if('#' == c){
*T = NULL;
}else{
*T = (BiThrNode*)malloc(sizeof(BiThrNode));
(*T)->data = c;
(*T)->ltag = Link;
(*T)->rtag = Link;
createBiThrTree(&(*T)->lchild);
createBiThrTree(&(*T)->rchild);
}
}
//中序遍历线索化
void inThreading(BiThrTree T){
if(T){
inThreading(T->lchild);//递归左孩子线索化
//节点处理
if(!T->lchild){
/*在当前的节点没有左子树,为该节点设置前驱线索,指向前驱结点的指针称为线索*/
T->ltag = Thread;
T->lchild = pre;//左孩子指向标记指针,也就是为中序标记的首元素设置前驱线索(即控制台输出的第一个元素)
}
if(pre!=NULL && !pre->rchild){//处理后继
/*刚访问的节点不为空,且刚访问的结点没有右孩子*/
pre->rtag = Thread;
pre->rchild = T;//右孩子指向它的右孩子根节点
}
pre = T;
inThreading(T->rchild);//递归右孩子线索化
}
}
//中序遍历线索二叉树---非递归
void InOrderThreading(BiThrTree T){
BiThrTree p = T;
while(p != NULL){
//当ltag == Thread时,循环到中序序列第一个节点
while(p->ltag == Link){
p = p->lchild;
}
printf("%c ", p->data);
while(p->rtag == Thread && p->rchild != NULL){
p = p ->rchild;
printf("%c ", p->data);
}
p = p->rchild;
}
}
int main(){
BiThrTree T = NULL;
printf("Please input threaded binary tree:Tip('#' is equal to NULL)\n");
fflush(stdout);
createBiThrTree(&T);
inThreading(T);
pre->rtag = Thread;
printf("Infixorder this threaded binary tree: ");
fflush(stdout);
InOrderThreading(T);
return 0;
}
运行结果:
Please input threaded binary tree:Tip('#' is equal to NULL)
ABD###C##
Infixorder this threaded binary tree: D B A C
调试结果