链表,双链表,循环链表的常见操作

这篇文章用于巩固,复习用,所以不做链表的慨念和相关知识。直接上代码,来复习那些已经快要忘却的链表操作。

理解的同时,动手敲几遍代码,才能牢固掌握欧


实现单链表的建立,测长,打印,删除,插入,排序,逆置,查找中间节点
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <conio.h>

typedef struct student{
	int data;
	struct student *next;
}node;

node *create()
{
	node *head,*p,*s;
	int x,int cycle = 1;
	head = (node*)malloc(sizeof(node));
	p = head;
	while(cycle)
	{
		printf("\nplease input the data:");
		scanf("%d",&x);
		if(x != 0)
		{
			s = (node*)malloc(sizeof(node));
			s->data = x;
			printf("\n%d",s->data);
			p->next = s;
			p = s;
			
		}
		else{
			cycle = 0;
		}
	}
	head = head->next;
	p->next = NULL;
	printf("\n yyy %d",head->data);
	return(head);
}

int length(node *head)
{
	int n = 0;
	node *p;
	p = head;
	while(p != NULL)
	{
		p = p->next;
		n++;
	}
	return(n);
}

void print(node *head)
{
	node *p;int n;
	n = length(head);
	printf("\nNow,These %d records are:\n ",n);
	p =head;
	
	while(p != NULL)
	{
		printf("%d\n",p->data);
		p = p->next;
	}
}

node *delete(node *head,int num)
{
	node *p1,*p2;
	p1 = head;
	while(num != p1->data && p1->next != NULL)
	{
		p2 = p1;
		p1 = p1->next;
	}
	if(num == p1->data)
	{
		if(p1 == head)
		{
			head = p1->next;
			free(p1);
		}
		else
		{
			p2->next = p1->next;
		}
	}
	else
	{
		printf("\n%d could not been found",num);
	}
	return head;
} 

node *insert(node *head,int num)
{
	node *p0,*p1,*p2;
	p1 = head;
	p0 = (node *)malloc(sizeof(node));
	p0->data = num;
	while(p0->data > p1->data && p1->next != NULL)
	{
		p2 = p1;
		p1 = p1->next;
	}
	if(p0->data <= p1->data)
	{
		if(head == p1)
		{
			p0->next = p1;
			head = p0;
		}
		else
		{
			p2->next= p0;
			p0->next = p1;
		}
		
	}
	else
	{
		p1->next = p0;
		p0->next = NULL;
	}
	return head;
}

node *sort(node *head)
{
	node *p,*p2,*p3;
	int n,temp;
	n = length(head);
	if(head == NULL || head->next == NULL)
	{
		return head;
	}
	p = head;
	for(int j = 1;j < n;++j)
	{
		p = head;
		for(int i = 0;i < n - j;++i)
		{
			if(p->data > p->next->data)
			{
				temp = p->data;
				p->data = p->next->data;
				p->next->data = temp;
			}
			p = p->next;
		}
	}
	return head;
}

node *reverse(node *head)
{
	node *p1,*p2,*p3;
	if(head == NULL || head->next == NULL)
	{
		return head;
	}
	p1 = head;
	p2 = p1->next;
	while(p2)
	{
		p3 = p2->next;
		p2->next = p1;
		p1 = p2;
		p2 = p3;
	}
	head->next = NULL;
	head = p1;
	return head;
}

void searchmid(node *head,node *mid)
{
	node *temp = head;
	while(head->next->next != NULL)
	{
		head = head->next->next;
		temp = temp->next;
		mid = temp;
	}+
	
}

int main()
{
	node *head,stud;
	int n,del_num,insert_num;
	head = create();
	print(head);
	cout << "\nInt : ";
	cin >> del_num;
	head = delete(head,del_num);
	print(head);
	cout << "\nplease input the insert data:";
	cin >> insert_num;
	head = insert(head,insert_num);
	print(head);
	return 0;
}

下面是双链表

双向链表的创建,插入,删除
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <conio.h>

typedef struct student{
	int data;
	struct student *next;
	struct student *pre;
}dnode;

