本文代码分别包括:
头文件、创建链表等
1创建链表
第8题验证是否有环的创建链表
2遍历链表函数
3删除链表结点函数
4-1倒置链表函数-方法一改变指针指向
4-2倒置链表函数-方法二改变结点位置(头插法,断一个接一个)
5删除倒数第n个结点-快慢指针法
6合并两个有序链表
7两数相加
8判断链表中是否有环
*9求环的入口(较难,考试可能性小)
*10求环的长度
*11约瑟夫环-不包含头结点的环删除指定序列结点后相连
主函数
PART 1(自己写的):
准备代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
typedef struct ListNode{
int data;
struct ListNode *next;
}ListNode;
1创建链表
//1创建链表
ListNode *CreatList(){
ListNode *H,*M,*N; //定义头结点指针H、向下链接结点指针M、新创建结点指针N
int n,c; //n为创建链表结点的个数,c为结点data值
H = (ListNode *)malloc(sizeof(ListNode)); //分配一块LinkNode类型的内存空间做头结点
H->next = NULL; //头结点指针域指向空
M = H; //M先指向头结点
printf("please input the number of nodes:");
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
N = (ListNode *)malloc(sizeof(ListNode)); //新创建子结点
printf("please input %dth data:",i);
scanf("%d",&c); //新创建结点data值
N->data = c;
M->next = N; //通过M指针将新结点链接进单链表
M = N; //M指向最后一个结点
}
M->next = NULL;
printf("\n");
return H;
}
第8题验证是否有环的创建链表
//第8题验证是否有环的创建链表
ListNode *CreatList2(){
ListNode *H,*M,*N;
int n,c;
H = (ListNode *)malloc(sizeof(ListNode));
H->next = NULL;
M = H;
printf("please input the number of nodes:");
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
N = (ListNode *)malloc(sizeof(ListNode));
printf("please input %dth data:",i);
scanf("%d",&c);
N->data = c;
M->next = N;
M = N;
}
M->next = H->next->next;
printf("\n");
return H;
}
2遍历链表函数
//2遍历链表函数
void TraverseList(ListNode *pHead){
ListNode *p = pHead->next;
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
3删除链表结点函数
//3删除链表结点函数
void Del_Node(ListNode *pHead,int n){
ListNode *p = pHead; //定义p指向头结点
ListNode *q = pHead->next; //定义q总指向p的下一个结点,q指向待删除元素
int i = 1;
while((q != NULL) && (n>=1) && (i<=n-1)) //循环终止条件为第n-1个元素已经是最后一个元素或者n小于1或者已经查找到索删位置
{
p = p->next;
q = q->next;
i++;
}
if(q == NULL)
p->next = NULL;
else{
p->next = q->next;
free(q);
}
}
4-1倒置链表函数-方法一改变指针指向
//4-1倒置链表函数-方法一改变指针指向
ListNode *ReverseList(ListNode *pHead){
ListNode *p,*q,*r; //定义三个指针依次指向头结点后三个结点
p = pHead->next;
q = p->next;
r = q->next;
if(p == NULL || q == NULL) //如果不存在结点或者只有一个结点,则不发生交换
return NULL;
while(r != NULL) //如果最后一个结点指向NULL,则不再需要向后移动指针
{
q->next = p;
p = q;
q = r;
r = r->next;
}
q->next = p; //对最后两个结点进行倒叙
pHead->next->next = NULL; //将第一个结点指向NULL
pHead->next = q; //用头结点连接链表第最后一个结点,完成倒叙
}
4-2倒置链表函数-方法二改变结点位置(头插法,断一个接一个)
//4-2倒置链表函数-方法二改变结点位置(头插法,断一个接一个)
ListNode *ReverseList2(ListNode * pHead){
ListNode *p,*q;
p = pHead->next;
q = p->next;
while(p != NULL && q != NULL) //如果为空链表或者q指向空,表示无结点调整不再执行循环,注意此处为!=所以要用&&
{
p->next = q->next; //将q结点摘出来插在头结点后
q->next = pHead->next;
pHead->next = q;
q = p->next; //更新指针,使得q总指向要调整的结点,而p指针一直指向最小值
}
return pHead;
}
5删除倒数第n个结点-快慢指针法
//5删除倒数第n个结点-快慢指针法
ListNode *Del_FromEnd(ListNode *pHead,int n){
ListNode *slow,*fast;
slow = pHead;
fast = pHead;
if(n<1) //输入不合法返回
{
printf("wrong,can't do it!\n");
return NULL;
}
while(fast->next != NULL && n) //此处限制的无法删除头结点
{
fast = fast->next;
n--;
}
while(fast->next != NULL)
{
slow = slow->next;
fast = fast->next;
}
fast = slow->next; //复用fast指针指向删除的结点用于free
slow->next = slow->next->next;
free(fast);
return pHead;
}
6合并两个有序链表
//6合并两个有序链表
ListNode *MergeOderList(ListNode *pHead1,ListNode *pHead2){
ListNode *nHead = NULL; //定义一个新的头结点
ListNode *pMove = NULL; //定义一个新的遍历指针
if(pHead1->next == NULL) return pHead2; //如果有一个链表为空则返回另一个链表头
else if(pHead2->next == NULL) return pHead1;
if((pHead1->next->data) <= (pHead2->next->data)) //将第一个结点链入新链表的头结点
nHead = pHead1;
else
nHead = pHead2;
pHead1 = pHead1->next; //从第一个结点开始
pHead2 = pHead2->next;
pMove = nHead;
while((pHead1 != NULL) && (pHead2 != NULL)) //循环对比数据域的值,用pMove指针连接
{
if((pHead1->data) <= (pHead2->data))
{
pMove->next = pHead1;
pMove = pHead1;
pHead1 = pHead1->next;
}
else
{
pMove->next = pHead2;
pMove = pHead2;
pHead2 = pHead2->next;
}
}
if(pHead1 == NULL) //最后一个结点链入
pMove->next = pHead2;
else if(pHead2 == NULL)
pMove->next = pHead1;
return nHead;
}
7两数相加
//7两数相加
ListNode *NumberAdd(ListNode *pHead1,ListNode *pHead2){
ListNode *nHead = (ListNode *)malloc(sizeof(ListNode)); //创建头结点
nHead->next = NULL;
ListNode *pMove = nHead; //设立一个移动指针用于链接后方结点
int symbol = 0; //进位标志
pHead1 = pHead1->next; //两个相加链表从第一个结点开始
pHead2 = pHead2->next;
while((pHead1 != NULL) || (pHead2 != NULL)) //循环终止条件
{
int x = (pHead1 != NULL)? pHead1->data:0; //长度不一致时将先为NULL的置为0以相加时可以得到数值
int y = (pHead2 != NULL)? pHead2->data:0;
int sum = x + y + symbol;
ListNode *p = (ListNode *)malloc(sizeof(ListNode)); //创建结点
if(sum>=10)
{
p->data = sum % 10;
symbol = 1;
}
else
{
p->data = sum;
symbol = 0;
}
pMove->next = p; //使用pMove指针将每次新创建的结点p链进链表
pMove = p;
if(pHead1 != NULL) pHead1 = pHead1->next; //两个链表向下遍历
if(pHead2 != NULL) pHead2 = pHead2->next;
}
pMove->next = NULL;
if(symbol>0) //如果最后一位相加后有进位,需要单独再创建一个结点保存进位值
{
ListNode *p = (ListNode *)malloc(sizeof(ListNode));
p->data = symbol;
pMove->next = p;
p->next = NULL;
}
return nHead;
}
8判断链表中是否有环
//8判断链表中是否有环
void IfCircle(ListNode *pHead){
ListNode *slow = pHead,*fast = pHead; //设置快慢指针,慢指针每次走1步,快指针每次走2步
if(pHead->next == NULL)
printf("NO NODE!!");
while(fast != NULL){
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
printf("I HAVE A CIRCLE!!\n");
break;
}
}
}
*9求环的入口(较难,考试可能性小)
//*9求环的入口(较难,考试可能性小)
ListNode *CircleEntrance(ListNode *pHead){
ListNode *slow = pHead,*fast = pHead,*Len = pHead; //设置快慢指针,慢指针每次走1步,快指针每次走2步,再设置一个指针用于遍历头结点到入口距离
int cot = 0; //cot用来统计环入口距离头结点距离
if(pHead->next == NULL)
printf("NO NODE!!");
while(fast != NULL && fast->next !=NULL) //注意链表为奇数偶数时fast移动后指向的位置
{
slow = slow->next;
fast = fast->next->next;
/*分析:设头结点到环入口距离为a,环长为r,slow和fast相遇时slow在环中走过的距离为x。可得相遇时慢指针走过的长度为a+x,
快指针走过的距离为(a+x+r),由于fast=2倍slow,可得a=r-x,而r-x也等于slow距离环入口的长度*/
if(slow == fast)
{
printf("I HAVE A CIRCLE!\n");
while(Len != slow) //见分析,slow与fast相遇点到环入口的距离等于头结点到环入口的距离
{
Len = Len->next;
slow = slow->next;
cot++;
}
printf("The Circle Entrance is %dth Node!\n",cot);
return Len;
}
}
if(fast == NULL || fast->next == NULL)
return NULL;
}
*10求环的长度
//*10求环的长度
int CircleLength(ListNode *pHead){
ListNode *Head;
ListNode *a = CircleEntrance(Head);
ListNode *b = a->next; //b为环入口的下一位,用户验证走完一圈因为下面循环判断的时候不能相等,所以这里错一位
int cot = 1; //cot用来统计环长
if(a == NULL)
return 0;
while(b != a) //b=a时即为环长
{
b=b->next;
cot++;
}
printf("Circle Length is %d\n",cot);
return cot;
}
*11约瑟夫环-不包含头结点的环删除指定序列结点后相连
//*11约瑟夫环-不包含头结点的环删除指定序列结点后相连
void JosphCircle(ListNode *pHead,int n){
ListNode *p = pHead->next; //p指向第一个结点
ListNode *Del = NULL; //删除结点指针
int cot=0; //cot为统计环长
while(pHead->next != NULL)
{
pHead = pHead->next;
cot++;
}
pHead->next = p; //将链表变成环
if(n>=cot) printf("Bad Man!!"); //删除序列大于环长则不存在约瑟夫环
while(p->next != p)
{
for(int i=1;i<=n;i++)
p = p->next;
Del = p->next;
printf("DELE Node Number is %d\n",Del);
p->next = Del->next;
free(Del);
/*此方法不对的原因是删除的是不是p本身而是下一个元素?
p->data = p->next->data;
Del = p->next;
p->next = Del->next;
free(Del);*/
}
}
主函数
int main()
{
ListNode *chain,*chain1,*chain2;
chain = CreatList();
//Del_Node(chain,4);
//ReverseList2(chain);
//Del_FromEnd(chain,5);
//chain1 = CreatList();
//chain2 = CreatList();
//chain = MergeOderList(chain1,chain2);
//chain = NumberAdd(chain1,chain2);
JosphCircle(chain,2);
TraverseList(chain);
//chain = CreatList2();
//IfCircle(chain);
//CircleEntrance(chain);
//CircleLength(chain);
return 0;
}
PART 2(西交无尽):
#include<stdio.h>
#include<stdlib.h>
#define null NULL
//Definition of ListNode
typedef struct list_node
{
int data ; //数据域,用于存储数据
struct list_node *next ; //指针,可以用来访问节点数据,也可以遍历,指向下一个节点
}ListNode;
//尾插法创建链表
ListNode *CreateList(int n)
{
ListNode *head;
ListNode *p,*pre;
int i;
head=(ListNode *)malloc(sizeof(ListNode));
head->next=NULL;
pre=head;
for(i=1; i<=n; i++)
{
printf("input name of the %d data:",i);
p=(ListNode *)malloc(sizeof(ListNode));
scanf("%d",&p->data);
pre->next=p;
pre=p;
}
p->next = NULL;
//p->next=head->next->next;
return head;
}
//遍历链表函数
void TraverseList(ListNode *pHead)
{
ListNode *p = pHead->next; //将头节点的指针给予临时节点p
while(p != NULL) //节点p不为空,循环
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return ;
}
//删除链表节点函数
int Del_Node(ListNode *pHead,int back)
{
int i = 0;
int data;
ListNode *_node = pHead;
ListNode *pSwap;
if ((back < 1) && (NULL == _node->next))
{
printf("删除失败!\n");
return 0;
}
while(i < back-1)
{
_node = _node->next;
++i;
}
pSwap = _node->next;
data = pSwap->data;
_node->next = _node->next->next;
free(pSwap);
return data;
}
//倒置链表3
ListNode *node2(ListNode *pHead){
pHead = pHead->next;
ListNode *p = NULL;
while(pHead){
ListNode *nx = pHead->next;
pHead->next = p;
p = pHead;
pHead = nx;
}
return p;
}
//倒置链表1
ListNode *node1(ListNode *pHead){
ListNode *p = NULL;
ListNode *q = NULL;
ListNode *r = NULL;
if(pHead->next == NULL){return NULL;}
if(pHead->next->next == NULL){return pHead;}
else if(pHead->next->next->next == null) {
p = pHead->next;
q = p->next;
q->next = p;
pHead->next = q;
p->next = NULL;
}
else if(pHead->next->next->next != null){
p = pHead->next;
q = p->next;
r = q->next;
p->next = null;
while(r != NULL){
q->next = p;
p = q;
q = r;
r = r->next;
}
q->next = p;
pHead->next = q;
}
return pHead;
}
//倒置链表3
ListNode* ReverseList(ListNode* pHead)
{
ListNode *q=pHead->next;
ListNode *p=NULL;
ListNode *r=NULL;
if(pHead->next==NULL)
return NULL;
while(q->next)
{
r=q->next;
q->next=p;
p=q;
q=r;
}
q->next=p;
pHead->next = q;
return pHead;
}
//删除倒数第N个节点
ListNode *removeNthFromEnd(ListNode *head, int n)
{
// write your code here
ListNode *fast = head;
ListNode *low = head;
ListNode *pre = NULL;
if(head == NULL || n <= 0)
{
return NULL; //输入的链表为空,或输入的n不合法;
}
for(int i = 0; i < n-1; i ++)
{
if(fast->next)
{
fast = fast->next;
}
else
{
return NULL; //输入的n大于链表的长度;
}
}
while(fast->next)
{
fast = fast->next;
pre = low; //需要保存需要删除的那个结点的上一个结点。
low = low->next;
}
if(low == head) //删除的那个结点是头结点。
{
head = head->next;
}
else
{
pre->next = pre->next->next;
}
return head;
}
//合并两个有序链表
ListNode *MergeTwoOrderedLists(ListNode *pHead1, ListNode *pHead2)
{
ListNode *pTail = NULL;//指向新链表的最后一个结点 pTail->next去连接
ListNode *newHead = NULL;//指向合并后链表第一个结点
if (pHead1->next == NULL)
{
return pHead2;
}
else if(pHead2->next == NULL)
{
return pHead1;
}
else
{
//确定头指针
if ( pHead1->next->data < pHead2->next->data)
{
newHead = pHead1;
}
else
{
newHead = pHead2;
}
pHead1 = pHead1->next;
pHead2 = pHead2->next;
pTail = newHead; //指向第一个结点
while ( pHead1 && pHead2)
{
if ( pHead1->data <= pHead2->data )
{
pTail->next = pHead1;
pHead1 = pHead1->next;
}
else
{
pTail->next = pHead2;
pHead2 = pHead2->next;
}
pTail = pTail->next;
}
if(pHead2 != NULL)
{
pTail->next = pHead2;
}
else if(pHead1 != NULL)
{
pTail->next = pHead1;
}
return newHead;
}
}
//两数相加
ListNode *addTwoNumbers(ListNode *pHead1, ListNode *pHead2) {
ListNode *L,*curr;
L = (ListNode *)malloc(sizeof(ListNode));
L->next = NULL;
curr = L;
ListNode *p = pHead1->next, *q = pHead2->next;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p->data : 0;
int y = (q != null) ? q->data : 0;
int sum = carry + x + y;
carry = sum / 10;
ListNode *r = (ListNode *)malloc(sizeof(ListNode));
r->data = sum%10;
curr->next = r;
curr = curr->next;
if (p != null) p = p->next;
if (q != null) q = q->next;
}
curr->next = NULL;
if (carry > 0) {
ListNode *r = (ListNode *)malloc(sizeof(ListNode));
r->data = carry;
curr->next = r;
curr->next->next = NULL;
}
return L;
}
//检查环
int HasCircle(ListNode * pHead)
{
ListNode * pFast = pHead; // 快指针每次前进两步
ListNode * pSlow = pHead; // 慢指针每次前进一步
while(pFast != NULL && pFast->next != NULL)
{
pFast = pFast->next->next;
pSlow = pSlow->next;
if(pSlow == pFast) // 相遇,存在环
return 1;
}
return 0;
}
//找出环的入口
ListNode *searchEntranceNode(ListNode *pHead)
{
ListNode *pSlow=pHead;//p表示从头结点开始每次往后走一步的指针
ListNode *pFast=pHead;//q表示从头结点开始每次往后走两步的指针
while(pFast !=NULL && pFast->next !=NULL)
{
pSlow=pSlow->next;
pFast=pFast->next->next;
if(pSlow == pFast){
break;//p与q相等,单链表有环
}
}
if(pFast==NULL || pFast->next==NULL)
return NULL;
pSlow=pHead;
while(pSlow != pFast)
{
pSlow=pSlow->next;
pFast=pFast->next;
}
return pSlow;
}
//求环长
int circleLength(ListNode *pHead)
{
ListNode *p=searchEntranceNode(pHead);//找到环的入口结点
if(p==null)
return 0;//不存在环时,返回0
ListNode *q = p->next;
int length=1;
while(p != q)
{
length++;
q=q->next;
}
return length;//返回环的长度
}
//约瑟夫环
void JosephProblem(ListNode *pHead,int m){
ListNode *p = pHead->next;
while(pHead->next != NULL) pHead = pHead->next;
pHead->next = p;
while(p->next != p){
for(int i = 0;i<m-1;i++) p=p->next;
//打印
printf("%d ",p->next->data);
ListNode *del = p->next;
p->next = del->next;
free(del);
/*
//特殊的删除方法
p->data = p->next->data;
ListNode *del = p->next;
p->next = del->next;
free(del);
*/
}
}
int main()
{
ListNode *chain,*nchain,*nnchain,*nnnchain = NULL;
int n,back2;
chain = CreateList(5);
JosephProblem(chain,2);
return 0;
}
(感谢西交无尽学长提供以上题目练习)