#include<iostream>
#include<cassert>
using namespace std;
class Node
{
public:
int data;
Node* next;
};
typedef class Node List_Node;
/*---------------------------------------------------------
在链表的末端插入新的节点,创建链表:这里我建立的是带有头节点
的链表,头结点的数据域是null,指针域存储的是第一个节点的地址
-----------------------------------------------------------*/
List_Node *creat(int n)
{
List_Node *head;//头指针
List_Node *p1, *p2;//p1为移动指针,p2为不断新建的节点
int i;
head = (List_Node*)malloc(sizeof(List_Node));
head->data = NULL;//将头节点的数据置为NULL
p1 = head;//将头结点的首地址赋给p1
for (i = 0; i < n; i++)
{
cout << "第"<<i<<"个数据" << endl;
p2 = (List_Node*)malloc(sizeof(List_Node));
cin >> p2->data;//输入节点的所存储的数据
p1->next = p2;//将插入的节点的地址赋给上一个节点的链接指针
p1 = p2;//把节点p2的地址赋给p1,相当于把p1指向的位置后移动一位
}
p1->next = NULL;//将最后一个节点的链接指针置为null
return head;// 返回这个链表的首地址
}
/*------------
打印整个链表
-------------*/
void print(List_Node *L)
{
List_Node *p;
p = L->next;
cout << "输出链表:";
while (p)
{
cout << p->data << ' ';
p = p->next;
}
cout << endl;
}
/*--------------------
删除指定的节点
----------------------*/
void delete_node(List_Node *L, int x)
{
List_Node *p = L;
List_Node *pre;
while (p->next->data != x && p != NULL)//找到被删除节点的前一个节点
p = p->next;
if (p)
{
pre = p->next->next;
free(p->next);
p->next= pre ;
}
}
//找到倒数第K个节点,最后一个节点为倒数第一个
List_Node *finde_node(List_Node* pHead, int k)
{
assert(pHead != NULL);
// 先获得链表的长度
int length = 0;
List_Node* p = pHead;
while (p != NULL)
{
length++;
p = p->next;
}
assert(length >= k);
p = pHead;
// 在从头移动 length-k次就好了
for (int i = 0; i<length - k; i++)
p = p->next;
return p;
}
/*--------------------------------------------------------
求单链表倒数第N个数:利用两指针遍历表,保持他们的距离为n,当
后面的指针为NULL时,输出前面指针所指向的数,即倒数第N个数。
----------------------------------------------------------*/
int index_backn(List_Node *L, int n)
{
List_Node *fir, *sec;
fir = L->next;
sec = L->next;
int i;
//当i小于n的时候第二个指针移动n步,当i大于等于n时候两个指针一起移动。
for (i = 0; sec; i++)
{
if (n<=i)
{
fir = fir->next;
sec = sec->next;
}
else
{
sec = sec->next;
}
}
return fir->data;
}
/*------------------------------------------------------------------
找到单链表的中间结点:也是利用两个指针,一个慢移动指针(一次走一步),一
个快移动指针(一次走两步),当快指针指向NULL时,则慢指针指向中间节点。
--------------------------------------------------------------------*/
int find_mid(List_Node *L)
{
List_Node*fir, *sec;
fir = L->next;
sec = L->next;
while ((sec->next) && (sec->next->next))
{
fir = fir->next;
sec = sec->next->next;
}
return fir->data;
}
/*-------------------------------------------------------------------------
链表逆置:利用三个指针来实现的,三个连续指针依
次向前移动,每次反转前两个指针指向数之间的指针
更清楚的一点的解释:通过不断的移动三个指针,每次逆转链接指针的指向,移动到
最后整个链表的链接指向和原来的指向刚好相反,儿节点中数据保持不变,在输出链表
中根据链表的指向输出数据。
---------------------------------------------------------------------------*/
void ReverseList(List_Node *L)
{
if (!L->next->next)
;
else{
List_Node *p3 = L->next->next->next;
List_Node *p2 = L->next->next;
List_Node *p1 = L->next;
L->next->next = NULL;//将第一个节点的(头结点并不是第一个节点)指针域置为空
//不断移动两个指针,每次把前两个指针的链接指向逆转
while (p3){
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;//移动到最后别忘记把最后一个节点与倒数第二个节点链接上
L->next = p2;//把头节点链接上最后一个节点
}
}
//递归的方法逆转链表
List_Node *digui_ReverseList(List_Node *L)
{
if ((L == NULL) || (L->next == NULL))
return L;
List_Node *p1 = L->next;
List_Node *p2 = L->next->next;
L=digui_ReverseList(p2);
p2->next = p1;
p1->next = NULL;
return L;
}
/*-----------------------------------
带头节点表的删除
-------------------------------------*/
List_Node *my_reverse(List_Node *head)
{
if (head == NULL || head->next == NULL)
return head;
List_Node *pre, *cur,*ne;
pre = head->next; //将前面几个节点的地址依次保存在新定义的结构体指针
cur = pre->next;
while (cur)
{
ne = cur->next;
cur->next = pre; //直接将两个指针的指向反转
pre = cur; //将当前节点赋给pre,将三个指针在链表中的位子都往后移一位
cur = ne;
}
head->next->next = NULL; //将原来的第一个节点的指针域赋为空,作为尾节点
head->next = pre; //将原来的尾节点变成新链表的第一个节点
return head;
}
int main()
{
List_Node *mylist;
mylist = creat(5);
//print(mylist);
//List_Node *p;
//delete_node(mylist, 3);
//print(mylist);
//p=finde_node(mylist, 2);
//cout << p->data << endl;
//print(mylist);
int i,j=0;
i= index_backn(mylist, 2);
j = find_mid(mylist);
cout << i << '\n' << j << endl;
mylist = my_reverse(mylist);
//ReverseList(mylist);
print(mylist);
return 0;
}
带头节点链表的操作(链表的创建、删除、查找、逆转、打印等等)
最新推荐文章于 2022-06-22 17:11:33 发布