数据结构学习笔记 --- 线性表 (应用举例)

1. 引言 


本文主要讲解一个线性表 (应用举例


2. 具有实际意义的线性链表


#include "ds.h"

using namespace std;

typedef 	int 		ElemType;

// 结点类型
typedef struct LNode{
	ElemType 	data;
	struct LNode	*next;
}*Link,*Position;

typedef struct LinkList{
	Link 	head, tail;   	// 分别指向线性链表中的头结点和最后一个结点
	int		len;		// 指示线性链表中数据元素的个数
}LinkList;

void MakeNode(Link &p, ElemType e);
void FreeNode(Link &p);
void InitList(LinkList &L);
void ClearList(LinkList &L);
void DestroyList(LinkList &L);
// h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前, 形参增加L,因为需修改L
void InsFirst(LinkList &L,Link h,Link s);
// h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。
// 若链表为空(h指向尾结点),q=NULL,返回FALSE
Status DelFirst(LinkList &L, Link h, Link &q);

// 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的
// 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
void Append(LinkList &L, Link s);
// 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置。若无前驱,则返回NULL
Position PriorPos(LinkList L, Link p);
// 删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Status Remove(LinkList &L, Link &q);
// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
// 并修改指针p指向新插入的结点
void InsBefore(LinkList &L, Link &p, Link s);

// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
// 并修改指针p指向新插入的结点
void InsAfter(LinkList &L,Link &p,Link s);
// 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
void SetCurElem(Link p, ElemType e);
ElemType GetCurElem(Link p);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Position GetHead(LinkList L);
Position GetLast(LinkList L);
Position NextPos(Link p);
// 返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR。i=0为头结点
Status LocatePos(LinkList L, int i, Link &p);
// 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
// 若不存在这样的元素,则返回NULL
Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));

void ListTraverse(LinkList L, void(*visit)(ElemType) );
// 已知L为有序线性链表,将元素e按非降序插入在L中。
void OrderInsert(LinkList &L, ElemType e, int (*com)(ElemType, ElemType));
// 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中
// 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数
// compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
Status LocateElem(LinkList L,ElemType e,Position &q,int(*compare)(ElemType,ElemType));


// 分配由p指向的值为e的结点。若分配失败,则退出
void MakeNode(Link &p, ElemType e)
{
	p = (Link)malloc(sizeof(LNode));
	if (!p)
		exit(ERROR);
	memcpy(&(p->data), &e, sizeof(ElemType));
}

// 释放p所指结点
void FreeNode(Link &p)
{
	free(p);
	p = NULL;
}

// 构造一个空的线性链表L
void InitList(LinkList &L)
{
	Link 	p;
	p = (Link)malloc(sizeof(LNode)); // 生成头结点
	if (p)
	{
		p->next = NULL;
		L.head = L.tail = p;
		L.len = 0;
	}
	else
		exit(ERROR);
}

// 将线性链表L重置为空表,并释放原链表的结点空间
void ClearList(LinkList &L)
{
	Link 	p, q;
	if (L.head != L.tail)
	{
		p = q = L.head->next;
		L.head->next = NULL;
		while (p != L.tail)
		{
			q = p->next;
			free(p);
			p = q;
		}
		free(q);  // 释放尾节点
		L.tail = L.head;
		L.len = 0;
	}
}

// 销毁线性链表L,L不再存在
void DestroyList(LinkList &L)
{
	ClearList(L);
	FreeNode(L.head);
	L.tail = NULL;
	L.len = 0;
}

// h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前, 形参增加L,因为需修改L
void InsFirst(LinkList &L,Link h,Link s)
{
	s->next = h->next;
	h->next = s;
	if (h == L.tail)
		L.tail = s;
	L.len++;
}

// h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。
// 若链表为空(h指向尾结点),q=NULL,返回FALSE
Status DelFirst(LinkList &L, Link h, Link &q)
{
	q = h->next;
   	if (q) // 链表非空
   	{
     		h->next = q->next;
     		if(!h->next) // 删除尾结点
       			L.tail = h; // 修改尾指针
     		L.len--;
     		return OK;
   	}
  	 else
     		return FALSE; // 链表空
}

// 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的
// 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
void Append(LinkList &L, Link s)
{
	int 	i = 1;
	Link 	p = s;

	if (NULL == p)
		return;
	L.tail->next = s;
	while (p->next)
	{
		i++;
		p = p->next;
	}
	L.tail = p;
	L.len += i;
}

