本篇内容中的代码注释皆为本人的理解,如果有误,请指正!
本篇内容参考自:http://www.nowamagic.net/librarys/veda/detail/1803
Link.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
struct node//创建一个结构体
{
string data;
struct node *next;
};
class Link
{
public:
Link(void);//构造函数,用于初始化
void insertIndex(string _data,int index);//插入指定位置
void insertFirst(string _data);//在头部插入
void insertLast(string _data);//在末尾插入
void delIndex(int index);//删除指定位置
void delFirst();//删除头部
void delLast();//删除尾部
void delAll();//删除全部
void findIndex(int index);//查找指定位置的数据
void findData(string _data);//查找指定数据的位置
void print()const;//打印
void getNodeFromBack(int n);//获取单链表倒数第n个结点的值
void reverse();
int getLen()const;//获取链表长度
~Link(void);
private:
struct node *head;//定义一个头节点head
int len;//链表的长度
};
Link.cpp:
#include "Link.h"
//用于初始化
Link::Link(void)
{
head = new node;//给head开辟空间,注:(.h)中只定义head,但是没有开辟空间,
head->next= NULL;//使头结点指向下一结点的指针域置空
head->data="head";//头结点的数据域存值
len = 0;//初始值为0,不算头结点
}
//插入指定位置
void Link::insertIndex(string _data,int index){
if(index <0)//判断输入的下标是否合法
{
cout<<"index error"<<endl;
return ;//一般void不能返回一个值,即不能return 一个值.但是这里只是return;故可以使用
}
node *newNode = new node;//创建一个新结点,该结点为待插入的结点
node *temp =head;//创建一个新结点用来存储头结点
if(index ==0){//如果插入的下标为0,即要插入到头结点的前面时
newNode->next=temp;//新结点的指针域指向temp结点
head = newNode;//把插入的结点设置为头结点,因为头结点永远是在最前面的
newNode->data = _data;//把要存储的值 赋值到新结点的数据域中
len++;//长度+1
return ;
}
if(index >0){
int k =1;//一个比较标记,值为1代表从是第一个结点
while(k<index && temp !=NULL){//如果比较标记小于要插入的位置 且temp结点不为NULL时,执行循环体
temp =temp->next;//temp结点指向下一个结点
++k;//比较标记跟着循环体改变,当不满足k<index关系时,说明已经找到要插入的位置了
}
if(temp ==NULL){//如果temp的结点为空,则说明整个链表为空,结点插入不了
cout<<"NULL"<<endl;
return ;
}
newNode->next = temp->next;//待插入结点的指针域指向temp结点的下一结点
temp->next = newNode;//temp结点的指针域指向待插入结点
newNode->data = _data;///把要存储的值 赋值到新结点的数据域中
len++;//长度+1
}
}
//头部插入
void Link::insertFirst(string _data){
if(head ==NULL){//判断当前头结点是否为空,如果为空,则插入不了
cout<<"head is NULL"<<endl;
return ;
}
node *newNode =new node;//创建一个新结点,该结点为待插入的结点
newNode->next =head->next;//新结点的指针域指向头结点的下一结点
head->next = newNode;//头结点的指针域指向新结点
newNode->data =_data;//把要存储的值 赋值到新结点的数据域中
len++;//长度+1
}
//末尾插入
void Link::insertLast(string _data){
node *temp =head;//创建一个新结点用来存储头结点
while(temp->next !=NULL){//一直循环到链表的末尾,当temp的指针域为空时,代表temp结点为最后一个结点
temp =temp->next;//temp结点依次往后更替
}
node *newNode =new node;//创建一个新结点
temp->next =newNode;//temp结点的指针域指向新结点 注:这是新结点为最后一个结点
newNode->next =NULL;//新结点的指针域置空
newNode->data =_data;//把要存储的值 赋值到新结点的数据域中
len++;//长度+1
}
//删除指定位置
void Link::delIndex(int index){
if(index <0){//判断输入的下标是否合法
cout<<"index error"<<endl;
return ;
}
else if(index ==0){//当下标为0时,代表要删除的是当前头结点
head = head->next;//把头结点移到下一结点
len--;//长度-1
}
else if(index >0){
node *temp = head;//创建新结点存储头结点
int k=1;//一个比较标记,值为1代表从是第一个结点
while(k<index &&temp!=NULL){//如果比较标记小于要删除的位置 且temp结点不为NULL时,执行循环体
temp =temp->next;//temp结点指向下一个结点
k++;//比较标记跟着循环体改变,当不满足k<index关系时,说明已经找到要删除的位置了
}
node *p = temp->next;//创建新结点指向temp结点的下一结点
temp->next = p->next;//temp的指针域指向p的下一结点,即temp的下一个结点的下一个结点
delete p;//从堆中删除结点
len--;//长度-1
}
}
//删除头部
void Link::delFirst(){
if(head ==NULL){//判断头结点是否为空
cout<<"head is NULL"<<endl;
return ;
}
node *temp = head;//创建新结点存储头结点
head = head->next;//当前头结点指向下一结点
delete temp;//从堆中删除结点
len--;//长度-1
}
//删除尾部
void Link::delLast(){
node *temp =head;//创建新结点存储头结点
node *newNode=new node;//创建一个新结点
while(newNode->next!=NULL){//循环一直到最后的结点指针域为空
temp = temp->next;
newNode = temp->next;
}
temp->next = newNode->next;//temp结点的指针域指向newNode的指针域,即最后一个结点的指针域
newNode->next=NULL;//newNode的指针域置为空,代表最后一个结点
delete newNode;//删除结点
len--;//长度-1
}
//删除全部
void Link::delAll(){
node *temp ;//创建一个结点
int k=len;//用来保存当前的长度
for(int i=0;i<k;i++){//使temp结点从头结点遍历到最后结点,依次删除
temp =head;
head=head->next;
len--;
delete temp;
}
}
//查找指定位置的数据
void Link::findIndex(int index){
if(index>len ||index<0 ){//判断下标是否合法
cout<<"index error"<<endl;
return;
}
int k=0;//一个标记,从头结点开始
node *temp =head;//创建新结点存储头结点
while(k<index && temp!=NULL){//依次循环,直到标记和下标相等,说明找到了要查找的位置
temp =temp->next;
++k;
}
if(index ==0)cout<<"该位置为头结点,其数据为:"<<temp->data<<endl;
else cout<<"查找第"<<index<<"个的数据为:"<<temp->data<<endl;
}
//查找指定数据的位置
void Link::findData(string _data){
node *temp =head;//创建新结点存储头结点
for(int i=0;i<=len;i++){//循环遍历
if(temp !=NULL && temp->data ==_data){//当找到数据时,打印输出
if(i==0) cout<<_data<<"的位置为: 头结点"<<endl;
else cout<<_data<<"的位置为: "<<i<<endl;
return ;
}
temp =temp->next;//如果没找到 继续循环找下去
}
cout<<"没有找到"<<_data<<endl;
}
//获取单链表中倒数第n个结点的值
void Link::getNodeFromBack(int n){//建立两个指针,第一个先走n步,然后第2个指针也开始走,
node *temp =head; //两个指针步伐(前进速度)一致。当第一个结点走到链表末尾时,
node *newNode =head; //第二个节点的位置就是我们需要的倒数第n个节点的值。
int k=0;
while(k <n &&temp->next !=NULL){
k++;
temp = temp->next;
}
if(temp->next ==NULL && k<n-1){
cout<<"超出链表长度"<<endl;
return ;
}
while(temp !=NULL){
//查找倒数第N个元素
temp =temp->next;
newNode =newNode->next;
}
cout<<"倒数第"<<n<<"的值为:"<<newNode->data<<endl;
}
//链表逆序
void Link::reverse(){
node *p1,*p2,*p3;//创建三个新结点
p1 =head->next;//p1 结点存储的是第一个结点
p2 = p1->next;//p2 结点存储的是第二个结点
p1->next =NULL;//将第一个结点指向的下一结点置空
while(p2!=NULL){//p2结点为主要操作结点,当p2为空时,说明已经逆序完毕
p3 =p2->next;//p3结点存储的是p2结点的下一结点
p2->next =p1;//p2结点指向p1
p1 = p2;//把逆序过来的结点置为p1
p2 = p3;//p2结点向后移一位
}
head->next =p1;//最后把头结点的下一结点置为最终逆序过来的p1结点即可
//(即头结点指向p1,而p1指向后面的结点,形成链表)
}
//打印
void Link::print()const {
if(head== NULL){//判断头结点是否为空
cout<<"error"<<endl;
return ;
}
cout<<"len: "<<getLen()<<endl;
cout<<"头结点的数据为:"<<head->data<<endl;
node *temp = head->next;//创建新结点存储头结点的下一结点
for(int i=0;temp !=NULL;i++){//循环遍历输出
cout<<"第"<<i+1<<"个的数据为:"<<temp->data<<endl;
temp = temp->next;
}
cout<<endl;
}
//获得长度
int Link::getLen()const{
return len;
}
Link::~Link(void)
{
node *temp;//定义一个新结点
for(int i=0;i<=len;i++){//循环遍历,从头结点到最后结点,依次删除
temp =head;
head =head->next;
delete temp;
// cout<<"析构"<<endl;
}
}
main.cpp:
#include <iostream>
#include "Link.h"
using namespace std;
int main()
{
Link l;
cout<<"打印*****************"<<endl;
l.print();
cout<<"尾部插入******************"<<endl;
l.insertLast("a");
l.insertLast("b");
l.insertLast("c");
l.insertLast("d");
l.print();
cout<<"逆序打印*******************"<<endl;
l.reverse();
l.print();
cout<<"指定位置插入*******************"<<endl;
l.insertIndex("e",3);
l.print();
cout<<"首部插入*******************"<<endl;
l.insertFirst("f");
l.print();
cout<<"查找*******************"<<endl;
l.getNodeFromBack(2);
l.findData("a");
l.findData("q");
l.findIndex(4);
l.findIndex(9);
cout<<endl;
cout<<"删除指定位置*******************"<<endl;
l.delIndex(0);
l.print();
cout<<"删除头部*******************"<<endl;
l.delFirst();
l.print();
cout<<"删除尾部*******************"<<endl;
l.delLast();
l.print();
cout<<"删除全部*******************"<<endl;
l.delAll();
l.print();
return 0;
}