带头节点链表的操作(链表的创建、删除、查找、逆转、打印等等)

来源:互联网 发布:vmware12安装mac 编辑:程序博客网 时间:2024/05/16 01:20
#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;//将头节点的数据置为NULLp1 = head;//将头结点的首地址赋给p1for (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;//将最后一个节点的链接指针置为nullreturn 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;}

0 0
原创粉丝点击