// 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置。若无前驱,则返回NULL
Position PriorPos(LinkList L, Link p)
{
	Link 	s = L.head->next;
	
	if (p == NULL || p == L.head || p == s)
		return NULL;

	while (s->next)
	{
		if (p == s->next)
			return s;
		s = s->next;
	}
	
}
// 删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Status Remove(LinkList &L, Link &q)
{
	Link p=L.head;
   	if(L.len==0) // 空表
   	{
    	q=NULL;
     	return FALSE;
   	}
   	while(p->next!=L.tail)
     	p=p->next;
   	q=L.tail;
   	p->next=NULL;
   	L.tail=p;
   	L.len--;
   	return OK;
}
// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
// 并修改指针p指向新插入的结点
void InsBefore(LinkList &L, Link &p, Link s)
{
	Link 	temp = L.head;
	
	while (temp->next != p)
	{
		temp = temp->next;
	}
	
	s->next = temp->next;
	temp->next = s;
	
	p = s;
	L.len++;
}

// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
// 并修改指针p指向新插入的结点
void InsAfter(LinkList &L,Link &p,Link s)
{
	if (p == L.tail)
	{
		p->next = s;
		s->next = NULL;
		L.tail = s;
	}
	else
	{		
		s->next = p->next;
		p->next = s;
	}
	p = s;
	L.len++;

}
// 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
void SetCurElem(Link p, ElemType e)
{
	memcpy(&(p->data), &e, sizeof(sizeof(ElemType)));
}
ElemType GetCurElem(Link p)
{
	return p->data;
}
Status ListEmpty(LinkList L)
{
	if (0 == L.len)
		return TRUE;
	else
		return FALSE;
}
int ListLength(LinkList L)
{
	return L.len;
}
Position GetHead(LinkList L)
{
	return L.head;
}
Position GetLast(LinkList L)
{
	return L.tail;
}
Position NextPos(Link p)
{ // 已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置。若无后继,则返回NULL
	return p->next;
}
// 返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR。i=0为头结点
Status LocatePos(LinkList L, int i, Link &p)
{
	int 	j = 0;
	p = L.head;
	
	while (j < i && p != NULL)
	{
		j++;
		p = p->next;
	}
	
	if (j > i || !p )
		return ERROR;
	
	return OK;
}
// 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
// 若不存在这样的元素,则返回NULL
Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
	Link 	p = L.head->next;
	
	while (p && !compare(e, p->data))
		p = p->next;
	return p;
}

void ListTraverse(LinkList L, void(*visit)(ElemType) )
{
	Link 	p = L.head->next;
	
	while (p)
	{
		visit(p->data);
		p = p->next;
	}
	printf("\n");
}
// 已知L为有序线性链表,将元素e按非降序插入在L中。
void OrderInsert(LinkList &L, ElemType e, int (*com)(ElemType, ElemType))
{
	Link o,p,q;
   	q=L.head;
   	p=q->next;
   	while(p!=NULL&&com(p->data,e)<0) // p不是表尾且元素值小于e
   	{
     	q=p;
     	p=p->next;
   	}
   	o=(Link)malloc(sizeof(LNode)); // 生成结点
   	o->data=e; // 赋值
   	q->next=o; // 插入
   	o->next=p;
   	L.len++; // 表长加1
   	if(!p) // 插在表尾
     	L.tail=o; // 修改尾结点
}
// 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中
// 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数
// compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
Status LocateElem(LinkList L,ElemType e,Position &q,int(*compare)(ElemType,ElemType))
{
   Link p=L.head,pp;
   do
   {
     pp=p;
     p=p->next;
   }while(p&&(compare(p->data,e)<0)); // 没到表尾且p->data.expn<e.expn
   if(!p||compare(p->data,e)>0) // 到表尾或compare(p->data,e)>0
   {
     q=pp;
     return FALSE;
   }
   else // 找到
   {
     q=p;
     return TRUE;
   }
}

 Status equal(ElemType c1,ElemType c2)
 { // 判断是否相等的函数
   if(c1==c2)
     return TRUE;
   else
     return FALSE;
 }

 int comp(ElemType a,ElemType b)
 { // 根据a<、=或>b,分别返回-1、0或1
   if(a==b)
     return 0;
   else
     return (a-b)/abs(a-b);
 }

