编程小白的数据结构学习:单链表

学习用代码,记录自己复习的时候用。。

代码参考了 白皮肤的黑客 的文章,地址 https://blog.csdn.net/Davidluo001/article/details/46476221

下面贴代码。

#include "stdafx.h"
#include <stdio.h>
#include <malloc.h>


typedef int Elemtype;
typedef struct Node {
	Elemtype data;    //存放节点的数据
	Elemtype num;     //存放结点的顺序
	struct Node *next;  //存放指向下一个结点的指针
}List,*NodeList;

//创建一个链表//
NodeList  Create_List() {
	int len, i;
	printf("请输入想要定义的链表长度len=");
	scanf("%d", &len);
	NodeList PHead;    //定义一个头结点
	PHead = (Node *)malloc(sizeof(Node));//动态为其分配内存空间
	PHead->next = NULL;
	NodeList PTail;   //尾结点,永远指向末尾
	PTail = PHead;
	for (i = 0; i < len; i++) {
		//循环创建结点
		int value;   //存放结点的值
		printf("请输入第%d个结点的值value=", i + 1);
		scanf("%d", &value);
		NodeList New;
		New = (Node *)malloc(sizeof(Node));
		New->data = value;
		New->num = i + 1;
		New->next = NULL;
		PTail->next = New;
		PTail = New;   //Tail永远指向尾巴
	}
	return PHead;
}

//遍历单链表//
void Traverse(NodeList PHead) {
	//传入头结点
	NodeList P;
	P = PHead->next;   //P指向第一个结点
	while (P != NULL) {
		printf("NO.%d->%d\t", P->num, P->data);
		P = P->next;
	}
	printf("\n");
}

//判断链表是否为空链表//
bool IfEmpty(NodeList PHead) {
	//同样也是传链表的头结点
	//true表示是空链表,false表示不是空链表
	if (PHead->next == NULL)
		return true;
	else
		return false;
}

//获取链表的长度
int List_Num(NodeList PHead) {
	NodeList P = PHead->next;//指向第一个结点
	int num = 0;
	while (P != NULL) {
		num++;   //长度加一
		P = P->next;
	}
	return num;
}

//往列表中插入元素//
bool Insert_List(NodeList PHead, int pos, int value) {
	//传入元素分别是列表头指针,插入的位置,插入元素的值
	//先要判断插入的位置是否合法
	//合法的位置传出true,不合法的传出false
	int num;
	num = List_Num(PHead);//表示列表的长度
	if (pos > num+1 || pos <= 0) {
		printf("输入的位置不合法,请重新输入\n");
		return false;
	}
	//分配一个结点空间
	NodeList PNew,P;
	PNew = (Node *)malloc(sizeof(Node));
	PNew->num = pos;
	PNew->data = value;
	PNew->next = NULL;
	if (pos == 1) {
		//插入第一个位置,即为头结点之后的结点
		PNew->next = PHead->next;
		PHead->next = PNew;
		//接下来逐个修改之后的结点的编号(加一)
		for (P = PNew->next; P != NULL; P = P->next)
			P->num++;
		return true;
	}
	else if (pos == num + 1) {
		//插入到链表的末尾
		P = PHead->next;
		while (P->next != NULL)
			P = P->next;//最后P会指向末尾结点
		P->next = PNew;
		return true;
	}
	else {
		//插入到链表的中间
		P = PHead->next;
		while (P->num != pos-1)
			P = P->next;//此时的后一个结点就应该是PNew
		PNew->next = P->next;
		P->next = PNew;
		//之后要修改PNew->next及其之后的结点的num
		P = PNew->next;
		while (P != NULL) {
			P->num++;
			P = P->next;
		}
		return true;
	}
}

//在列表中删除元素//
bool Delete_List(NodeList PHead, int pos, NodeList  e) {
	//从链表中删除编号为pos的结点并且用结点e返回
	//首先判断输入是否合法
	int num = List_Num(PHead);
	NodeList P = PHead->next;//P指向第一个结点
	NodeList P1;             //用来指向P之前的一个结点
	if (pos > num || pos <= 0) 
		//输入不合法
		return false;
	if (pos == 1) {
		//删除第一个结点
		PHead->next = P->next;
		e = P;
		//将除了第一个结点之外的结点编号减一
		P = PHead->next;
		while (P != NULL) {
			P->num--;
			P = P->next;
		}
		return true;
	}
	else if (pos == num) {
		//删除最后一个结点
		P = PHead->next;
		P1 = PHead->next;
		P = P->next;
		while (P->next != NULL) {
			P = P->next;//最后P指向最后一个结点
			P1 = P1->next;
		}
		e = P;
		P1->next = NULL;
		return true;
	}
	else {
		//删除中间的结点
		P = PHead->next;//这里表示第一个结点
		P1 = PHead->next;
		P = P->next;   //这里已经是第二个结点了
		while (P->num != pos) {
			P = P->next;
			P1 = P1->next;
		}
		//此时P指向要删除的结点
		P1->next = P->next;
		e = P;
		//P之后的结点num减一
		P = P1->next;
		while (P != NULL) {
			P->num--;
			P = P->next;
		}
		return true;
	}
}
int main()
{
	NodeList P,e;
	int num;
	bool ifsuccess;   //用来记录返回值
	char choose1 = 'Y',choose2 = 'Y';
	P = Create_List();//P就是这个单链表的头结点
	num = List_Num(P);
	printf("列表的长度为%d\n", num);
	Traverse(P);
	//执行插入命令
	while (choose1 == 'Y') {
		//此时执行结点插入函数
		int pos, value;
		printf("请输入插入结点的位置:");
		scanf("%d", &pos);
		printf("请输入插入结点的值:");
		scanf("%d", &value);
		ifsuccess = Insert_List(P, pos, value);
		if (ifsuccess == true) {
			Traverse(P);
			printf("继续插入输入Y,否则输入N:");
			getchar();
			scanf("%c", &choose1);
		}
	}
	//执行删除命令
	while (choose2 == 'Y') {
		int pos;
		printf("请输入要删除的结点的编号:");
		scanf("%d", &pos);
		ifsuccess=Delete_List(P, pos, e);
		if (!ifsuccess) {
			printf("输入不合法,请重新输入\n");
			choose2 = 'Y';
		}
		else {
			Traverse(P);
			printf("继续删除请按Y,退出请按N:");
			getchar();
			scanf("%c", &choose2);
		}
	}
    return 0;
}

下面是运行情况


最后有一个问题没有解决,就是在删除的时候用e来返回删除的结点信息,但是编译器总是说我在使用前没有定义,这个问题没法解决。。希望有大佬能够帮忙解决这个问题。微笑微笑

猜你喜欢

转载自blog.csdn.net/haohulala/article/details/80024737