单链表及其常用操作(C++)

目录

1.节点定义

2.初始化链表

3.建立单链表

头插法

尾插法

4.遍历操作

5.函数求链表长度

6.查找操作

7.插入操作

8.删除操作

删除第i个节点

删除所有数据域为data的节点

9.连接两个链表MN

10.链表排序

11.链表逆置

全部代码

1.节点定义

typedef struct LNode {
	int data;            //数据域
	struct LNode* next;  //指针域
}LNode,*LinkList;
//对第二个别名的分析:LinkList等价于struct LNode*
//使用LinkList创建的量为指向结构体的指针
//而使用LNode创建的量为结构体本身

2.初始化链表

申请一个空的头结点

void InitList(LinkList& L) {
	L = (LinkList)malloc(sizeof(LinkList));
	//可以让头结点的data存储链表长度
	L->data = 0;
	L->next = NULL;
}

3.建立单链表

头插法

//头插法建立单链表
//头插法建立的单链表中节点次序是与输入顺序相反的
LinkList HeadInsert(LinkList& L) {
	InitList(L);            //初始化链表
	int x;
	cin >> x;
	while (x != 9999) {		//输入9999表示结束
		LinkList s = (LinkList)malloc(sizeof(LNode));
		s->data = x;
		s->next = L->next;
		//s插在头结点和上一个结点之间,让s指向上一个节点
		L->next = s;
		L->data++;          //更新链表长度
		cin >> x;
	}
	return L;               //返回头结点指针
}

同样可以再传入一个参数表示要输入的节点数

例:

LinkList HeadInsert(LinkList& L,int n) {
	InitList(L);
	int x;
	while (n--) {
        cin>>x;
		LinkList s = (LinkList)malloc(sizeof(LNode));
		s->data = x;
		s->next = L->next;
		//s插在头结点和上一个结点之间,让s指向上一个节点
		L->next = s;
		L->data++;
	}
	return L;
}

尾插法

//尾插法建立单链表
LinkList TailInsert(LinkList& L) {
	InitList(L);
	LinkList s;
	LinkList r = L;//创建一个尾指针,始终指向最后一个结点
	int x;
	cin >> x;
	while (x != 9999) {
		s = (LinkList)malloc(sizeof(LNode));
		s->data = x;
		r->next = s;	//相当于前一个结点的指针域指向新的结点s
		r = s;			//更新r,永远指向最后一个节点
		L->data++;
		cin >> x;
	}
	r->next = NULL;    //重点 最后一个结点指向空节点
	return L;          //返回头结点
}

4.遍历操作

//遍历操作
void PrintList(LinkList L) {		
	//p指向第一个结点
	LNode* p = L->next;
	//LNode*等同于LinkList,写LinkList p也可以

	//p不为空就输出当前结点的值,并令p指向下一个结点
	while (p) {
		cout << p->data << " ";
		p = p->next;
	}
    //头结点的数据域保存链表长度
	cout << "共" << L->data << "个结点";
	cout << endl;
}

5.函数求链表长度

//求链表长度
int Length(LinkList L) {
	int len = 0;
	LinkList p = L->next;
	while (p) {
		len++;
		p = p->next;
	}
	return len;
}

6.查找操作

//按data查找,返回数据域为data的节点指针
LinkList SearchData(LinkList L,int x) {
	LinkList p = L->next;
	while (p) {
		if (p->data == x)
			return p;
		p = p->next;
	}
	cout << "查找失败" << endl;
	return NULL;
}
//按位查找,返回第i个节点的指针
LinkList SearchLocade(LinkList L, int i) {
	if (i == 0)
		return L;
	LinkList p = L->next;
	int n = 1;
	while (p && n < i) {
		p = p->next;
		n++;
	}
	return p;
}
//按data查找,返回x是第几个结点,找不到返回-1
int SearchDatai(LinkList L, int x) {
	LinkList p = L->next;
	int i = 1;
	while (p && p->data != x) {
		if (p->data == x)
			return i;
		i++;
		p = p->next;
	}
	return -1;
}

7.插入操作

//插入操作
void Insert(LinkList L, int i, int data) {
	if (i > Length(L) + 1) {
		cout << "位置错误,插入失败" << endl;
		return;
	}
	LinkList p = SearchLocade(L, i - 1);		//按位查找,返回指针
	LinkList q = (LinkList)malloc(sizeof(LNode));
	q->data = data;
	q->next = p->next;
	p->next = q;
	L->data++;        //更新链表长度
}