void print(ElemType e)
{
	printf("%d ", e);
}

int main()
 {
   Link p,h;
   LinkList L;
   Status i;
   int j,k;
   InitList(L); // 初始化空的线性表L
   for(j=1;j<=2;j++)
   {
     MakeNode(p,j); // 生成由p指向、值为j的结点
     InsFirst(L,L.tail,p); // 插在表尾
   }
   OrderInsert(L,0,comp); // 按升序插在有序表头
   for(j=0;j<=3;j++)
   {
     i=LocateElem(L,j,p,comp);
     if(i)
       printf("链表中有值为%d的元素。\n",p->data);
     else
       printf("链表中没有值为%d的元素。\n",j);
   }
   printf("输出链表:");
   ListTraverse(L,print); // 输出L
   for(j=1;j<=4;j++)
   {
     printf("删除表头结点:");
     DelFirst(L,L.head,p); // 删除L的首结点,并以p返回
     if(p)
       printf("%d\n",GetCurElem(p));
     else
       printf("表空,无法删除 p=%u\n",p);
   }
   printf("L中结点个数=%d L是否空 %d(1:空 0:否)\n",ListLength(L),ListEmpty(L));
   MakeNode(p,10);
   p->next=NULL; // 尾结点
   for(j=4;j>=1;j--)
   {
     MakeNode(h,j*2);
     h->next=p;
     p=h;
   } // h指向一串5个结点,其值依次是2 4 6 8 10
   Append(L,h); // 把结点h链接在线性链表L的最后一个结点之后
   OrderInsert(L,12,comp); // 按升序插在有序表尾头
   OrderInsert(L,7,comp); // 按升序插在有序表中间
   printf("输出链表:");
   ListTraverse(L,print); // 输出L
   for(j=1;j<=2;j++)
   {
     p=LocateElem(L,j*5,equal);
     if(p)
       printf("L中存在值为%d的结点。\n",j*5);
     else
       printf("L中不存在值为%d的结点。\n",j*5);
   }
   for(j=1;j<=2;j++)
   {
     LocatePos(L,j,p); // p指向L的第j个结点
     h=PriorPos(L,p); // h指向p的前驱
     if(h)
       printf("%d的前驱是%d。\n",p->data,h->data);
     else
       printf("%d没前驱。\n",p->data);
   }
   k=ListLength(L);
   for(j=k-1;j<=k;j++)
   {
     LocatePos(L,j,p); // p指向L的第j个结点
     h=NextPos(p); // h指向p的后继
     if(h)
       printf("%d的后继是%d。\n",p->data,h->data);
     else
       printf("%d没后继。\n",p->data);
   }
   printf("L中结点个数=%d L是否空 %d(1:空 0:否)\n",ListLength(L),ListEmpty(L));
   p=GetLast(L); // p指向最后一个结点
   SetCurElem(p,15); // 将最后一个结点的值变为15
   printf("第1个元素为%d 最后1个元素为%d\n",GetCurElem(GetHead(L)->next),GetCurElem(p));
   MakeNode(h,10);
   InsBefore(L,p,h); // 将10插到尾结点之前,p指向新结点
   p=p->next; // p恢复为尾结点
   MakeNode(h,20);
   InsAfter(L,p,h); // 将20插到尾结点之后
   k=ListLength(L);
   printf("依次删除表尾结点并输出其值:");
   for(j=0;j<=k;j++)
     if(!(i=Remove(L,p))) // 删除不成功
       printf("删除不成功 p=%u\n",p);
     else
       printf("%d ",p->data);
   MakeNode(p,29); // 重建具有1个结点(29)的链表
   InsFirst(L,L.head,p);
   DestroyList(L); // 销毁线性链表L
   printf("销毁线性链表L之后: L.head=%u L.tail=%u L.len=%d\n",L.head,L.tail,L.len);
 }

3. 利用无头结点的单链表处理学生健康登记表


// 利用无头结点的单链表处理学生健康登记表
#include "ds.h"

#define 	NAMELEN 	40 
#define 	CLASSLEN 	20 

struct stud
{
	char 	name[NAMELEN+1];
	long 	num;
	char 	sex;
	int		age;
	char 	Class[CLASSLEN+1];
	int 	health;
};

typedef stud ElemType; 

typedef struct LNode{
	ElemType 		data;
	struct LNode	*next;
}LNode, *LinkList;

//#define 	DestroyList 	ClearList

