欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

有关多种(单向,双向,循环)链表的操作----初始化,插入,输出,删除,头(尾)插法

程序员文章站 2022-04-10 23:45:51
...

代码以功能排布,相同的功能,不同种类的链表放在一块便于对比

#include"stdio.h"
#include"stdlib.h"

typedef struct Node {
	int data;
	struct Node* Next;
}*PList;
typedef struct DNode {
	int data;
	struct DNode* Next;
	struct DNode* Prior;
}*DList; //双向循环链表
typedef struct CNode {
	int data;
	struct CNode* Next;
}*CList; //单向循环链表

/*输出组*/
void Print(struct Node* p) {
	printf("单向链输出: ");
	p = p->Next;
	while (p) {
		printf("%d ", p->data);
		p = p->Next;
	}
	printf("\n");
}

void Print_D(struct DNode* P) {
	printf("双向链输出: ");
	struct DNode* p = P->Next;
	while (p != P) {
		printf("%d ", p->data);
		p = p->Next;
	}
	printf("\n");
}

void Print_CH(struct CNode* P) {
	printf("循环链输出(头指针): ");
	struct CNode* p = P->Next;
	while (p != P) {
		printf("%d ", p->data);
		p = p->Next;
	}
	printf("\n");
}

void Print_CE(struct CNode* p) {  //p指向链表的尾部
	printf("循环链输出(尾指针): ");
	struct CNode* c = p->Next->Next;
	while (c != p->Next) { //c指向头结点的时候结束
		printf("%d ", c->data);
		c = c->Next;
	}
	printf("\n");
}

/*初始化组*/
int Init(PList* P) {
	*P =  (PList)malloc(sizeof(struct Node));
	if (!*P) {
		printf("failed to initialize\n");
		return 1;
	}
	(*P)->Next = NULL; //一定要记住赋初值
	return 0;
}

int DInit(DList* P) {
	*P = (DList)malloc(sizeof(struct DNode));
	if (!*P) {
		printf("failed to initialize\n");
		return 1;
	}
	(*P)->Next = *P;
	(*P)->Prior = *P;
	return 0;
}

int CInit(CList* P) {
	*P = (CList)malloc(sizeof(struct CNode));
	if (!*P) {
		printf("failed to initialize\n");
		return 1;
	}
	(*P)->Next = *P;
	return 0;
}

/*插入 从1到n都可插   插到第i个前*/
int ListInsert(PList* P, int i, int e) {
	PList p = *P;	int j = 0;
	while (p && j < i - 1) { //p要指向i前一个结点
		p = p->Next;	j++;
	}
	if (i - 1 < j || !p) {
		printf("i is error\n");
		return 0;
	}
	PList s = (PList)malloc(sizeof(struct Node));
	s->data = e;
	s->Next = p->Next;
	p->Next = s;
	return 1;
}

int DListInsert(DList* P, int i, int e) {
	DList p = *P;	int j = 0;
	while (p->Next != *P && j < i - 1) { //p指向i前一个结点 注意第一次时p指向头结点,需要进入while循环,之后的条件不可以以p指向头结点为退出条件
									 //因为指向i这个结点时会有麻烦,当在最后一个插入时,需要再次指向头节点,所以while条件就会麻烦。
		p = p->Next;	j++;
	}
	if (i - 1 != j) { 
		printf("i is error\n");
		return 0;
	}
	DList s = (DList)malloc(sizeof(struct DNode));
	s->data = e;
	s->Next = p->Next;
	p->Next->Prior = s;
	p->Next = s;
	s->Prior = p;
	return 1;
}

int CListInsert(CList* P, int i, int e) {
	CList p = *P;	int j = 0;
	while (p->Next != *P && j < i - 1) { //p指向i前一个结点
		p = p->Next;	j++;
	}
	if (i - 1 != j) {
		printf("i is error\n");
		return 0;
	}
	CList s = (CList)malloc(sizeof(struct CNode));
	s->data = e;
	s->Next = p->Next;
	p->Next = s;
	return 1;
}

//头插法
int CHListInsert(CList* P, int e) {
	CList H = (CList)malloc(sizeof(struct CNode));
	if (!H) {
		return 0;
	}
	H->data = e;
	H->Next = (*P)->Next;
	(*P)->Next = H;
	return 1;
}


//尾插法
int CEListInsert(CList* P, int e) {
	CList E = (CList)malloc(sizeof(struct CNode));
	if (!E) {
		return 0;
	}
	E->data = e;
	E->Next = (*P)->Next;
	(*P)->Next = E;
	*P = E;
	return 1;
}


/*删除组*/
int DeleList(PList* P, int i, int* e) {
	PList p = *P;	int j = 0; //p指向i前一个结点且要保证第i个结点存在
	while (p->Next != NULL && j < i - 1) {
		p = p->Next;	j++;
	}
	if (i < j || p->Next == NULL) {
		return 0;
	}
	PList d = p->Next;
	*e = d->data;
	p->Next = d->Next;
	free(d);
	return 1;
}

int DeleDList(DList* P, int i, int* e) {
	DList p = (*P)->Next;	int j = 1; //让p指向第i个结点
	while (p != *P && j < i) {
		p = p->Next;	j++;
	}
	if (i != j || p == *P) {
		return 0;
	}
	*e = p->data;
	p->Next->Prior = p->Prior;
	p->Prior->Next = p->Next;
	free(p);
	return 0;
}

int DeleCList(CList* P, int i, int* e) {
	CList p = *P;	int j = 0; //p指向i前一个 要保证i个结点存在
	while (p->Next != *P && j < i - 1) {
		p = p->Next;	j++;
	}
	if (p->Next == *P || i < j) {
		return 0;
	}
	CList d = p->Next;
	*e = d->data;
	p->Next = d->Next;
}

/*测试*/
int main() {
	PList plist; DList dlist;	CList clist;
	Init(&plist);	DInit(&dlist);	CInit(&clist);
	Print(plist);
	Print_D(dlist);
	Print_CH(clist);
	printf("\n");
	int elem[] = {1,2,3,4,5};
	for (int i = 0; i < 5; i++) { //有效插入
		ListInsert(&plist, i+1, elem[i]);
		DListInsert(&dlist, i+1, elem[i]);
		CListInsert(&clist, i+1, elem[i]);
	}
	Print(plist);
	Print_D(dlist);
	Print_CH(clist);
	printf("\n");
	int err = 9;
	//错误插入
	ListInsert(&plist, 7, err);
	DListInsert(&dlist, 7, err);
	CListInsert(&clist, 7, err);
	ListInsert(&plist, 0, err);
	DListInsert(&dlist, 0, err);
	CListInsert(&clist, 0, err);
	Print(plist);
	Print_D(dlist);
	Print_CH(clist);
	printf("\n 尾插法: \n");
	//循环链表的尾插法
	CList c;
	CInit(&c);
	for (int i = 0; i < 7; i++) {
		CEListInsert(&c, i);
	}
	Print_CE(c);
	printf("\n 头插法: \n");
	//循环链表的头插法
	CList h;
	CInit(&h);
	for (int i = 0; i < 7; i++) {
		CHListInsert(&h, i);
	}
	Print_CH(h);
	printf("\n");
}

有关多种(单向,双向,循环)链表的操作----初始化,插入,输出,删除,头(尾)插法
这段代码实现了一些链表的基础操作
如果还需要什么功能,可以在评论区内留言

相关标签: 算法实现