在链表最后插入n个节点(同尾插法)

//在链表后插入n个结点
void InsertN(LinkList L, int n) {
	LinkList s = L;
	while (s->next != NULL)			//让s指向最后一个结点
		s = s->next;
	while (n--) {
		L->data++;	
		int x;
		cin >> x;
		LinkList r = (LinkList)malloc(sizeof(LNode));
		r->data = x;
		s->next = r;
		s = r;
	}
	s->next = NULL;
}

8.删除操作

删除第i个节点

//删除第i个结点
void DeleteLocade(LinkList L, int i) {
	L->data--;
	LinkList p = SearchLocade(L, i - 1);	//前一个结点
	LinkList q = p->next;					//待删除的第i个结点
	p->next = q->next;
	free(q);								//释放被删结点的内存(不写也行)
}

删除所有数据域为data的节点

//删除所有数据等于data的结点
void DeleteList(LinkList L, int data) {
	LinkList p = L;
	while (p->next) {
		if (p->next->data == data)
			p->next = p->next->next;    //删除
		else
			p = p->next;
	}
}

9.连接两个链表MN

//链表链接函数,N接在M后面
LinkList AddList(LinkList M, LinkList N) {
	LinkList p = M->next;
	LinkList q = N->next;
	while (p->next != NULL)
		p = p->next;						//p成为M链表的最后一个结点
	p->next = q;							//q接在p后面
	return M;
}

10.链表排序

//链表排序函数(冒泡)
void SortList(LinkList L) {
	LinkList tail, p, q;
	tail = NULL;
	while (L->next->next != tail) {
		p = L;
		q = L->next;
		while (q->next != tail) {
			if (q->data > q->next->data) {
				p->next = q->next;
				q->next = p->next->next;
				p->next->next = q;
				q = p->next;				//保证p和q相邻
			}
			q = q->next;
			p = p->next;
		}
		//循环一遍后排好最后一个结点,且q指向最后一个结点,(tail=q)使tail前移一位
		tail = q;
	}
}

11.链表逆置

LinkList ReverseList(LinkList L) {
	LinkList p = L->next, q = p->next;
	LinkList s = nullptr;
	while (p) {
		p->next = s;
		s = p;
		p = q;
		if (q)q = q->next;
	}
	L->next = s;
	return L;
}

全部代码

#include<iostream>
using namespace std;

typedef struct LNode {
	int data;
	struct LNode* next;
}LNode,*LinkList;
//对第二个别名的分析:LinkList等价于struct LNode*
//使用LinkList创建的量为指向结构体的指针
//而使用LNode创建的量为结构体本身

//初始化操作,申请一个头节点
//传入一个地址
void InitList(LinkList& L) {
	L = (LinkList)malloc(sizeof(LinkList));
	//可以让头结点的data存储链表长度
	L->data = 0;
	L->next = NULL;
}


//遍历操作
void PrintList(LinkList L) {		
	//传入一个结构体指针
	//p从头节点指向第一个结点
	LNode* p = L->next;
	//LNode*等同于LinkList,写LinkList p也可以

	//p不为空就输出当前结点的值,并将p指向下一个结点
	while (p) {
		cout << p->data << " ";
		p = p->next;
	}
	cout << "共" << L->data << "个结点";
	cout << endl;
}


//头插法建立单链表
//头插法建立的单链表中节点次序是与输入顺序相反的
//传入的是头指针的地址
LinkList HeadInsert(LinkList& L) {
	InitList(L);
	int x;
	cin >> x;
	while (x != 9999) {		//输入9999表示结束
		LinkList s = (LinkList)malloc(sizeof(LNode));
		s->data = x;
		s->next = L->next;
		//s插在头结点和上一个结点之间,让s指向上一个节点
		L->next = s;
		L->data++;
		cin >> x;
	}
	return L;
}


//尾插法建立单链表
LinkList TailInsert(LinkList& L) {
	InitList(L);
	LinkList s;
	LinkList r = L;//创建一个尾指针,始终指向最后一个结点
	int x;
	cin >> x;
	while (x != 9999) {
		s = (LinkList)malloc(sizeof(LNode));
		s->data = x;
		r->next = s;	//相当于前一个结点的指针域指向新的结点
		r = s;			//更新r,指向最后一个结点
		L->data++;
		cin >> x;
	}
	r->next = NULL;
	return L;
}