void InitList(LinkList &L);
void ClearList(LinkList &L);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Status GetElem(LinkList L, int i, ElemType &e);
int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType));
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e);
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e);
Status ListInsert(LinkList &L, int i, ElemType e);
Status ListDelete(LinkList &L, int i, ElemType &e);
void ListTraverse(LinkList L, void (*vi)(ElemType));

void InsertAscend(LinkList &L,ElemType e,int(*compare)(ElemType,ElemType));
LinkList Point(LinkList L,ElemType e,Status(*equal)(ElemType,ElemType),LinkList &p);
Status DeleteElem(LinkList &L,ElemType &e,Status(*equal)(ElemType,ElemType));
void Print(stud e);
Status compare(ElemType a, ElemType b);



void InitList(LinkList &L)
{
	L = NULL;
}
void ClearList(LinkList &L)
{
	LinkList p = L, q;
	
	while (p)
	{
		q = p->next;
		free(p);
		p = q;
	}
	
	L = NULL;
}
Status ListEmpty(LinkList L)
{
	if (L == NULL)
		return TRUE;
	else
		return FALSE;
}
int ListLength(LinkList L)
{
	int 		i = 0;
	LinkList	p = L;
	
	while (p)
	{
		p = p->next;
		i++;
	}
	
	return i;
}
Status GetElem(LinkList L, int i, ElemType &e)
{
	int 		j = 1;
	LinkList 	p = L;
	
	while (p && j < i)
	{
		p = p->next;
	}
	
	if (!p || j > i)
		return ERROR;
	
	memcpy(&e, &(p->data), sizeof(ElemType));
	return OK;
	
}
int LocateElem(LinkList L, ElemType e, Status (*compare)(ElemType, ElemType))
{
	LinkList 		p = L;
	int 			j = 0;
	
	while (p)
	{
		j++;
		if (compare(e, p->data))
			return j;
		p = p->next;
	}
	
	return 0;
}

#ifdef PRIOR_NEXT
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{
	LinkList 	p = L, q;
	
	while (p->next) 
	{
		q = p->next;
		if (cur_e == q->data)
		{
			pre_e = p->data;
			return OK;
		}
		p = q;
	}
	
	return ERROR;
}
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{
	LinkList 	p = L;
	
	while (p->next)
	{
		if (cur_e == p->data)
		{
			next_e = p->next->data;
			return OK;
		}
		p = p->next;
	}
	
	return ERROR;
}
#endif
Status ListInsert(LinkList &L, int i, ElemType e)
{
	LinkList 	p = L, s;
	int 		j = 1;
	
	s = (LinkList)malloc(sizeof(LNode));
	memcpy(&(s->data), &e, sizeof(ElemType));	
	
	if (1 == i)
	{
		s->next = L;
		L = s;
	}
	else 
	{
		while (p && j < i - 1) 
		{
			j++;
			p = p->next;
		}
		
		if (!p || j > i-1)
			return ERROR;
		
		s->next = p->next;
		p->next = s;
	}
	
	return OK;
}
Status ListDelete(LinkList &L, int i, ElemType &e)
{
	LinkList 	p = L, q;
	int 		j = 1;
	
	if (1 == i)
	{
		q = L;
		L = p->next;
	}
	else
	{
		while (p->next && j < i - 1)
		{
			j++;
			p = p->next;
		}
		
		if (!p->next || j > i-1)
			return ERROR;
		q = p->next;
		p->next = q->next;
	}
	memcpy(&e, &(q->data), sizeof(ElemType));
	free(q);
	q = NULL;
	return OK;
}
void ListTraverse(LinkList L, void (*vi)(ElemType))
{
	LinkList p = L;
	while (p)
	{
		vi(p->data);
		p = p->next;
	}
	printf("\n");
}


void InsertAscend(LinkList &L,ElemType e,int(*compare)(ElemType,ElemType))
{ // 按关键字非降序将e插入表L。函数compare()返回值为:形参1的关键字-形参2的关键字
   	LinkList q=L;
   	if(!L||compare(e,L->data)<=0) // 链表空或e的关键字小于等于首结点的关键字
     	ListInsert(L,1,e); // 将e插在表头,在bo2-8.cpp中
   	else
   	{
    	while(q->next&&compare(q->next->data,e)<0) // q不是尾结点且q的下一结点关键字<e的关键字
       	q=q->next;
     	ListInsert(q,2,e); // 插在q所指结点后(将q作为头指针)
   	}
}

