常见数据结构--C

常见数据结构的代码实现

C

链表的实现


利用 C 语言结构体类型定义单链表:

typedef struct node{
ElemType data; //数据域
 struct node *next; //指向下一个节点的指针
}LNode,*LinkList;
#ifndef _LINK_H
#define _LINK_H
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
enum BOOL{False,True}; //定义 BOOL 型
typedef struct{
int sn;
char name[10];
float score;
}Stu;
typedef Stu ElemType;
typedef struct node{
ElemType data; //数据域
struct node *next; //指向下一个节点的指针
}LNode,*LinkList;
//生成一个带头结点的有 n 个元素的单链表
void CreatList(LinkList &L,int n); 
//在单链表的第 i 各位置插入元素 e,成功返回 True,失败返回 False
BOOL ListInsert(LinkList &L,int i,ElemType e); 
//在单链表中删除第 i 个元素,成功删除返回 True,并用 e 返回该元素值,失败返回 False
BOOL ListDelete(LinkList &L,int i,ElemType &e); 
//在单链表中查找关键字为 e 的元素,成功返回 True,并用 i 返回该元素位置,失败返回
False
BOOL ListFind_keyword(LinkList L,ElemType e,int &i); 
//在单链表中查找第 i 个元素,成功返回 True,并用 e 返回该元素值,失败返回 False
BOOL ListFind_loc(LinkList L,int i,ElemType &e); 
void ListPrint(LinkList L); //显示链表所有元素
void DestroyLink(LinkList &L); //删除链表,回收内存空间
int CompareElemType(ElemType a,ElemType b); //比较结构体数据的异同
#endif
3. 将接口实现放在 Link.cpp 里,文件内容如下:
#include <string.h>
#include "link.h"
void CreatList(LinkList &L,int n){ //生成一个带头结点的有 n 个元素的单链表
int i;
LinkList p;
L=(LinkList)malloc(sizeof(LNode)); //申请生成头结点if(!L) exit(1);
L->next=NULL;
printf("使用头插法,请逆序位输入%d 个学生信息(学号 姓名 分数),101 张三 97.5:
\n",n);
getchar();
for(i=n;i>0;--i) { //头插法
p=(LinkList)malloc(sizeof(LNode)); //申请生成新结点
if(!p) exit(1);
scanf("%d %s %f",&p->data.sn,&p->data.name,&p->data.score);
p->next=L->next;
L->next=p;
 }
printf("%d 个结点的链表已经建立\n",n);
}
BOOL ListInsert(LinkList &L,int i,ElemType e){ //在单链表的第 i 各位置插入元素 e,成功返
回 True,失败返回 False
LinkList s,p=L;
int j=0;
while(p && j<i-1) { //找到第 i-1 个结点的位置
p=p->next; ++j;
} 
if(!p || j>i-1) return False; //i<1 或者 i 大于表长+1
s=(LinkList)malloc(sizeof(LNode)); //申请生成一个新结点 
if(!s) exit(1);
//将新结点插入到单链表中
s->data.sn=e.sn; strcpy(s->data.name,e.name); s->data.score=e.score; 
s->next=p->next; p->next=s; 
return True;
}
BOOL ListDelete(LinkList &L,int i,ElemType &e){//在单链表中删除第 i 个元素,成功删除返
回 True,并用 e 返回该元素值,失败返回 False
LinkList q,p=L;
int j=0;
while(p->next && j<i-1){ //查找第 i-1 个结点位置
p=p->next;
++j;
}
if(!(p->next) || j>i-1) return False; //删除位置不合理
q=p->next; p->next=q->next; //删除该元素 
e.sn=q->data.sn; strcpy(e.name,q->data.name); e.score=q->data.score; //e 取得该元素值
free(q); //释放该元素空间
return True;}
BOOL ListFind_keyword(LinkList L,ElemType e,int &i){
//在单链表中查找关键字为 e 的元素,成功返回 True,并用 i 返回该元素位置,失败返回
False
i=1;
LinkList p=L->next;
ElemType a=p->data;
while(p && !(CompareElemType(a,e))){ //p 指针指向下一个,直到找到关键字 e 或
到链表尾为止
p=p->next; 
i++;
} 
if(!p || !(CompareElemType(a,e))) return False; //该元素在链表中不存在
else return True;
}
BOOL ListFind_loc(LinkList L,int i,ElemType &e){ //在单链表中查找第 i 个元素,成功返回
True,并用 e 返回该元素值,失败返回 False
LinkList p=L->next;
int j=1;
while(p && j<i) { //移动指针,直到找到第 i 个元素或 p 为 NULL
p=p->next; ++j;
}
if(!p || j>i) return False; //第 i 个元素不存在
e.sn=p->data.sn; strcpy(e.name,p->data.name); e.score=p->data.score; //查找成功,用 e 取
得第 i 个元素值
return True;
}
void ListPrint(LinkList L) {//显示链表所有元素
LinkList q=L->next;
printf("链表所有元素:\n");
while(q){
printf(" 学号: %10d 姓 名 : %13s 分
数:%10.2f\n",q->data.sn,q->data.name,q->data.score);
q=q->next;
}
printf("\n");
}
void DestroyLink(LinkList &L){ //删除链表,回收内存空间
LinkList q;
while (L){q=L->next;
free(L);
L=q;
}
printf("链表已经销毁\n");
}
int CompareElemType(ElemType a,ElemType b){ //比较结构体数据的异同
if(a.sn==b.sn && a.score==b.score && strcmp(a.name,b.name)==0) return 1;
else return 0;
}
4. 主函数:
#include "link.h"
void main(){
LinkList L;
BOOL temp;
int num,loc,flag=1;
char j;
Stu stu;
printf("本程序实现链式结构的线性表操作: 插入,删除,定位,查找等\n");
printf("请输入初始链表长度:"); //输入生成单链表时的元素个数
scanf("%d",&num);
CreatList(L,num); //生成单链表
ListPrint(L); 
while(flag) { 
printf("请选择:\n"); 
printf("1.显示所有学生记录\n"); //显示链表元素
printf("2.插入一个学生记录\n"); //插入链表元素
printf("3.删除一个学生记录\n"); //删除链表元素
printf("4.按关键字查找对应的学生记录\n"); //按关键字查找
printf("5.按结点序号查找学生记录\n"); //按结点序号查找
printf("6.退出程序 \n"); //退出
scanf(" %c",&j);
switch(j){
case '1':
ListPrint(L); 
break;
case '2':
printf("请插入位置和输入元素(学生记录):\n");
printf("格式: 位置 学号 姓名 分数;例如:3,1001,张三,95.5\n");
//输入要插入的元素和要插入的位置
scanf("%d %d %s %f",&loc,&stu.sn,&stu.name,&stu.score); 
temp=ListInsert(L,loc,stu); //插入if(temp==False) printf("插入失败!\n"); 
else printf("插入成功!\n"); 
ListPrint(L);
break;
case '3':
printf("请输入要删除元素的结点位置:");
scanf("%d",&loc); //输入要删除的节点的位置
temp=ListDelete(L,loc,stu); //删除
if(temp==False) printf("删除失败!\n"); 
//删除成功,显示该元素
else printf("成功删除了一个元素:%d,%s,%.2f\n",stu.sn,stu.name,stu.score); 
ListPrint(L);
break;
case '4':
if(L->next==NULL) printf("链表为空!\n"); 
else{
printf("请输入查找元素(学号 姓名 分数):");
scanf("%d %s %f",&stu.sn,&stu.name,&stu.score); //输入要查找的元素
temp=ListFind_keyword(L,stu,loc); //按关键字查找
if(temp==False) printf("没有找到该元素!\n"); 
else printf("该元素在链表的第%d 个结点\n",loc); 
 }
break;
case '5':
if(L->next==NULL) printf("链表为空!\n"); //链表为空
else{
printf("请输入查找位置:");
scanf("%d",&loc); //输入查找元素的位置
temp=ListFind_loc(L,loc,stu); //按结点序号查找
if(temp==False) printf("该位置不存在!\n"); 
else printf("第%d 个元素是:%d %s %.2f\n",loc,stu.sn,stu.name,stu.score); 
}
break;
default:
flag=0;
DestroyLink(L); //销毁链表,回收空间
printf("程序结束,按任意键退出!\n");
}
 }
getch();
}

栈的实现

#define MAX_STACK_SIZE 100 /* 栈大小 */
typedef int ElemType ;
typedef struct sqstack
{ 
ElemType stack_array[MAX_STACK_SIZE] ;
int base;
int top;
}SqStack ;2)链栈的存储结构设计
typedef struct Stack_Node
{ 
ElemType data;
struct Stack_Node *next;
}Stack_Node , *Link_SN;3)顺序栈的操作算法设计
//初始化栈
Status Init_Stack(SqStack &S)
{ 
 S.base=S.top=0 ; 
return OK;
}
//压栈
Status push(SqStack &S , ElemType e) /* 使数据元素 e 进栈成为新的栈顶 */
{ 
if(S.top>=MAX_STACK_SIZE) return ERROR; /* 栈满,返回错误标志 */
S.stack_array[S.top]=e ; 
S.top++ ; /* 栈顶指针加 1 */
return OK; /* 压栈成功 */
}
//弹栈
Status pop( SqStack &S, ElemType &e ) /*弹出栈顶元素*/
{ 
if(S.top==0) return ERROR ; /* 栈空,返回错误标志 */
e=S.stack_array[--S.top]; 
return OK; 
}4)链栈的操作算法设计
//初始化栈
Status Init_LinkStack(Link_SN &top)
{
top=(Link_SN)malloc(sizeof(Stack_Node ));
if(!top) exit(OVERFLOW);
top->next=NULL;
return OK;
}
//压栈Status Push_Link(Link_SN &top , ElemType e) /* 使数据元素 e 进栈成为新的栈顶 */
{ 
Stack_Node *p = (Stack_Node *)malloc(sizeof(Stack_Node)) ; 
if (!p) exit(OVERFLOW); /* 申请新结点失败,返回错误标志 */
p->data=e ; 
p->next=top; 
top=p; /* 钩链 */
return OK;
}
//弹栈
char Pop_LinkStack(Link_SN &top) /* 将栈顶元素出栈 */
{ 
char e;
Link_SN p;
if(top->next==NULL) return ERROR; /* 栈空,返回错误标志 */
p=top; 
e=top->data; /* 取栈顶元素 */
top=top->next; /* 修改栈顶指针 */
free(p); 
return e;
}