dnode *create()
{
	dnode *head,*p,*s;
	int x,int cycle = 1;
	head = (dnode *)malloc(sizeof(dnode));
	p = head;
	while(cycle)
	{
		printf("\nplease input the data:");
		scanf("%d",&x);
		if(x != 0)
		{
			s = (dnode *)malloc(sizeof(dnode));
			s->data = x;
			printf("\n%d",s->data);
			p->next = s;
			s->pre = p;
			p = s;
		}
		else
			cycle = 0;
	}
	head = head->next;
	head->next = NULL;
	p->next = NULL;
	printf("\n yyy %d",head->next);
	return head;
}

dnode *delete(dnode *head,int num)
{
	dnode *p1,*p2;
	p1 = head;
	while(num != p1->data && p1->next != NULL)
	{
		p1 = p1->next;
	}
	if(num == p1->next)
	{
		if(p1 === head)
		{
			head = head->next;
			head->pre = NULL;
			free(p1);
		}
		else if(p1->next == NULL)
		{
			p1->pre->next = NULL;
			free(p1);
			
		}
		else
		{
			p1->next->pre = p1->pre;
			p1->pre->next = p1->next;
		}
		
	}
	else
	{
		printf("\n%d could not been found",num);
	}
	return head;
}

dnode *insert(dnode *head,int num)
{
	dnode *p0,*p1;
	p1 = head;
	p0 = (dnode *)malloc(sizeof(dnode));
	p0->data = num;
	while(p0->data > p1->data && p1->next != NULL)
	{
		p1 = p1->next;
	}
	if(p0->data <= p1->data)
	{
		if(head = p1)
		{
			p0->next = p1;
			p1->pre = p0;
			head = p0;
		}
		else
		{
			p1->pre->next = p0;
			p0->next = p1;
			p0->pre = p1->pre;
			p1->pre = p0;
		}
	}
	else
	{
		p1->next = p0;
		p0->pre = p1;
		p0->next = NULL;
	}
	return head;
}


int length(dnode *head)
{
	int n = 0;
	dnode *p;
	p = head;
	while(p != NULL)
	{
		p = p->next;
		n++;
	}
	return(n);
}

void print(dnode *head)
{
	dnode *p;int n;
	n = length(head);
	printf("\nNow,These %d records are:\n ",n);
	p =head;
	
	while(p != NULL)
	{
		printf("%d\n",p->data);
		p = p->next;
	}
}

int main()
{
	dnode *head,stud;
	int n,del_num,insert_num;
	head = create();
	print(head);
	cout << "\nInt : ";
	cin >> del_num;
	head = delete(head,del_num);
	print(head);
	cout << "\nplease input the insert data";
	cin >> insert_num;
	head = insert(head,insert_num);
	print(head);
	return 0;
}

下面是循环链表

循环链表(经典实例)约瑟夫环问题

已知n个人(以编号1,2,3,4...,n分别表示)围在一张圆桌上,从编号k的人开始报数,
数到m的那个人出列,它的下一个人有从k开始报数,数到m的那个人出列,依次规律重
复,知道圆桌上没有人,使用c++编程实现。

街二觉问题的核心步骤:
1,建立一个具有n个结点的无头结点的循环链表。
2,确定一个人报数。
3,不断的从链表删除结点,直到链表为空。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

#define ERROR 0;

typedef struct LNode
{
	int data;
	struct LNode *link;
}LNode,*LinkList;

void JOSEPHUS(int n,int k,int m)  //n为总人数,k为第一个开始报数的人,m为出列者喊的数。
{
	/*
	p为当前节点,r为辅助节点,指向p的前驱节点,list为头节点
	*/
	LinkList p,r,list,curr;
	p = (LinkList)malloc(sizeof(LNode));
	p->data = 0;
	p->link = p;
	curr = p;
	for(int i = 1;i < n;i++)
	{
		LinkList t = (LinkList)malloc(sizeof(LNode));
		t->data = i;
		t->link = curr->link;
		curr->link = t;
		curr = t;
	}
	//把当前指针移动到到第一个报数的人
	r = curr;
	while(k--)
	{
		r = p;
		p = p->link;
	}
	while(n--)
	{
		for(int s = m -1;s--;r = p,p = p->link)
		{
			r->link = p->link;
			printf("%d->",p->data);
			free(p);
			p = p->link;
		}	
	}	
}

int main()
{
	JOSEPHUS(13,4,1);
	
	return 0;
}
希望这些代码,能让你对链表的基本操作能有很好的帮助,自己动手多敲几遍,我相信你也会运用的很熟练。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值