LinkList Point(LinkList L,ElemType e,Status(*equal)(ElemType,ElemType),LinkList &p)
{ // 查找表L中满足条件的结点。如找到,返回指向该结点的指针,p指向该结点的前驱(若该结点是
   // 首元结点,则p=NULL)。如表L中无满足条件的结点,则返回NULL,p无定义。
   // 函数equal()的两形参的关键字相等,返回OK;否则返回ERROR
	int i,j;
   	i=LocateElem(L,e,equal);
   	if(i) // 找到
   	{
     	if(i==1) // 是首元结点
     	{
       		p=NULL;
       		return L;
     	}
     	p=L;
     	for(j=2;j<i;j++)
       		p=p->next;
     	return p->next;
   	}
   	return NULL; // 没找到
}

Status DeleteElem(LinkList &L,ElemType &e,Status(*equal)(ElemType,ElemType))
{ // 删除表L中满足条件的结点,并返回TRUE;如无此结点,则返回FALSE。
   // 函数equal()的两形参的关键字相等,返回OK;否则返回ERROR
   LinkList p,q;
   q=Point(L,e,equal,p);
   if(q) // 找到此结点,且q指向该结点
   {
     if(p) // 该结点不是首元结点,p指向其前驱
       ListDelete(p,2,e); // 将p作为头指针,删除第2个结点
     else // 该结点是首元结点
       ListDelete(L,1,e);
     return TRUE;
   }
   return FALSE;
}

 char sta[3][9]={"health","General","psyhical"}; // 健康状况(3类)
FILE *fp; // 全局变量

void Print(stud e)
{ // 显示记录e的内容
  printf("%-8s %6ld",e.name,e.num);
  if(e.sex=='m')
    printf(" 男");
  else
    printf(" 女");
  printf("%5d  %-4s",e.age,e.Class);
  printf("%9s\n",sta[e.health]);
}

void ReadIn(stud &e)
{ // 由键盘输入结点信息
  printf("请输入姓名(<=%d个字符): ",NAMELEN);
  scanf("%s",e.name);
  printf("请输入学号: ");
  scanf("%ld",&e.num);
  printf("请输入性别(m:男 f:女): ");
  scanf("%*c%c",&e.sex);
  printf("请输入年龄: ");
  scanf("%d",&e.age);
  printf("请输入班级(<=%d个字符): ",CLASSLEN);
  scanf("%s",e.Class);
  printf("请输入健康状况(0:%s 1:%s 2:%s):",sta[0],sta[1],sta[2]);
  scanf("%d",&e.health);
}

void WriteToFile(stud e)
{ // 将结点信息写入fp指定的文件
  fwrite(&e,sizeof(stud),1,fp);
}

Status ReadFromFile(stud &e)
{ // 由fp指定的文件读取结点信息到e
  int i;
  i=fread(&e,sizeof(stud),1,fp);
  if(i==1) // 读取文件成功
    return OK;
  else
    return ERROR;
}

int cmp(ElemType c1,ElemType c2)
{
  return (int)(c1.num-c2.num);
}

void Modify(LinkList &L,ElemType e)
{ // 修改结点内容,并按学号将结点非降序插入链表L
  char s[80];
  Print(e); // 显示原内容
  printf("请输入待修改项的内容,不修改的项按回车键保持原值:\n");
  printf("请输入姓名(<=%d个字符): ",NAMELEN);
  gets(s);
  if(strlen(s))
    strcpy(e.name,s);
  printf("请输入学号: ");
  gets(s);
  if(strlen(s))
    e.num=atol(s);
  printf("请输入性别(m:男 f:女): ");
  gets(s);
  if(strlen(s))
    e.sex=s[0];
  printf("请输入年龄: ");
  gets(s);
  if(strlen(s))
    e.age=atoi(s);
  printf("请输入班级(<=%d个字符): ",CLASSLEN);
  gets(s);
  if(strlen(s))
    strcpy(e.Class,s);
  printf("请输入健康状况(0:%s 1:%s 2:%s):",sta[0],sta[1],sta[2]);
  gets(s);
  if(strlen(s))
    e.health=atoi(s); // 修改完毕
  InsertAscend(L,e,cmp); // 把q所指结点的内容按学号非降序插入L
}

#define N 4 // student记录的个数

