线性表是n个数据元素组成的有限序列,按照存储的方式分为顺序和链式。今天用C对顺序和链式分别做点练习。
(下面有很大一部分的代码是用vim写的,贴到博客上就有些格式问题了,不知道怎么解决。。)
纯C+顺序表 完成迷你选座系统
谁说简单数组不强大?
用简单的数组完成小型的选座系统建设:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct Node{
int used;
char sno[20],sname[20];
};
struct seat{
struct Node st[MAX];
int length;
};
/* 写入数据到顺序表中 */
void sql_init(struct seat *sql){
FILE *fin=fopen("/home/edemon/Documents/data","r");
if(fin==NULL){
printf("the file can't be open.\n");
return ;
}
/*feof(FILE *stream)用来侦测是否读取到了文件尾,尾数stream为fopen()所返回之文件指针。
如果已到文件尾则返回非零值,其他情况返回0。 */
for(int i=1;i<MAX;i++) sql->st[i].used=0;
while(feof(fin)==0){
int d=-1;
char s1[20],s2[20];
fscanf(fin,"%d%s%s",&d,s1,s2);
if(feof(fin)>0) break;
strcpy(sql->st[d].sno,s1);
strcpy(sql->st[d].sname,s2);
sql->st[d].used=1;
sql->length++;
}
}
/* 展示座位的使用情况 */
void show(struct seat *sql){
puts("");
for(int i=1;i<MAX;i++){
if(sql->st[i].used==0) printf("the No.%d seat is empty.\n",i);
else {
printf("the No.%d seat is used, information: %s %s\n",i,sql->st[i].sno,sql->st[i].sname);
}
}
}
/* 写入文件 */
void write(struct seat *sql){
FILE *fout=fopen("/home/edemon/Documents/data","w");
for(int i=1;i<MAX;i++){
if(sql->st[i].used){
fprintf(fout,"%-4d%10s%10s\n",i,sql->st[i].sno,sql->st[i].sname);
}
}
}
int main()
{
/*FILE *fout;
fout=fopen("/home/edemon/Documents/data","w");
int id=1;
char sno[20]="20130001",name[20]="Elena";
fprintf(fout,"%-4d%10s%10s\n",id,sno,name);*/
struct seat sql;
sql.length=0;
struct Node e;
sql_init(&sql);
int key;
char number[20];
while(1){
//fflush(stdin); /* 刷新标准输入缓冲区 */
//system("clear"); /* for windows: system("cls"); it's to clear screen */
system("cat /home/edemon/Documents/data > /home/edemon/Documents/copy.txt");
printf("****** 欢迎使用选座系统 ******\n");
printf("注意:非正常退出会使得文件中的数据丢失\n");
printf("* 1-查看所有的座位使用信息 *\n");
printf("* 2-查询某一座位的使用信息 *\n");
printf("* 3-输号选座 *\n");
printf("* 4-释放座位 *\n");
printf("* 0-退出系统 *\n");
printf("**************************************\n");
int ch;
scanf("%d",&ch);
switch(ch){
case 0:
write(&sql);
return 0;
case 1:
show(&sql);
//getchar();
break;
case 2:
printf("请输入座位号: ");
int d=0;
scanf("%d",&d);
if(sql.st[d].used==0) printf("the No.%d seat is empty\n",d);
else {
printf("the No.%d seat is used, information: %s %s\n",d,sql.st[d].sno,sql.st[d].sname);
}
break;
case 3:
enter: printf("\n请输入空的座位号: "); scanf("%d",&key);
if(sql.st[key].used){
printf("该座位已经被使用\n");
goto enter;
}
printf("\n你的学号: "); scanf("%s",e.sno);
for(int i=1;i<MAX;i++){
if(strcmp(sql.st[i].sno,e.sno)==0){
printf("已有相同的学号正在使用座位No.%d,请确认没有输错学号。\
输入3继续选座,输入其他数字退出。\n",i);
scanf("%d",&key);
if(key==3) goto enter;
else goto final;
}
}
printf("\n你的姓名:"); scanf("%s",e.sname);
e.used=1;
sql.st[key]=e;
write(&sql);
break;
case 4:
printf("请输入学号: "); scanf("%s",number);
for(int i=1;i<MAX;i++){
if(strcmp(sql.st[i].sno,number)==0){
sql.st[i].used=0;
}
}
write(&sql);
printf("谢谢你的合作\n");
break;
default:
printf("请输入正确的指令。\n");
break;
}
final:;
}
return 0;
}
关于指针
指针本身只是一个整数(地址),但其所指向的对象是丰富多样的,正因为寻址高效,所以处理数据很迅速。
源码:
#include <stdio.h>
int main(){
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p=&a;
for(int i=0;i<10;i++){
/*输出内存地址要用%p输出,%d输出范围比指针地址储存的范围小*/
printf("%p %d\n",p,*p);
p++;
}
return 0;
}
/*
输出:
0x7fff1b077870 1
0x7fff1b077874 2
0x7fff1b077878 3
0x7fff1b07787c 4
0x7fff1b077880 5
0x7fff1b077884 6
0x7fff1b077888 7
0x7fff1b07788c 8
0x7fff1b077890 9
0x7fff1b077894 10
*/
来看一个链表:
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int val;
struct node *next;
}*List,Node;
typedef struct node Node;
int main(){
List p=(Node*)malloc(sizeof(Node));
List p2=p;
for(int i=1;i<11;i++){
List temp=(Node*)malloc(sizeof(Node));
temp->val=i;
temp->next=NULL;
p->next=temp;
p=p->next;
}
p=p2->next;
while(p){
printf("%p %d\n",p,p->val);
p=p->next;
}
return 0;
}
/*
output:
0xc71050 2
0xc71070 3
0xc71090 4
0xc710b0 5
0xc710d0 6
0xc710f0 7
0xc71110 8
0xc71130 9
0xc71150 10
*/
可以看出,结点的地址顺序和值的顺序保持一致的。
链表操作
链表逆序:
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int a;
struct node *next;
}*List,list;
List create(){
List head=(list*)malloc(sizeof(list));
List p=head;
for(int i=1;i<10;i++){
List t=(list*)malloc(sizeof(list));
t->a=i;
t->next=NULL;
p->next=t;
p=p->next;
}
return head;
}
List reverse(List head){ // p3 p2 p1
List p1,p2,p3;
p1=NULL;
p2=head->next;
p3=NULL;
while(p2!=NULL){
p1=p2->next;
p2->next=p3;
p3=p2;
p2=p1;
}
return p3;
}
void print(List head){
List p=head;
while(p){
printf("%3d",p->a);
p=p->next;
}
puts("");
}
int main(){
List head=create();
print(head->next);
head=reverse(head);
print(head);
return 0;
}
/*
output:
1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1
*/
链表删除节点
bool delet(List head,int i){
int c=1;
List p=head->next,q=head;
while(p && c<i){
p=p->next;
q=q->next;
c++;
}
if(c!=i) return false;
q->next=p->next;
free(p);
return true;
}
链表增加节点(在i位置的后面插入值为number的结点):
bool insert(List head,int i,int number){
int c=1;
List p=head->next;
while(p && c<i){
p=p->next;
c++;
}
if(c!=i) return false;
List node=(list *)malloc(sizeof(list));
node->a=number;
node->next=p->next;
p->next=node;
}
合并有序链表(两个有序链表合并后依然有序):
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int a;
struct node *next;
}*List,list;
List create(int start,int end){
List head=(list*)malloc(sizeof(list));
List p=head;
for(int i=start;i<=end;i++){
List t=(list*)malloc(sizeof(list));
t->a=i;
t->next=NULL;
p->next=t;
p=p->next;
}
return head;
}
void print(List head){
List p=head;
while(p){
printf("%3d",p->a);
p=p->next;
}
puts("");
}
List merge(List h1,List h2){
List p=(list*)malloc(sizeof(list));
List r=p;
h1=h1->next;
h2=h2->next;
while(h1 || h2){
if(h1==NULL){
p->next=h2;
p=p->next;
h2=h2->next;
continue;
}
if(h2==NULL){
p->next=h1;
p=p->next;
h1=h1->next;
continue;
}
if(h1->a>h2->a){
p->next=h2;
p=p->next;
h2=h2->next;
}
else {
p->next=h1;
p=p->next;
h1=h1->next;
}
}
return r;
}
int main(){
List h1=create(1,10);
List h2=create(6,15);
List h=merge(h1,h2);
print(h);
return 0;
}
/*
output:
0 1 2 3 4 5 6 6 7 7 8 8 9 9 10 10 11 12 13 14 15
*/
输出一个链表的中间结点:
1 2 3 4 5 6 7 8 9
5
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int a;
struct node *next;
}*List,list;
List create(){
List head=(list*)malloc(sizeof(list));
List p=head;
for(int i=1;i<10;i++){
List t=(list*)malloc(sizeof(list));
t->a=i;
t->next=NULL;
p->next=t;
p=p->next;
}
return head;
}
void print(List head){
List p=head;
while(p){
printf("%3d",p->a);
p=p->next;
}
puts("");
}
/* 步长为1和步长为2的指针进行判断 */
List mid(List head){
List one=head;
List two=head;
while(two){
one=one->next;
if(two) two=two->next;
if(two) two=two->next;
}
return one;
}
int main(){
List head=create();
print(head->next);
List m=mid(head);
printf("%d\n",m->a);
return 0;
}