树的实现


 #define MAX_STACK_SIZE 100 /* 栈大小 *
typedef int ElemType ;
typedef struct sqstack
{ 
ElemType stack_array[MAX_STACK_SIZE] ;
int base;
int top;
}SqStack ;(2)链栈的存储结构设计
typedef struct Stack_Node
{ 
ElemType data;
struct Stack_Node *next;
}Stack_Node , *Link_SN;
(3)顺序栈的操作算法设计
//初始化栈
Status Init_Stack(SqStack &S)
{ 
 S.base=S.top=0 ; 
return OK;
}
//压栈
Status push(SqStack &S , ElemType e) /* 使数据元素 e 进栈成为新的栈顶 */
{ 
if(S.top>=MAX_STACK_SIZE) return ERROR; /* 栈满,返回错误标志 */
S.stack_array[S.top]=e ; 
S.top++ ; /* 栈顶指针加 1 */
return OK; /* 压栈成功 */
}
//弹栈
Status pop( SqStack &S, ElemType &e ) /*弹出栈顶元素*/
{ 
if(S.top==0) return ERROR ; /* 栈空,返回错误标志 */
e=S.stack_array[--S.top]; 
return OK; 
}4)链栈的操作算法设计
//初始化栈
Status Init_LinkStack(Link_SN &top)
{
top=(Link_SN)malloc(sizeof(Stack_Node ));
if(!top) exit(OVERFLOW);
top->next=NULL;
return OK;
}
//压栈Status Push_Link(Link_SN &top , ElemType e) /* 使数据元素 e 进栈成为新的栈顶 */
{ 
Stack_Node *p = (Stack_Node *)malloc(sizeof(Stack_Node)) ; 
if (!p) exit(OVERFLOW); /* 申请新结点失败,返回错误标志 */
p->data=e ; 
p->next=top; 
top=p; /* 钩链 */
return OK;
}
//弹栈
char Pop_LinkStack(Link_SN &top) /* 将栈顶元素出栈 */
{ 
char e;
Link_SN p;
if(top->next==NULL) return ERROR; /* 栈空,返回错误标志 */
p=top; 
e=top->data; /* 取栈顶元素 */
top=top->next; /* 修改栈顶指针 */
free(p); 
return e;
}

