数据结构—链表

本文深入讲解了链表的基本概念及多种操作方法,包括创建、插入、删除、查找等核心算法,并提供了详细的代码实现,帮助读者全面掌握链表的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//链表
#include "StdAfx.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>



//定义单链表类型

typedef int DataType;
struct Node//定义结构体类型
{
	DataType data;//数据域
	struct Node *next;//指针域
};
typedef struct Node *PNode;//给struct Node*取个别名PNode,之后用这个别名的代表结点
typedef struct Node  *LinkList;//给struct Node*取个别名LinkList,之后用这个别名的代表单链表



//创建带头结点的空的单链表

LinkList SetNullList_Link()
{
	LinkList head = (LinkList)malloc(sizeof(struct Node));//申请头结点空间*head,头指针head指向该空间
	if (head != NULL)//若空间分配成功,则头结点的next域为空
		head->next = NULL;
	else
		printf("alloc failure");
	return head; //返回头指针
}



//判断该链表是否为空

int IsNull_Link(LinkList head) 
{
	return(head->next == NULL);
}



//头插法建立单链表(每读入一个数据元素创建一个结点置于头结点之后,形成的单链表与读入数据元素顺序相反)

void CreateList_Head(struct Node *head)
{
	PNode p = NULL;   //临创建一个空指针p临时使用
	int data;
	printf("请输入整型数据建立链表,以-1结束\n");
	scanf_s("%d", &data);//键盘输入int型数据data,输入-1时结束
	while (data != -1)
	{
		p = (struct Node*)malloc(sizeof(struct Node)); //分配空间*p,指针p指向该空间
		p->data = data;  //将输入数据放于创建的结点*p的数据域内
		p->next = head->next;   //将*p的指针域改为头指针的指针域,输入第二个数据时也就是它的指针域为指向上一个结点的指针
		head->next = p;//将头指针的指针域改为指向*p的指针p
		scanf_s("%d", &data);
	}
}



//尾插法建立单链表(申请一个尾指针q一直指向链表最后一个结点,每读入一个数据创建一个节点,形成的单链表与读入数据元素顺序相同)

void CreateList_Tail(struct Node *head)
{
	struct Node *p = NULL;//创建空指针p临时使用
	struct Node *q = head;//申请指针q指向头结点*head
	int data;
	printf("请输入整型数据建立链表,以-1结束\n");
	scanf_s("%d", &data);
	while (data != -1)
	{
		p = (struct Node*)malloc(sizeof(struct Node)); //分配空间
		p->data = data; //将输入数据放于创建的结点*p的数据域内
		p->next = NULL; //*p指针域为空
		q->next = p;//使尾指针之前指向的那个结点的指针域指向临时结点p
		q = p;//使尾指针指向临时结点p
		scanf_s("%d", &data);
	}
}



//按值查找算法

PNode Locate_Link(LinkList llist, DataType x)//查找与x值相同的元素返回其所在位置
{
	PNode p;
	if (llist == NULL) return NULL;//链表为空返回null
	p = llist->next;//令p指向链表首结点指针域
	while (p != NULL&&p->data != x)//若首结点指针域不为空则指向首结点指针域指针所指向的下个结点
		p = p->next;
	return p;
}



//插入算法(后插法)

int InsertPost_link(LinkList llist, PNode p, DataType x)//在llist链表中的p位置之后插入值为x的结点(p要先用查找算法确定其值)
{
	PNode q;
	if (p == NULL) { printf("para failure!\n"); return 0; }
	q = (PNode)malloc(sizeof(struct Node));//q指向新创建的结点*q,数据域存放x
	if (q == NULL)
	{
		printf("out of space!\n");  return 0;
	}
	else
	{
		q->data = x;  q->next = p->next;//使新结点*q的指针域指向*p指针域原本所指向的结点,使*p的指针域指向新结点*q,
		p->next = q;  return 1;
	}
}



//插入算法(前插法)

int InsertPre_link(LinkList llist, PNode p, DataType x)//在llist链表中的p位置之前插入值为x的结点(p要先用查找算法确定其值)
{ 
	PNode pre = llist;//先使pre指针指向链表头结点
	PNode q = NULL;//创建空指针p临时使用,待会儿为q创建空间使其成为结点存放x
	while (pre->next != p) //定位p的前驱结点
	{
		pre = pre->next;
	}
	q = (PNode)malloc(sizeof(struct Node));
	q->data = x;//新结点*q内存放x,使*q的指针域指向*p,使前驱结点*pre指针域指向*q
	q->next = p;
	pre->next = q;
	return 1;
}



//删除算法(按值删除)

