#include <cstdio> 
#include <cstdlib>
#include <cstring>
using namespace std;
struct list* create();	/*新建链表*/ 
struct list* insert( struct list *head, struct list *temp );	/*插入*/ 
struct list *deletes( struct list *head, int num );	/*删除*/ 
void print( struct list *head );	/*遍历输出*/ 
typedef long long LL;	/*给予long long别名 LL*/ 
struct list{
	int num;
	char name[20];
	LL tel;		/*定义long long 的整型变量*/ 
	struct list *next;	/*嵌套定义,既是结构分量又是该结构指针*/ 
};
int main()
{
	struct list *head, *p; /*头结点和操作指针*/ 
	int num;
	char name[20];
	LL tel;
	int choice;
	int size = sizeof( struct list );
	
	do{
		printf("1: create\n2: insert\n3: delete\n4: print\n0: exit\n");
		scanf("%d", &choice );
		switch( choice ){
			case 1:
				head = create();
				break;
			case 2:
				printf("input num, name and tel: \n");
				scanf("%d%s%lld", &num, name, &tel );
				p = ( struct list * ) malloc( size );
				p->num = num;
				strcpy( p->name, name );
				p->tel = tel;
				head = insert( head, p );
				break;
			case 3:
				printf("input num:\n");
				scanf("%d", &num );
				head = deletes( head, num );
				break;
			case 4:
				print( head );
				 break;
			case 0:
				break;
		}
	}while( choice != 0 );
	
	return 0;
}

struct list* create()
{
	struct list *head, *p;	/*定义头结点和操作指针*/ 
	int num;
	char name[20];
	LL tel;
	int size = sizeof( struct list );
	
	head = NULL;	/*头结点初始为空指针*/ 
	printf("input num, name and tel:\n");
	scanf("%d%s%lld", &num, name, &tel );
	while( tel != 0 ){
		p = ( struct list * ) malloc( size );	/*动态分配存储空间*/ 
		p->num = num;
		strcpy( p->name, name );
		p->tel = tel;
		head = insert( head, p );	/*调用插入函数,插入一个结点*/ 
		scanf("%d%s%lld", &num, name, &tel );
	}
	return head;	/*返回头结点的地址*/ 
 }
 
 /*插入需要考虑插入的结点是不是在头结点之前,头结点为空怎么办,不为空又怎么班; 
  插入结点是不是在中间,还是在末尾*/ 
  /*查找插入结点的位置条件是什么*/ 
 struct list* insert( struct list *head, struct list *temp )
 {
 	/* ptr为带插入结点,ptr1是最后要插入结点的前一个结点
	 ptr2 是最后要插入结点的后一个结点*/ 
 	struct list *ptr, *ptr1, *ptr2;
 	
 	ptr2 = head;	/*初始ptr2 为头结点, 便于用循环查找要插入的位置*/ 
 	ptr = temp;		/*用ptr来保存要插入的结点*/ 
 	if( head == NULL ){	/*如果链表为空则直接在头结点插入*/ 
 		head = ptr;
 		head->next = NULL; /*初始头结点的下一个结点为空*/ 
	 }
	 else{
	 	/*用循环查找要插入的位置*/ 
	 	/*插入顺序为num的序号*/ 
	 	while( ( ptr->num > ptr2->num ) && ( ptr2->next != NULL ) ){
	 		ptr1 = ptr2;	/*ptr和ptr2逐个后移*/ 
	 		ptr2 = ptr2->next;
		 }
		 if( ptr->num <= ptr2->num ){	/*判断插入位置是不是链表末尾或头结点之前*/ 
		 	if( head == ptr2 )	/*如果要插入的结点在头结点之前*/ 
		 		head = ptr;		/*头结点为新的 头结点*/ 
		 	else
		 		ptr1->next = ptr;
		 	/*如果插入在头结点,则头结点后移,否则三个结点先断后连 */
		 	ptr->next = ptr2;
		 }
		 else{					/*插入在末尾, 这时ptr2为最后一个结点*/ 
		 	ptr2->next = ptr;
		 	ptr->next = NULL; 	/*初始尾结点的下一个结点为空*/ 
		 }
	 }
	 return head;
 }
 
 /*删除需要考虑删除的结点是不是头结点,如果不是查找删除结点的条件是什么,
 只删除遇到的指定num值的第一个还是所有*/ 
 struct list *deletes( struct list *head, int num )
 {
 	struct list *ptr1, *ptr2;
 	
 	/*如果要删除的结点为头结点 */
 	while( head != NULL && head->num == num ){
 		ptr2 = head;
 		head = head->next;	/*头结点后移*/ 
 		free( ptr2 );	/*释放之前的头结点*/ 
	 }
	 if( head == NULL )
	 	return NULL;
	ptr1 = head;		/*ptr1, ptr2, 一前一后*/ 
	ptr2 = head -> next;
	while( ptr2 != NULL ){	/*从头结点的下一个结点开始查找*/ 
		if( ptr2->num == num ){	/*如果找到*/ 
			ptr1->next = ptr2->next;	/*直接把要删除的结点的前后两个结点相连*/ 
			free( ptr2 );	/*释放要删除的结点*/ 
			//break			/*加上break只删除第一个num, 不加删除所有*/ 
		}
		else			/*如果没找到, ptr1和ptr2后移一个结点*/ 
			ptr1 = ptr2;
		ptr2 = ptr1->next;
	} 
	return head;
 }
 
 void print( struct list *head )
 {
 	struct list *ptr;
 	if( head == NULL ){
 		printf("\nNO Records\n");
 		return;
	 }
	 printf("num\t name\t tel\n");
	 for( ptr=head; ptr != NULL; ptr = ptr->next )	/*循环输出*/ 
	 	printf("%d\t %s\t %lld\n", ptr->num, ptr->name, ptr->tel );
 }