BOOL visited[MAX_VERTEX_NUM]; //全局变量--访问标志数组
void CreateGraph(Graph &G) //构造邻接表结构的图 G
{
int i;
int start,end; 
ArcNode *s;
for(i=1;i<=G.vexnum;i++) G.AdjList[i]=NULL; //初始化指针数组
printf("输入各边的两个顶点(有向图输入格式:弧尾,弧头):\n");
for(i=1;i<=G.arcnum;i++)
{
scanf("%d,%d",&start,&end); //输入弧的起点和终点
s=(ArcNode *)malloc(sizeof(ArcNode)); //生成一个弧结点
s->nextarc=G.AdjList[start]; //插入到邻接表中s->adjvex=end;
G.AdjList[start]=s;
if(G.GraphKind==0) //若是无向图,再插入到终点的弧链中
{
s=(ArcNode *)malloc(sizeof(ArcNode));
s->nextarc=G.AdjList[end];
s->adjvex=start;
G.AdjList[end]=s;
}
}
}
void DFSTraverse(Graph G) //深度优先遍历图 G
{
int i;
printf("深度优先搜索遍历序列:");
for(i=1;i<=G.vexnum;i++) visited[i]=False; //访问标志数组初始化
for(i=1;i<=G.vexnum;i++)
{
if(!visited[i]) DFS(G,i); //对尚未访问的顶点调用 DFS
}
printf("\b\b \n");
}
void DFS(Graph G,int i) //从第 i 个顶点出发递归地深度遍历图 G
{
int w;
visited[i]=True; //访问第 i 个顶点
printf("%d->",i);
for(w=FirstAdjVex(G,i);w;w=NextAdjVex(G,i,w))
{
if(!visited[w]) DFS(G,w); //对尚未访问的邻接顶点 w 调用 DFS
}
}
void BFSTraverse(Graph G) //按广度优先非递归的遍历图 G,使用辅助队列 Q 和访问标志数
组 visited
{
int i,u,w; 
SqQueue Q; 
printf("广度优先搜索遍历序列:");
for(i=1;i<=G.vexnum;i++) visited[i]=False; //访问标志数组初始化
InitQueue(Q); //初始化队列for(i=1;i<=G.vexnum;i++)
{
if(!visited[i])
{
visited[i]=True; //访问顶点 i
printf("%d->",i);
EnQueue(Q,i); //将序号 i 入队列
while(QueueLength(Q)>0) //若队列不空,继续
{
DeQueue(Q,u); //将队头元素出队列并置为 u
for(w=FirstAdjVex(G,u);w;w=NextAdjVex(G,u,w))
{
if(!visited[w]) //对 u 的尚未访问的邻接顶点 w 进行访问并入队列
{
visited[w]=True;
printf("%d->",w);
EnQueue(Q,w);
}
}
}
}
}
printf("\b\b \n");
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值