void DelValue_Link(LinkList head, int data)
{
	struct Node* p = head->next;//p指向头结点指针域所指向结点
	struct Node* beforeP = head;//beforeP指向头结点
	while (p != NULL) 
	{
		if (p->data == data)  //找到相等的进行删除
		{
			beforeP->next = p->next;
			free(p); break;
		}
		else      //否则继续向后移动查找
		{
			beforeP = p; p = p->next;
		}
	}
}



//删除算法(删除r指针所指结点)

void DelPostion_Link(LinkList head, PNode r)
{
	PNode pre = head;
	while (pre->next != r) //定位r的前驱结点
	{
		pre = pre->next;
	}
	pre->next = r->next;//直接使其前驱结点的指针域指向r结点指针域即可
	free(r);
}



//删除算法(删除r指针所指结点的后继结点)

void DelPostionNext_Link(LinkList head, PNode r)
{
	PNode p;
	if (r->next) p = r->next;
	r->next = p->next;
	free(p);
}



//打印链表
void printLinkList(LinkList llist)
{
	PNode p;
	if (llist == NULL)
		printf("\n The Linklist is NULL !\n");
	p = llist->next;
	while (p != NULL)
	{
		printf("%d", p->data);
		p = p->next;
	}

	printf("\n");
}



//主函数
int main()
{

	PNode p= SetNullList_Link();//p为链表头指针
	LinkList List1 = SetNullList_Link();//创建空链表List1

	// 尾插法输入数据建立链表(头插法:CreateList_Head(List1);)
	CreateList_Tail(List1);
	
	//打印输入的初始链表
	printLinkList(List1);

	// 按值查找(5在哪里)
    p = Locate_Link(List1, 5);
	printf("The location of %d is %d\n", 5,p);

	// 后插法(p后面插入9并打印更新后的链表)
	printf("5后面插入9:");
	if (p == NULL)
	{
		printf("p is null!");
		system("pause");
	}
	else
	{
		InsertPost_link(List1, p, 9);
		printLinkList(List1);
	}

	//前插法(p前面插入9并打印更新后的链表)
	printf("5前面插入9:");
	if (p == NULL)
	{
		printf("p is null!");
		system("pause");
	}
	else
	{
		InsertPre_link(List1, p, 9);
		printLinkList(List1);
	}

	//在下标2处插入8
	printf("在下标为2的位置添加元素8:");
	int loc = 2;
	int ptr = 0;
	PNode q = List1->next;
	while (q)
	{
		ptr = ptr + 1;
		if (ptr == loc)
		{
			break;
		}
		q = q->next;
	}
	InsertPost_link(List1, q, 8);
	printLinkList(List1);

	// 删除元素5的后继并打印
	printf("删除5后继元素:");
	DelPostionNext_Link(List1, p);
	printLinkList(List1);

	
	//删除与5相等的结点
	printf("删除5:");
	DelValue_Link(List1, 5);
	printLinkList(List1);

	system("pause");
}
//建立尾指针表示的单循环链表

typedef int DataType;
struct Node
{
	DataType data;
	struct Node *next;
};
typedef struct Node *PNode;
typedef struct Node *CLinkList;
CLinkList createListRearCircle()
{
	PNode rear,s;//尾指针rear
	int x;//输入数据x
	CLinkList head=(CLinkList)malloc(sizeof(struct Node));
	head -> next=head;
	rear=head;//尾指针指向头结点
	printf("请输入整型数据建立链表,以-1结束\n");
	scanf("%d",&x);
	while(x!=-1)
	{
		s=(PNode)malloc(sizeof(struct Node));
		s->data=x;
		s->next=head;
		rear->next=s;
		rear=s;
		scanf("%d",&x);
	}
	return rear;
}

//将两个单循环链表合并成一个

LinkList Combine(LinkList ra, LinkList rb)
{ 
  LinkList p = ra->next;  //由于ra带有头结点,故从ra->next开始
 ra->next = rb->next->next;  //ra的尾部链接rb的除去头结点的开始结点
 free(rb->next);  //释放rb链表的头结点
 rb->next = p;   //rb的尾部链接ra的头结点
 return rb;  
}
//双链表定义

typedef int DataType;
typedef struct node
{
	DataType data;
	struct node *llink;
	struct node *rlink;
}Dlnode;
typedef struct
{
	Dlnode *first;
	Dlnode *last;
}DlinkList;
DlinkList *dist;

//双链表删除算法
void Del_DoubleList(DlinkList dlist,Dlnode *p)
{
	p->llink->rlink=p->rlink;
	p->rlink->llink=p->llink;
	free(p);
}

//双链表插入算法

void Insert_DoubleList(Dlnode *p)
{
	Dlnode* s=(Dlnode*)malloc(sizeof(struct node));
	s->llink=p;
	s->rlink=p->rlink;
	p->rlink->llink=s;
	p->rlink=s;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值