Status EqualNum(ElemType c1,ElemType c2)
{
  if(c1.num==c2.num)
    return OK;
  else
    return ERROR;
}

Status EqualName(ElemType c1,ElemType c2)
{
  if(strcmp(c1.name,c2.name))
    return ERROR;
  else
    return OK;
}

int main()
{ // 表的初始记录
  stud student[N] = { {"wangxiaoling",790631,'m',18,"CLS91",0},
					  {"chenhong",790632,'f',20,"CLS91",1},
					  {"ling",790633,'m',21,"CLS91",0},
					  {"zhanglili",790634,'m',17,"CLS91",2}};
  int i,j,flag=1;
  char filename[13];
  ElemType e;
  LinkList T,p,q;
  InitList(T); // 初始化链表
  while(flag)
  {
    printf("1:将结构体数组student中的记录按学号非降序插入链表\n");
    printf("2:将文件中的记录按学号非降序插入链表\n");
    printf("3:键盘输入新记录,并将其按学号非降序插入链表\n");
    printf("4:删除链表中第一个有给定学号的记录\n");
    printf("5:删除链表中第一个有给定姓名的记录\n");
    printf("6:修改链表中第一个有给定学号的记录\n");
    printf("7:修改链表中第一个有给定姓名的记录\n");
    printf("8:查找链表中第一个有给定学号的记录\n");
    printf("9:查找链表中第一个有给定姓名的记录\n");
    printf("10:显示所有记录 11:将链表中的所有记录存入文件 12:结束\n");
    printf("请选择操作命令: ");
    scanf("%d",&i);
    switch(i)
    {
      case 1: for(j=0;j<N;j++)
		 InsertAscend(T,student[j],cmp); 
	       break;
      case 2: printf("请输入文件名: ");
	       scanf("%s",filename);
	       if((fp=fopen(filename,"rb"))==NULL)
		 printf("打开文件失败!\n");
	       else
	       {
		 while(ReadFromFile(e))
		   InsertAscend(T,e,cmp); 
		 fclose(fp);
	       }
	       break;
      case 3: ReadIn(e);
	       InsertAscend(T,e,cmp); 
	       break;
      case 4: printf("请输入待删除记录的学号: ");
	       scanf("%ld",&e.num);
	       if(!DeleteElem(T,e,EqualNum)) 
		 printf("没有学号为%ld的记录\n",e.num);
	       break;
      case 5: printf("请输入待删除记录的姓名: ");
	       scanf("%*c%s",e.name); // %*c吃掉回车符
	       if(!DeleteElem(T,e,EqualName)) 
		 printf("没有姓名为%s的记录\n",e.name);
	       break;
      case 6: printf("请输入待修改记录的学号: ");
	       scanf("%ld%*c",&e.num);
	       if(!DeleteElem(T,e,EqualNum)) // 在链表中删除该结点,并由e返回
		 printf("没有学号为%ld的记录\n",e.num);
	       else
		 Modify(T,e); // 修改e并按学号插入链表T
	       break;
      case 7: printf("请输入待修改记录的姓名: ");
	       scanf("%*c%s%*c",e.name); // %*c吃掉回车符
	       if(!DeleteElem(T,e,EqualName)) 
		 printf("没有姓名为%s的记录\n",e.name);
	       else
		 Modify(T,e);
	       break;
      case 8: printf("请输入待查找记录的学号: ");
	       scanf("%ld",&e.num);
	       if(!(q=Point(T,e,EqualNum,p))) 
		 printf("没有学号为%ld的记录\n",e.num);
	       else
		 Print(q->data);
	       break;
      case 9: printf("请输入待查找记录的姓名: ");
	       scanf("%*c%s",e.name);
	       if(!(q=Point(T,e,EqualName,p))) 
		 printf("没有姓名为%s的记录\n",e.name);
	       else
		 Print(q->data);
	       break;
      case 10:printf("  姓名    学号 性别 年龄 班级 健康状况\n");
	       ListTraverse(T,Print);
	       break;
      case 11:printf("请输入文件名: ");
	       scanf("%s",filename);
	       if((fp=fopen(filename,"wb"))==NULL)
		 printf("打开文件失败!\n");
	       else
		 ListTraverse(T,WriteToFile);
	       fclose(fp);
	       break;
      case 12:flag=0;
    }
  }
  
  return 0;
}


你可能感兴趣的:(数据结构,c,struct,null,Class,FP)