欢迎来到千学网!
您现在的位置:首页 > 实用文 > 其他范文

栈的实现(C语言实现)

时间:2022-09-03 08:25:50 其他范文 收藏本文 下载本文

以下是小编精心整理的栈的实现(C语言实现),本文共9篇,希望对大家有所帮助。

栈的实现(C语言实现)

篇1:栈的实现(C语言实现)

//头文件 #include/*====================栈 数据结构利用数组实现====================*/#define MAX 100#define ok 1#define error 0typedef struct Stack{ int data[MAX]; int top;//栈顶 int bottom; //栈底}Stack,*STACK;//初始化栈int InitStack(STACK stack);//销毁int DestroyStack(STACK stack);//清空int ClearStack(STACK stack);//栈空int StackEmpty(STACK stack);//获取栈顶元素int GetTop(STACK stack,int* elem);//压栈int Push(STACK stack,int* elem);//出栈int Pop(STACK stack,int* elem);//返回栈中元素长度int StackLength(STACK stack,int* len);//打印栈中元素int PrintStack(STACK stack);//栈满int StackFull(STACK stack);

//main函数中实现#include “stack.h”int main{ int num=10, num1, i=0,j=0; Stack stack; int initFlag=InitStack(&stack); if(!initFlag) return 0; for(num1=0;num1<10;num1++) Push(&stack,&num1);/* int pushFlag=Push(&stack,&num); if(!pushFlag) return 0;*/// ClearStack(&stack); for(;i<10;i++) { int flag=Pop(&stack,&num1); if(flag) printf(“%d ”,num1); else printf(“Pop error”); } int lenFlag=StackLength(&stack,&num1); if(lenFlag) printf(“len=%d ”,num1); else printf(“StackLength error”);/* int getFlag=GetTop(&stack,&num1); if(getFlag) printf(“%d ”,num1);*/ PrintStack(&stack); return 0;}//初始化栈int InitStack(STACK stack){ if(stack==NULL) return error; stack->bottom=stack->top=0; return ok;}//压栈int Push(STACK stack,int* elem){ int flag=StackFull(stack); if(!flag) return error; stack->data[stack->top] =*elem; ++stack->top; return ok;}//打印栈中所有元素int PrintStack(STACK stack){ int i=0; int flag=StackEmpty(stack); if(!flag) return error; for(i=0;itop;i++) { printf(“%d ”,stack->data[i]); } printf(“n”); return ok;}//栈空int StackEmpty(STACK stack){ if(stack==NULL || stack->top==stack->bottom) return error; else return ok;}//出栈int Pop(STACK stack,int* elem){ int flag=StackEmpty(stack); if(!flag) return error; *elem=stack->data[stack->top-1]; --stack->top; return ok;}//栈满int StackFull(STACK stack){ if(stack==NULL || stack->top>MAX) return error; else return ok;}//销毁int DestroyStack(STACK stack){ if(stack==NULL) return ok; else { stack->top=stack->bottom; stack=NULL; return ok; }}//清空int ClearStack(STACK stack){ int flag=StackEmpty(stack); if(!flag) return error; else { stack->top=stack->bottom; return ok; }}//获取栈顶元素int GetTop(STACK stack,int* elem){ int flag=StackEmpty(stack); if(!flag) return error; *elem=stack->data[stack->top-1]; return ok;}//返回栈中元素长度int StackLength(STACK stack,int* len){ if(stack==NULL) return error; if(stack->top==stack->bottom) { *len=0; return ok; } else { *len=stack->top; return ok; }}

篇2:链表的c语言实现③

3、删除

假如我们已经知道了要删除的结点p的位置,那么要删除p结点时只要令p结点的前驱结点的链域由存储p结点的地址该为存储p的后继结点的地址,并回收p结点即可,

以下便是应用删除算法的实例:

#include

#include

#include

#define N 10

typedef struct node

{

char name[20];

struct node *link;

}stud;

stud * creat(int n) /*建立新的链表的函数*/

