实验作业三:单链表

题目:

利用尾插法建立一个单链表,并从屏幕显示单链表元素列表;根据屏幕上的提示进行单链表的删除、插入等操作。

 

运行环境:Dev-C++ 5.11

 

下面是正式的代码,这里没有拆分成多个文件,直接堆在一起了。

/* 单链表程序

包含结构体:
	1. 定义单链表结构(结点)

包含函数:
	1. 获取链表的指定位置的结点
	2. 创建一个单链表
	3. 插入节点
	4. 输出已有的单链表信息
	5. 按序号删除结点
	6. 按序号查询结点
	7. 提示框函数(负责调用上面5个函数)
	8. 释放结点内存空间
*/

#include<stdio.h>
#include<stdlib.h>
#define SIZE sizeof(LinkList)

// 定义单链表的结构(结点)
typedef struct Node{
	int data;			// 数据域
	struct Node *next;	// 指针域
}LinkList;

// 全局变量n用来存储链表结点的个数,也方便输出提示信息
int n;

// 1. 移动指针到想要的位置,返回从此位置开始的结点指针类型变量
LinkList* remove(LinkList* head, int i) {
	LinkList* p;
	int j=0;
	p = head;
	while((j < i) && (p->next != NULL)){
		p = p->next;
		j++;
	}
	if(j == i)
		return p;
	else
		return NULL;
}

// 2.创建一个空的单链表,并对其进行赋值,返回单链表的头结点的指针
LinkList* creat() {
	LinkList *head;
	LinkList *p1, *p2;
	n = 0;
	printf("请输入数值(输入数值时,输入'0'并回车可以退出输入)\n");
	p1 = p2 = (LinkList *)malloc(SIZE);
	printf("第%d个数值:",n+1);
	scanf("%d",&p1->data);         		// 开始输入第一个结点的数值
	head = p1;                    	 	// 头结点指向首元结点

	// 如果用户输入的数值不是0
	while (p1->data != 0) {
		n += 1;							// 结点数+1
		p1 = (LinkList*)malloc(SIZE);	// 再创建一个结点,并让p1指向它
		p2->next = p1;					// 把新创建的结点同其前一个结点连接起来
		p2 = p1;						// p2指向新创建的结点
		printf("第%d个数值:",n+1);		// 输出提示信息
		scanf("%d",&p1->data);
	}

	// 如果用户输入的数值是0(默认表示输入结束,或者用户不想再继续输入)
	p2->next = NULL;					// p2就是尾结点
	return head; 						// 返回头结点的指针
}

// 3. 插入结点
LinkList* insert(LinkList *head) {
	LinkList *p, *s;
	int i;								// i用来存放插入结点的位置
	int num;							// num用来存放插入的数值
	printf("请输入插入结点的位置:");
	scanf("%d", &i);
	p = remove(head, i-2);				// 调用remove函数,获取一个结点的位置,这个结点是被插入结点的前一个结点
	if(p == NULL)   					// 保证程序稳健性
		printf("出错:插入位置错误。请重新输入\n");
	else {
		printf("请输入插入的数值:");
		scanf("%d", &num);
		s = (LinkList*)malloc(SIZE);	// 给s指针开辟内存空间
		s->data = num;					// 给被插入结点赋值
		s->next = p->next;				// 让s指向被插入结点的后一个结点
		p->next = s;					// 让s指向被插入结点的前一个结点
	}
	return head;                       	// 返回头结点
}

// 4. 输出链表中所有的数值
void print(LinkList *head) {
	int n = 1;                          // 局部变量n
	LinkList *p;
	p = head;
	printf("\n已输入的内容:\n");
	if(head != NULL)                    // 如果链表非空
		do {
			printf("第%d个数值是:%d\n",n, p->data);
			p = p->next;
			n += 1;
		}while(p!=NULL);
    else
		printf("出错:此链表为空链表");
}

// 5. 按序号删除结点
LinkList* del(LinkList *head) {
	LinkList *p1, *p2;
	int num;
	printf("请输入被删除结点的序号: ");
	scanf("%d", &num);
	p1 = remove(head, num-2);			// p1指向被删除结点的前一个结点
	if(p1 == NULL)
		printf("出错:输入序号错误。请重新输入\n");		// 保证程序稳健性
	else {
		p2 = (LinkList*)malloc(SIZE);	// 给p2开辟内存空间
		p2 = p1->next;					// 让p2指向被删除结点
		p1->next = p2->next;			// 将p1和p2之后的下一个结点连接起来
		free(p2);                       // 释放p2的内存空间
		p2 = NULL;                      // 给p2赋值为NULL
	}
	return head;
}

// 6. 按序号查询结点
void search(LinkList *head) {
	LinkList *p;
	int num;
	printf("请输入需要查询的结点的序号: ");
	scanf("%d", &num);
	p = head;
	if(p == NULL||num>n)                // 保证程序稳健性
		printf("链表不存在或者输入的序号不正确,请重新输入");
	else {
		while(num -= 1) {               // 当num为1时,p结点指向被查询结点
		p = p->next;
		}
		printf("查询结点数据为: %d\n", p->data);
	}
}

// 7. 释放结点内存空间
void free(LinkList* head) {
  LinkList * p;
  while(head != NULL) {
    p = head;
    head = head->next;
    free(p);
    p = NULL;                           // 给p指针赋值为NULL是一个好习惯
  }
  printf("链表已被释放");
}

// 8. 提示框函数(负责调用以上7个函数)
void menu() {
	int num;
	LinkList *head;
	printf("+————     单链表选择菜单     ————+\n");
	printf("|    1.创建一个单链表(并初始化数值)      |\n");
	printf("|    2.插入一个结点                      |\n");
	printf("|    3.输出已有的单链表的结点信息        |\n");
	printf("|    4.按序号删除结点                    |\n");
	printf("|    5.按序号查询结点                    |\n");
	printf("|    6.释放链表空间并退出                |\n");
	printf("+————————————————————+\n");

	while(num) {
		printf("\n请输入需要进行的操作: ");
		scanf("%d", &num);
		switch(num) {
			case 1:head = creat();print(head);system("pause");break;
			case 2:head = insert(head);system("pause");break;
			case 3:print(head);system("pause");break;
			case 4:head = del(head);system("pause");break;
			case 5:search(head);system("pause");break;
			case 6:free(head);system("pause");break;
			default:printf("未输入正确的数字,请重新输入\n");
		}
	}
}

// 主函数,只调用提示框函数
int main() {
	menu();
	return 0;
}

 

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值