//求链表长度
int Length(LinkList L) {
	int len = 0;
	LinkList p = L->next;
	while (p) {
		len++;
		p = p->next;
	}
	return len;
}


//查找
//按data查找,返回指针
LinkList SearchData(LinkList L,int x) {
	LinkList p = L->next;
	while (p) {
		if (p->data == x)
			return p;
		p = p->next;
	}
	cout << "查找失败" << endl;
	return NULL;
}
//按位查找,返回指针
LinkList SearchLocade(LinkList L, int i) {
	if (i == 0)
		return L;
	LinkList p = L->next;
	int n = 1;
	while (p && n < i) {
		p = p->next;
		n++;
	}
	return p;
}
//按data查找,返回x是第几个结点,找不到返回-1
int SearchDatai(LinkList L, int x) {
	LinkList p = L->next;
	int i = 1;
	while (p && p->data != x) {
		if (p->data == x)
			return i;
		i++;
		p = p->next;
	}
	return -1;
}


//插入操作
void Insert(LinkList L, int i, int data) {
	if (i > Length(L) + 1) {
		cout << "位置错误,插入失败" << endl;
		return;
	}
	LinkList p = SearchLocade(L, i - 1);		//按位查找,返回指针
	LinkList q = (LinkList)malloc(sizeof(LNode));
	q->data = data;
	q->next = p->next;
	p->next = q;
	L->data++;
}


//在链表后插入n个结点
void InsertN(LinkList L, int n) {
	LinkList s = L;
	while (s->next != NULL)			//让s指向最后一个结点
		s = s->next;
	while (n--) {
		L->data++;	
		int x;
		cin >> x;
		LinkList r = (LinkList)malloc(sizeof(LNode));
		r->data = x;
		s->next = r;
		s = r;
	}
	s->next = NULL;
}


//删除第i个结点
void DeleteLocade(LinkList L, int i) {
	L->data--;
	LinkList p = SearchLocade(L, i - 1);	//前一个结点
	LinkList q = p->next;					//待删除的第i个结点
	p->next = q->next;
	free(q);								//释放被删结点的内存
}

//删除所有数据等于data的结点
void DeleteList(LinkList L, int data) {
	LinkList p = L;
	while (p->next) {
		if (p->next->data == data)
			p->next = p->next->next;
		else
			p = p->next;
	}
}


//链表链接函数,N接在M后面
LinkList AddList(LinkList M, LinkList N) {
	LinkList p = M->next;
	LinkList q = N->next;
	while (p->next != NULL)
		p = p->next;						//p成为M链表的最后一个结点
	p->next = q;							
	return M;
}


//链表排序函数(冒泡)
void SortList(LinkList L) {
	LinkList tail, p, q;
	tail = NULL;
	while (L->next->next != tail) {
		p = L;
		q = L->next;
		while (q->next != tail) {
			if (q->data > q->next->data) {
				p->next = q->next;
				q->next = p->next->next;
				p->next->next = q;
				q = p->next;				//保证p和q相邻
			}
			q = q->next;
			p = p->next;
		}
		//循环一遍后排好最后一个结点,且q指向最后一个结点,(tail=q)使tail前移一位
		tail = q;
	}
}

//链表逆置
LinkList ReverseList(LinkList L) {
	LinkList p = L->next, q = p->next;
	LinkList s = nullptr;
	while (p) {
		p->next = s;
		s = p;
		p = q;
		if (q)q = q->next;
	}
	L->next = s;
	return L;
}

int main() {
	int n,i,insert;
	LinkList L = TailInsert(L);				//创建
	PrintList(L);							//遍历输出
	cout << "插入多少个结点:";
	cin >> n;
	InsertN(L, n);
	PrintList(L);
//	cout << Length(L) << endl;				//计算长度
//	LinkList search1 = SearchData(L, 5);	//查找5,找到输出5,找不到提示查找失败
//	if(search1!=NULL)
//		cout << search1->data << endl;
	cout << "在第几个结点前插入一个值:";
	cin >> i >> insert;
	Insert(L, i, insert);
	PrintList(L);
//	cout << SearchDatai(L, 4) << endl;		//找到4是第几个结点的值,找不到输出-1
//	DeleteLocade(L, 2);						//删除第2个结点
//	PrintList(L);
	return 0;
}

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值