{

stud *p,*h,*s;

int i;

if((h=(stud *)malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

h->name[0]='';

h->link=NULL;

p=h;

for(i=0;i

{

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

p->link=s;

printf(“请输入第%d个人的姓名”,i+1);

scanf(“%s”,s->name);

s->link=NULL;

p=s;

}

return(h);

}

stud * search(stud *h,char *x) /*查找函数*/

{

stud *p;

char *y;

p=h->link;

while(p!=NULL)

{

y=p->name;

if(strcmp(y,x)==0)

return(p);

else p=p->link;

}

if(p==NULL)

printf(“没有查找到该数据!”);

}

stud * search2(stud *h,char *x) /*另一个查找函数,返回的是上一个查找函数的直接前驱结点的指针,*/

/*h为表头指针,x为指向要查找的姓名的指针*/

/*其实此函数的算法与上面的查找算法是一样的,只是多了一个指针s,并且s总是指向指针p所指向的结点的直接前驱,*/

/*结果返回s即是要查找的结点的前一个结点*/

{

stud *p,*s;

char *y;

p=h->link;

s=h;

while(p!=NULL)

{

y=p->name;

if(strcmp(y,x)==0)

return(s);

else

{

p=p->link;

s=s->link;

}

}

if(p==NULL)

printf(“没有查找到该数据!”);

}

void del(stud *x,stud *y) /*删除函数,其中y为要删除的结点的指针,x为要删除的结点的前一个结点的指针*/

{

stud *s;

s=y;

x->link=y->link;

free(s);

}

main()

{

int number;

char fullname[20];

stud *head,*searchpoint,*forepoint;

number=N;

head=creat(number);

printf(“请输入你要删除的人的姓名:”);

scanf(“%s”,fullname);

searchpoint=search(head,fullname);

forepoint=search2(head,fullname);

del(forepoint,searchpoint);

一、循环链表

循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链,

循环链表的运算与单链表的运算基本一致。所不同的有以下几点:

1、在建立一个循环链表时,必须使其最后一个结点的指针指向表头结点,而不是象单链表那样置为NULL。此种情况还使用于在最后一个结点后插入一个新的结点。

2、在判断是否到表尾时,是判断该结点链域的值是否是表头结点,当链域值等于表头指针时,说明已到表尾。而非象单链表那样判断链域值是否为NULL。

二、双向链表

双向链表其实是单链表的改进。

当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。

在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。在c语言中双向链表结点类型可以定义为:

typedef struct node

{

int data; /*数据域*/

struct node *llink,*rlink; /*链域,*llink是左链域指针,*rlink是右链域指针*/

}JD;

当然,也可以把一个双向链表构建成一个双向循环链表。

双向链表与单向链表一样,也有三种基本运算:查找、插入和删除。

篇3:链表的c语言实现⑤

3、删除

删除某个结点,其实就是插入某个结点的逆操作,还是对于双向循环链表,要在连续的三个结点s,p,q中删除p结点,只需把s的右链域指针指向q,q的左链域指针指向s,并收回p结点就完成了。

下面就是一个应用双向循环链表删除算法的例子:

#include

#include

#include

#define N 10

typedef struct node

{

char name[20];

struct node *llink,*rlink;

}stud;

stud * creat(int n)

{

stud *p,*h,*s;

int i;

if((h=(stud *)malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

h->name[0]='';

h->llink=NULL;

h->rlink=NULL;

p=h;

for(i=0;i〈n;i++)

{

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

p-〉rlink=s;

printf(“请输入第%d个人的姓名”,i+1);

scanf(“%s”,s->name);

s->llink=p;

s->rlink=NULL;

p=s;

}

h->llink=s;

p->rlink=h;

return(h);

}

stud * search(stud *h,char *x)

{

stud *p;

char *y;

p=h->rlink;

while(p!=h)

{

y=p->name;

if(strcmp(y,x)==0)

return(p);

else p=p->rlink;

}

printf(“没有查找到该数据!”);

}

void print(stud *h)

{

int n;

stud *p;

p=h->rlink;

printf(“数据信息为:n”);

while(p!=h)

{

printf(“%s ”,&*(p->name));

p=p->rlink;

}

printf(“n”);

}

void del(stud *p)

{

(p->rlink)->llink=p->llink;

(p->llink)->rlink=p->rlink;

free (p);

}

main

{

int number;

char studname[20];

stud *head,*searchpoint;

number=N;

clrscr();

head=creat(number);

print(head);

printf(“请输入你要查找的人的姓名:”);

scanf(“%s”,studname);

searchpoint=search(head,studname);

printf(“你所要查找的人的姓名是:%sn”,*&searchpoint->name);

del(searchpoint);

print(head);

}

在这里列举了一个应用单链表基本算法的综合程序,双向链表和循环链表的综合程序大家可以自己去试一试。

#include

#include

#include

#define N 10 typedef struct node

{

char name[20];

struct node *link;

}stud;

stud * creat(int n)

{

stud *p,*h,*s;

int i;

if((h=(stud *)malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

h->name[0]='';

h->link=NULL;

p=h;

for(i=0;i

{

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

p->link=s;

printf(“请输入第%d个人的姓名”,i+1);

scanf(“%s”,s->name);

s->link=NULL;

p=s;

}

return(h);

}

stud * search(stud *h,char *x)

{

stud *p;

char *y;

p=h->link;

while(p!=NULL)

{

y=p->name;

if(strcmp(y,x)==0)

return(p);

else p=p->link;

}

if(p==NULL)

printf(“没有查找到该数据!”);

}

stud * search2(stud *h,char *x)

{

stud *p,*s;

char *y;

p=h->link;

s=h;

while(p!=NULL)

{

y=p->name;

if(strcmp(y,x)==0)

return(s);

else

{

p=p->link;

s=s->link;

}

}

if(p==NULL)

printf(“没有查找到该数据!”);

}

void insert(stud *p)

{

char stuname[20];

stud *s;

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

printf(“n请输入你要插入的人的姓名:”);

scanf(“%s”,stuname);

strcpy(s->name,stuname);

s->link=p->link;

p->link=s;

}

void del(stud *x,stud *y)

{

stud *s;

s=y;

x->link=y->link;

free(s);

}

void print(stud *h)

{

stud *p;

p=h->link;

printf(“数据信息为:n”);

while(p!=NULL)

{

printf(“%s ”,&*(p->name));

p=p->link;

}

}

void quit()

{

exit(0);

}

void menu(void)

{

clrscr();

printf(“ttt单链表C语言实现实例n”);

printf(“tt|————————————————|n”);

printf(“tt| |n”);

printf(“tt| [1] 建 立 新 表 |n”);

printf(“tt| [2] 查 找 数 据 |n”);

篇4:C语言编写实现玫瑰花

#include

#include

#include

/*玫瑰花*/

#define FNX(x) (int)(xo+(x)*1.0)

#define FNY(y) (int)(getmaxy()-(yo+(y)*1.0))

#define FNX2(phi) cos(phi)*ac-sin(phi)*bs

#define FNY2(phi) cos(phi)*as+sin(phi)*bc

/*画旋转的椭圆*/

void elli(int xo,int yo,int a,int b,double theta)

{

int i;

double da,c,s,ac,as,bc,bs,xf,yf,phi,x,y;

theta=theta*0.01745;

da=3*0.1745;

c=cos(theta);s=sin(theta);

ac=a*c;as=a*s;bc=b*c;bs=b*s;

x=FNX2(0);y=FNY2(0);

moveto(FNX(x),FNY(y));

for(i=1;i<=360;i++)

{

phi=i*da;xf=x*cos(phi)*0.1;yf=b*sin(phi)*0.1;

x=FNX2(phi);y=FNY2(phi);

lineto(FNX(x),FNY(y));

}

}

/*花*/

void hua(int x,int y)

{

register i;

/*画粉红色玫瑰*/

setcolor(12);

arc(x+65,y-60,150,350,8);

arc(x+66,y-54,300,470,8);

arc(x+65,y-56,30,230,10);

arc(x+64,y-57,300,490,17);

ellipse(x+73,y-30,250,450,27,40);

ellipse(x+59,y-30,100,290,27,40);

ellipse(x+65,y-40,140,270,20,30);

setfillstyle(SOLID_FILL,5);

floodfill(x+65,y-20,12);

/*画红色玫瑰*/

arc(x,y,150,350,12);

arc(x+1,y+8,280,470,12);

arc(x,y+2,30,230,16);

arc(x,y+3,80,240,28);

arc(x+2,y+8,180,330,22);

arc(x-2,y+2,310,460,25);

ellipse(x-12,y+30,120,300,30,40);

ellipse(x+10,y+28,250,423,30,42);

ellipse(x-4,y+10,290,393,30,40);

setfillstyle(SOLID_FILL,4);

floodfill(x+5,y+31,12);

/*画紫色花骨朵*/

ellipse(x+120,y+5,0,360,15,25);

setfillstyle(SOLID_FILL,1);

floodfill(x+120,y,12);

/*画黄色花骨朵*/

ellipse(x-70,y+10,0,360,14,20);

setfillstyle(SOLID_FILL,14);

floodfill(x-70,y+10,12);

setcolor(10);

/*画红花花萼*/

ellipse(x-15,y+32,190,310,30,35);

ellipse(x+16,y+32,235,355,26,35);

ellipse(x,y+35,190,350,43,50);

arc(x,y+82,190,350,6);

setfillstyle(SOLID_FILL,2);

floodfill(x,y+75,10);

/*画粉花花萼*/

ellipse(x+50,y-48,190,320,22,50);

ellipse(x+80,y-48,220,350,22,50);

ellipse(x+65,y-28,180,360,36,50);

floodfill(x+65,y+18,10);

/*画主枝*/

for(i=0;i<3;i++ )

{

ellipse(x-98,y+100+i,255,371,100,80);

ellipse(x-20,y+30+i,260,358,140,140);

ellipse(x+224,y+20+i,180,218,160,140);

}

/*画侧枝*/

ellipse(x+70,y+34,180,233,140,140);

ellipse(x,y+40,205,255,100,120);

ellipse(x+135,y-30,209,249,72,120);

ellipse(x,y+20,263,301,100,120);

ellipse(x+85,y-10,278,305,100,120);

ellipse(x+100,y-62,282,308,90,120);

篇5:链表的c语言实现④

双向链表的基本运算:

1、查找

假若我们要在一个带表头的双向循环链表中查找数据域为一特定值的某个结点时,我们同样从表头结点往后依次比较各结点数据域的值,若正是该特定值,则返回指向结点的指针,否则继续往后查,直到表尾,

下例就是应用双向循环链表查找算法的一个程序。

#include

#include

#define N 10

typedef struct node

{

char name[20];

struct node *llink,*rlink;

}stud;

stud * creat(int n)

{

stud *p,*h,*s;

int i;

if((h=(stud *)malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

h->name[0]='';

h->llink=NULL;

h->rlink=NULL;

p=h;

for(i=0;i

{

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

p->rlink=s;

printf(“请输入第%d个人的姓名”,i+1);

scanf(“%s”,s->name);

s->llink=p;

s->rlink=NULL;

p=s;

}

h->llink=s;

p->rlink=h;

return(h);

}

stud * search(stud *h,char *x)

{

stud *p;

char *y;

p=h->rlink;

while(p!=h)

{

y=p->name;

if(strcmp(y,x)==0)

return(p);

else p=p->rlink;

}

printf(“没有查找到该数据!”);

}

void print(stud *h)

{

int n;

stud *p;

p=h->rlink;

printf(“数据信息为:n”);

while(p!=h)

{

printf(“%s ”,&*(p->name));

p=p->rlink;

}

printf(“n”);

}

main

{

int number;

char studname[20];

stud *head,*searchpoint;

number=N;

clrscr();

head=creat(number);

print(head);

printf(“请输入你要查找的人的姓名:”);

scanf(“%s”,studname);

searchpoint=search(head,studname);

printf(“你所要查找的人的姓名是:%s”,*&searchpoint->name);

}

2、插入

对于双向循环链表,我们现在可以随意地在某已知结点p前或者p后插入一个新的结点。

假若s,p,q是连续三个结点的指针,若我们要在p前插入一个新结点r,则只需把s的右链域指针指向r,r的左链域指针指向s,r的右链域指针指向p,p的左链域指针指向r即可。

在p,q之间插入原理也一样。

下面就是一个应用双向循环链表插入算法的例子:

#include

#include

#include

#define N 10

typedef struct node

{

char name[20];

struct node *llink,*rlink;

}stud;

stud * creat(int n)

{

stud *p,*h,*s;

int i;

if((h=(stud *)malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

h->name[0]='';

h->llink=NULL;

h->rlink=NULL;

p=h;

for(i=0;i

{

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

p->rlink=s;

printf(“请输入第%d个人的姓名”,i+1);

scanf(“%s”,s->name);

s->llink=p;

s->rlink=NULL;

p=s;

}

h->llink=s;

p->rlink=h;

return(h);

}

stud * search(stud *h,char *x)

{

stud *p;

char *y;

p=h->rlink;

while(p!=h)

{

y=p->name;

if(strcmp(y,x)==0)

return(p);

else p=p->rlink;

}

printf(“没有查找到该数据!”);

}

void print(stud *h)

{

int n;

stud *p;

p=h->rlink;

printf(“数据信息为:n”);

while(p!=h)

{

printf(“%s ”,&*(p->name));

p=p->rlink;

}

printf(“n”);

}

void insert(stud *p)

{

char stuname[20];

stud *s;

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

printf(“请输入你要插入的人的姓名:”);

scanf(“%s”,stuname);

strcpy(s->name,stuname);

s->rlink=p->rlink;

p->rlink=s;

s->llink=p;

(s->rlink)->llink=s;

}

main()

{

int number;

char studname[20];

stud *head,*searchpoint;

number=N;

clrscr();

head=creat(number);

print(head);

printf(“请输入你要查找的人的姓名:”);

scanf(“%s”,studname);

searchpoint=search(head,studname);

printf(“你所要查找的人的姓名是:%sn”,*&searchpoint->name);

insert(searchpoint);

print(head);

}

篇6:链表的c语言实现①

准备:动态内存分配

一、为什么用动态内存分配

但我们未学习链表的时候,如果要存储数量比较多的同类型或同结构的数据的时候,总是使用一个数组,比如说我们要存储一个班级学生的某科分数,总是定义一个float型(存在0.5分)数组:

float score[30];

但是,在使用数组的时候,总有一个问题困扰着我们:数组应该有多大?

在很多的情况下,你并不能确定要使用多大的数组,比如上例,你可能并不知道该班级的学生的人数,那么你就要把数组定义得足够大。这样,你的程序在运行时就申请了固定大小的你认为足够大的内存空间。即使你知道该班级的学生数,但是如果因为某种特殊原因人数有增加或者减少,你又必须重新去修改程序,扩大数组的存储范围。这种分配固定大小的内存分配方法称之为静态内存分配。但是这种内存分配的方法存在比较严重的缺陷,特别是处理某些问题时:在大多数情况下会浪费大量的内存空间,在少数情况下,当你定义的数组不够大时,可能引起下标越界错误,甚至导致严重后果。

那么有没有其它的方法来解决这样的外呢体呢?有,那就是动态内存分配。

所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。从以上动、静态内存分配比较可以知道动态内存分配相对于景泰内存分配的特点:

1、不需要预先分配存储空间;

2、分配的空间可以根据程序的需要扩大或缩小。

二、如何实现动态内存分配及其管理

要实现根据程序的需要动态分配存储空间,就必须用到以下几个函数

1、malloc函数

malloc函数的原型为:

void *malloc (unsigned int size)

其作用是在内存的动态存储区中分配一个长度为size的连续空间。其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针。还有一点必须注意的是,当函数未能成功分配存储空间(如内存不足)就会返回一个NULL指针。所以在调用该函数时应该检测返回值是否为NULL并执行相应的操作。

下例是一个动态分配的程序:

#include

#include

main()

{

int count,*array; /*count是一个计数器,array是一个整型指针,也可以理解为指向一个整型数组的首地址*/

if((array(int *) malloc(10*sizeof(int)))==NULL)

{

printf(“不能成功分配存储空间。”);

exit(1);

}

for (count=0;count〈10;count++) /*给数组赋值*/

array[count]=count;

for(count=0;count〈10;count++) /*打印数组元素*/

printf(“%2d”,array[count]);

}

上例中动态分配了10个整型存储区域,然后进行赋值并打印。例中if((array(int *) malloc(10*sizeof(int)))==NULL)语句可以分为以下几步:

1)分配10个整型的连续存储空间,并返回一个指向其起始地址的整型指针

2)把此整型指针地址赋给array

3)检测返回值是否为NULL

2、free函数

由于内存区域总是有限的,不能不限制地分配下去,而且一个程序要尽量节省资源,所以当所分配的内存区域不用时,就要释放它,以便其它的变量或者程序使用,

这时我们就要用到free函数。

其函数原型是:

void free(void *p)

作用是释放指针p所指向的内存区。

其参数p必须是先前调用malloc函数或calloc函数(另一个动态分配存储区域的函数)时返回的指针。给free函数传递其它的值很可能造成死机或其它灾难性的后果。

注意:这里重要的是指针的值,而不是用来申请动态内存的指针本身。例:

int *p1,*p2;

p1=malloc(10*sizeof(int));

p2=p1;

……

free(p2) /*或者free(p2)*/

malloc返回值赋给p1,又把p1的值赋给p2,所以此时p1,p2都可作为free函数的参数。

malloc函数是对存储区域进行分配的。

free函数是释放已经不用的内存区域的。

所以由这两个函数就可以实现对内存区域进行动态分配并进行简单的管理了。

一、单链表的建立

有了动态内存分配的基础,要实现链表就不难了。

所谓链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。

链表又分为单链表、双向链表和循环链表等。我们先讲讲单链表。

所谓单链表,是指数据接点是单向排列的。一个单链表结点,其结构类型分为两部分:

1、数据域:用来存储本身数据

2、链域或称为指针域:用来存储下一个结点地址或者说指向其直接后继的指针。

例:

typedef struct node

{

char name[20];

struct node *link;

}stud;

这样就定义了一个单链表的结构,其中char name[20]是一个用来存储姓名的字符型数组,指针*link是一个用来存储其直接后继的指针。

定义好了链表的结构之后,只要在程序运行的时候爱数据域中存储适当的数据,如有后继结点,则把链域指向其直接后继,若没有,则置为NULL。

下面就来看一个建立带表头(若未说明,以下所指链表均带表头)的单链表的完整程序。

#include

#include /*包含动态内存分配函数的头文件*/

#define N 10 /*N为人数*/

typedef struct node

{

char name[20];

struct node *link;

}stud; stud * creat(int n) /*建立单链表的函数,形参n为人数*/

{

stud *p,*h,*s; /* *h保存表头结点的指针,*p指向当前结点的前一个结点,*s指向当前结点*/

int i; /*计数器*/

if((h=(stud *)malloc(sizeof(stud)))==NULL) /*分配空间并检测*/

{

printf(“不能分配内存空间!”);

exit(0);

}

h->name[0]=''; /*把表头结点的数据域置空*/

h->link=NULL; /*把表头结点的链域置空*/

p=h; /*p指向表头结点*/

for(i=0;i

{

if((s= (stud *) malloc(sizeof(stud)))==NULL) /*分配新存储空间并检测*/

篇7:链表的c语言实现②

二、单链表的基本运算

建立了一个单链表之后,如果要进行一些如插入、删除等操作该怎么办?所以还须掌握一些单链表的基本算法,来实现这些操作,单链表的基本运算包括:查找、插入和删除。下面我们就一一介绍这三种基本运算的算法,并结合我们建立单链表的例子写出相应的程序。

1、查找

对单链表进行查找的思路为:对单链表的结点依次扫描,检测其数据域是否是我们所要查好的值,若是返回该结点的指针,否则返回NULL。

因为在单链表的链域中包含了后继结点的存储地址,所以当我们实现的时候,只要知道该单链表的头指针,即可依次对每个结点的数据域进行检测。

以下是应用查找算法的一个例子:

#include

#include

#include /*包含一些字符串处理函数的头文件*/

#define N 10

typedef struct node

{

char name[20];

struct node *link;

}stud;

stud * creat(int n) /*建立链表的函数*/

{

stud *p,*h,*s;

int i;

if((h=(stud *)malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

h->name[0]='';

h->link=NULL;

p=h;

for(i=0;i

{

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

p->link=s;

printf(“请输入第%d个人的姓名”,i+1);

scanf(“%s”,s->name);

s->link=NULL;

p=s;

}

return(h);

}

stud * search(stud *h,char *x) /*查找链表的函数,其中h指针是链表的表头指针,x指针是要查找的人的姓名*/

{

stud *p; /*当前指针,指向要与所查找的姓名比较的结点*/

char *y; /*保存结点数据域内姓名的指针*/

p=h->link;

while(p!=NULL)

{

y=p->name;

if(strcmp(y,x)==0) /*把数据域里的姓名与所要查找的姓名比较,若相同则返回0,即条件成立*/

return(p); /*返回与所要查找结点的地址*/

else p=p->link;

}

if(p==NULL)

printf(“没有查找到该数据!”);

}

main

{

int number;

char fullname[20];

stud *head,*searchpoint; /*head是表头指针,searchpoint是保存符合条件的结点地址的指针*/

number=N;

head=creat(number);

printf(“请输入你要查找的人的姓名:”);

scanf(“%s”,fullname);

searchpoint=search(head,fullname); /*调用查找函数,并把结果赋给searchpoint指针*/

}

2、插入(后插)

假设在一个单链表中存在2个连续结点p、q(其中p为q的直接前驱),若我们需要在p、q之间插入一个新结点s,那么我们必须先为s分配空间并赋值,然后使p的链域存储s的地址,s的链域存储q的地址即可,

(p->link=s;s->link=q),这样就完成了插入操作。

下例是应用插入算法的一个例子:

#include

#include

#include

#define N 10

typedef struct node

{

char name[20];

struct node *link;

}stud;

stud * creat(int n) /*建立单链表的函数*/

{

stud *p,*h,*s;

int i;

if((h=(stud *)malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

h->name[0]='';

h->link=NULL;

p=h;

for(i=0;i

{

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

p->link=s;

printf(“请输入第%d个人的姓名:”,i+1);

scanf(“%s”,s->name);

s->link=NULL;

p=s;

}

return(h);

}

stud * search(stud *h,char *x) /*查找函数*/

{

stud *p;

char *y;

p=h->link;

while(p!=NULL)

{

y=p->name;

if(strcmp(y,x)==0)

return(p);

else p=p->link;

}

if(p==NULL)

printf(“没有查找到该数据!”);

}

void insert(stud *p) /*插入函数,在指针p后插入*/

{

char stuname[20];

stud *s; /*指针s是保存新结点地址的*/

if((s= (stud *) malloc(sizeof(stud)))==NULL)

{

printf(“不能分配内存空间!”);

exit(0);

}

printf(“请输入你要插入的人的姓名:”);

scanf(“%s”,stuname);

strcpy(s->name,stuname); /*把指针stuname所指向的数组元素拷贝给新结点的数据域*/

s->link=p->link; /*把新结点的链域指向原来p结点的后继结点*/

p->link=s; /*p结点的链域指向新结点*/

}

main()

{

int number;

char fullname[20]; /*保存输入的要查找的人的姓名*/

stud *head,*searchpoint;

number=N;

head=creat(number); /*建立新链表并返回表头指针*/

printf(“请输入你要查找的人的姓名:”);

scanf(“%s”,fullname);

searchpoint=search(head,fullname); /*查找并返回查找到的结点指针*/

insert(searchpoint); /*调用插入函数*/

}

篇8:go语言实现顺序存储的栈

作者:OSC首席键客 字体:[增加 减小] 类型:

这篇文章主要介绍了go语言实现顺序存储的栈,实例分析了Go语言实现顺序存储的栈的原理与各种常见的操作技巧,需要的朋友可以参考下

本文实例讲述了go语言实现顺序存储的栈,分享给大家供大家参考。具体如下:

1. sequence.go代码如下:

代码如下:

////////

// 顺序存储的栈

////////

package sequence

const MAXSIZE = 20

type Stack struct {

Data [MAXSIZE]int //存储栈元素

Top int         //指向栈顶,总是指向顶部元素,空时为-1

}

//压栈

//d:栈元素

func (s *Stack) Push(d int) bool {

if s.Top+1 > MAXSIZE {

return false

}

s.Data[s.Top+1] = d

s.Top++

return true

}

//弹栈

func (s *Stack) Pop() int {

if s.Top == -1 {

return 0

}

s.Data[s.Top] = 0

d := s.Data[s.Top]

s.Top--

return d

}

//取栈的容量

func (s *Stack) GetVol() int {

return len(s.Data)

}

//取栈的长度

func (s *Stack) GetLength() int {

c := s.Top + 1

return c

}

2. main.go代码如下:

代码如下:

package main

import (

“fmt”

“stack/sequence”

)

func main() {

//初始化一个栈

var s sequence.Stack

s.Top = -1

//压入10个元素

for i := 1; i <= 10; i++ {

s.Push(i)

}

fmt.Println(s)

fmt.Println(s.GetVol())   //容量

fmt.Println(s.GetLength()) //长度

//弹出一个元素

s.Pop()

s.Pop()

fmt.Println(s)

fmt.Println(s.GetVol())   //容量

fmt.Println(s.GetLength()) //长度

}

希望本文所述对大家的Go语言程序设计有所帮助,

篇9:C语言接口与实现实例

一个模块有两部分组成:接口和实现,接口指明模块要做什么,它声明了使用该模块的代码可用的标识符、类型和例程,实现指明模块是如何完成其接口声明的目标的,一个给定的模块通常只有一个接口,但是可能会有许多种实现能够提供接口所指定的功能。每个实现可能使用不同的算法和数据结构,但是它们都必须符合接口所给出的使用说明。客户调用程序是使用某个模块的一段代码,客户调用程序导入接口,而实现导出接口。由于多个客户调用程序是共享接口和实现的,因此使用实现的目标代码避免了不必要的代码重复,同时也有助于避免错误,因为接口和实现只需一次编写和调试就可多次使用。

本文地址:www.cnblogs.com/archimedes/p/c-interfaces-implementations.html,转载请注明源地址。

接口

接口只需要指明客户调用程序可能使用的标识符即可,应尽可能地隐藏一些无关的表示细节和算法,这样客户调用程序可以不必依赖于特定的实现细节。这种客户调用程序和实现之间的依赖--耦合----可能会在实现改变时引起错误,当这种依赖性埋藏在一些关于实现隐藏的或是不明确的假设中时,这些错误可能很难修复,因此一个设计良好且描述精确的接口应该尽量减少耦合。

C语言对接口和实现的分离只提供最基本的支持,但是简单的约定能给接口/实现方法论带来巨大的好处。在C中,接口在头文件声明,头文件声明了客户调用程序可以使用的宏、类型、数据结构、变量以及例程。用户使用C语言的预处理指令#include导入接口。

下面的例子说明了本篇文章的接口中所使用的一些约定、接口:

arith.h

该接口的名字为Arith,接口头文件也相应地命名为arith.h,接口的名字以前缀的形式出现在接口的每个标识符中。模块名不仅提供了合适的前缀,而且还有助于整理客户调用程序代码。

Arith接口还提供了一些标准C函数库中没有但是很有用的函数,并为出发和取模提供了良好的定义,而标准C中并没有给出这些操作的定义和只提供基于实现的定义。

实现

一个实现导出一个接口,它定义了必要的变量和函数以提供接口所规定的功能,在C语言中,一个实现是由一个或多个.c文件提供的,一个实现必须提供其导出的接口所指定的功能。实现应包含接口的.h文件,以保证它的定义和接口的声明时一致的。

Arith_min和Arith_max返回其整型参数中的最小值和最大值:

int Arith_max(int x, int y) {

return x > y ? x : y;

}

int Arith_min(int x, int y) {

return x > y ? y : x;

}

Arith_div返回y除以x得到的商,Arith_mod返回相应的余数。当x与y同号的时候,Arith_div(x,y)等价于x/y,Arith_mod(x,y)等价于x%y

当x与y的符号不同的时候,C的内嵌操作的返回值就取决于具体的实现:

eg.如果-13/5=2,-13%5=-3,如果-13/5=-3,-13%5=2

标准库函数总是向零取整,因此div(-13,2)=-2,Arith_div和Arith_mod的语义同样定义好了:它们总是趋近数轴的左侧取整,因此Arith_div(-13,5)=-3,Arith_div(x,y)是不超过实数z的最大整数,其中z满足z*y=x。

Arith_mod(x,y)被定义为x-y*Arith_div(x,y)。因此Arith_mod(-13,5)=-13-5*(-3)=2

函数Arith_ceiling和Arith_floor遵循类似的约定,Arith_ceiling(x,y)返回不小于实数商x/y的最小整数

Arith_floor(x,y)返回不超过实数商x/y的最大整数

完整实现代码如下:

arith.c

抽象数据类型

抽象数据类型(abstract data type,ADT)是一个定义了数据类型以及基于该类型值提供的各种操作的接口

一个高级类型是抽象的,因为接口隐藏了它的表示细节,以免客户调用程序依赖这些细节,

下面是一个抽象数据类型(ADT)的规范化例子--堆栈,它定义了该类型以及五种操作:

stack.h

实现

包含相关头文件:

#include

#include “assert.h”

#include “mem.h”

#include “stack.h”

#define T Stack_T

Stack_T的内部是一个结构,该结构有个字段指向一个栈内指针的链表以及一个这些指针的计数:

struct T {

int count;

struct elem {

void *x;

struct elem *link;

} *head;

};

Stack_new分配并初始化一个新的T:

T Stack_new(void) {

T stk;

NEW(stk);

stk->count = 0;

stk->head = NULL;

return stk;

}

其中NEW是一个另一个接口中的一个分配宏指令。NEW(p)将分配该结构的一个实例,并将其指针赋给p,因此Stack_new中使用它就可以分配一个新的Stack_T

当count=0时,Stack_empty返回1,否则返回0:

int Stack_empty(T stk) {

assert(stk);

return stk->count == 0;

}

assert(stk)实现了可检查的运行期错误,它禁止空指针传给Stack中的任何函数。

Stack_push和Stack_pop从stk->head所指向的链表的头部添加或移出元素:

void Stack_push(T stk, void *x) {

struct elem *t;

assert(stk);

NEW(t);

t->x = x;

t->link = stk->head;

stk->head = t;

stk->count++;

}

void *Stack_pop(T stk) {

void *x;

struct elem *t;

assert(stk);

assert(stk->count > 0);

t = stk->head;

stk->head = t->link;

乘法口诀表,C语言实现

c语言:模拟实现一个输入密码自动取款的程序

实现的反义词

实现梦想作文

实现的近义词

c语言面试题

C语言心得体会

c语言学习方法

c语言学习心得

go语言实现字符串base64编码的方法

《栈的实现(C语言实现)(共9篇).doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式

点击下载本文文档