循环链表,栈,队列,链表实现

明天要面试inginging

发现把代码放在博客里翻看的时候,好方便,所以花点时间来把自己认为基础的东西放过来,仅供自己复习复习

1.循环链表

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
/*
1.建立一个具有n个链节点的循环链表
2.确定第一个报数人的位置;
3.不断从链表中删除节点,直到链表为空;
*/
typedef struct LNode
{
	int data;
	struct LNode* link;
}LNode, *LinkList;

void baoshu(int n, int k , int m)
{
	//n是总人数,k是第一个开始报数的人,m是列出者喊道的数;
	LinkList p, r, 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;
	printf("%d\n",k);
	while(k--)

	{   printf("%d\n",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 = r->link;
	}
}
int main()
{
	baoshu(6,3,2);
}

2.单链表

功能包括:链表的创建,求长,打印,增加一个元素,删除一个元素,排序,反转

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <conio.h>

using namespace std;

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

node* creat()
{
	node * head, *p,*s;
	int x, 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   %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("\n Now, Thesese %d records are:\n", n);
	p=head;
	//if(p!=NULL)
	//{
		while(p!=NULL)
		{
			printf("\n   %d     ", p->data);
			p=p->next;
		}
	//}
}

node* del(node* head, int num)
{
	node* p1, *p2;
	p1=head;
	while(p1->data!=num&&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;
			free(p1);
		}
	}
	else 
	{
		printf("\n%d could not be 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(p1==head)
		{
			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;
	int 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)
	{
		//为什么这样呢?是因为,我总是将p1,p2之间的指针方向变换,但是,始终p2,p3之间是原来的顺序
		//不断的进行p1,p2向后移动,这样就可以达到反转的目的了
		//并且可以证明,这个方法没有错误,因为当我的p2要是空的话,我这个循环就结束了,但是我的p1之前的已经反转完毕
		//唯一需要注意的是,在循环技术后,要将head->next=NULL
		//而且此时我的head就是最后一次循环结束后的p1
		p3=p2->next;
		p2->next = p1;
		p1=p2;
		p2=p3;
	}
	head->next=NULL;
	head=p1;
	return head;
}

int main()
{
	node * p=creat();
	length(p);
	print(p);
	/*
	del(p, 5); 
	length(p);
	print(p);
	p=insert(p,1);
	length(p);
	print(p);    
	*/
    p=sort(p);
    print(p);
    p=reverse(p);
    print(p);

}

3.栈的相关操作

主要就是push,pop操作,定义了两个指向节点的指针,分别是bottom和top作为栈底和栈顶

#include <iostream>
#include <stdio.h>
#include <conio.h>
using namespace std;

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

typedef struct stack
{
	node* top, *bottom;

}stack;

//入栈
//涉及到插入问题,首先要新建一个节点,重要
//这里需要注意的一点是,HQ是一个栈,因此,我的操作是在栈的基础上
//入栈有两个情况:1.栈为空:则很简单,让栈顶以及栈底都指向新建的节点
//2.然后就是不为空的时候,让栈顶的下一个元素指向新建s,然后将栈顶移动到s
stack* push(stack* HQ, int x)
{
	node* p, *s;
	s=(node*)malloc(sizeof(node));
	s->data= x;
	s->next=NULL;

	if(HQ->bottom==NULL) //栈为空
	{
		HQ->bottom = s;
		HQ->top = s;
	}
	else 
	{
		HQ->top->next = s;
		HQ->top=s;
	}
	//free(s);
	return HQ;
}
//出栈
//考虑了三种情况,栈为空,栈有一个节点,栈有多个节点
//这里必须注意的是,要对stack->top以及stack->bottom 进行赋值
//有一点要注意的是,删除节点的时候,一定要保持让他和前面的节点之间的联系不能丢掉
//所以后面我们进行循环的判断是用了p->next!=HQ->top
//循环结束后,p->next就是指向了top
stack* pop(stack* HQ)
{
	node* p;
	int x;
	if(HQ->bottom==NULL)
	{
		printf("\n empty");
	}
	else
	{

		p=HQ->bottom;
		if(HQ->bottom == HQ->top)
		{
			x=HQ->bottom->data;
			HQ->bottom=NULL;
			HQ->top=NULL;
			printf("\n pop(%d)",x);
			return HQ;
		}
		else
		{
			while(p->next!=HQ->top)
			{
				p= p->next;
			}
			x=HQ->top->data;
			//释放top的内存
			free(HQ->top);
			HQ->top = p;
			HQ->top->next = NULL;
		}
	}
	printf("\n pop(%d)",x);
	return HQ;
}

int main()
{
	//node* p = (node*)malloc(sizeof(node));
	stack * Stack = (stack*)malloc(sizeof(stack));
	Stack->bottom = NULL;
	Stack->top = NULL;
	push(Stack,11);
	push(Stack ,12);
	pop(Stack);
	
	for(int i = 1; i <= 15; i++)
	{
		push(Stack, i);
	}
	
	while(Stack->bottom!=Stack->top)
	{
		pop(Stack);
	}

	free(Stack);
	return 0;

}

4.队列

这里只定义了两个操作,入队和出队,其实和栈的方法以及思路都差不多,入队和入栈是一样的,出队和出栈都要考虑三种情况

这里注意,同样定义了queue这个数据结构,里面包含两个指向节点的指针first, rear;

1.队列为空

2.队列有一个节点,判断方法是首位一样

3.队列有多个节点

#include <iostream>
#include <stdio.h>
#include <string>
#include <conio.h>
using namespace std;

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

typedef struct linkqueue
{
	node *first, *rear;
}queue;

//入队,在队末尾插入
queue* insert(queue* HQ, int x)
{
	node* s;
	s=(node*)malloc(sizeof(s));
	s->data=x;
	s->next=NULL;
	if(HQ->rear==NULL)
	{
		HQ->first=s;
		HQ->rear=s;
	}
	else 
	{
		HQ->rear->next=s;//首先将s链接到queue最后,并且将队尾指针指向s
		HQ->rear=s;
	}
	return HQ;
}
//出队,从队首开始删除一个节点
queue* del(queue* HQ)
{
	node* p;
	int x;
	if(HQ->first==NULL)
	{
		printf("\n yichu");
	}
	else 
	{
		x=HQ->first->data;
		p = HQ->first;
		if(HQ->first==HQ->rear)
		{
			free(p);
			HQ->first = NULL;
			HQ->rear = NULL;
		}
		else 
		{
			HQ->first = HQ->first->next;
			free(p);
		}
	}
	return HQ;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值