CPP随笔——链表初识1

本人学到Cpp链表的时候啊,那是肥肠的激动,难道我这么快就可以在Cpp里面玩到列表了吗,然后我就意识到了这东西虽然原理看起来简单,但做起来还真不是这样。

今天我们先来复现一下整形列表(其实实现灵活列表的话,可以把结构的数据设计为一个void指针和一个记录数据类型的整形,比如规定1是整形,2是long,3是...)

先不管存储数据的方式,今天的重点是尝试复现列表的创建、连接、扩展、反向

我先写一个头部为空的链表

我们先把头文件、结构和函数定义这些准备工作做上

#include <iostream>
using namespace std;

struct List
{
    int data;
    List *pN;
}; 

List *create(int*,int);
void show_list(List*);
void add_to_end(List*,List*);
void append(List*,int*,int len);
void reverse(List*); 
链表1-0——准备工作

 然后开始一个个写程序

List *create(int *data,int len)
{
    List *res;
    res = new List;
    *res={0,NULL};
    append(res,data,len);
    return res;
}
链表1-1——create
voidshow_list(List*head){head=head->pN;if(head){cout<<head->data<<"\t";if(head->pN){show_list(head);}}}
链表1-2——打印链表
void add_to_end(List* head,List* new_list)
{
    if(head->pN)
    {
        add_to_end(head->pN,new_list);
    }
    else
    {
        head->pN=new_list->pN;
    }
}
链表1-3——将new_list拼接到list后面
void appendone(List* head,int data)
{
    List *new_list,*new_head;
    new_list=new List;//一定要分配新的栈空间 ,不然新的结构的pN指针就会指向自身 
    new_head=new List;
    *new_head={0,new_list};
    *new_list={data,NULL}; 
    add_to_end(head,new_head);
}
链表1-4——append
void append(List* head,int *data,int len)
{
        for(int i=0;i<len;i++)
    {
        appendone(head,data[i]);
    }
}
链表1-5——加入一系列数
void reverse(List *head)
{
    List *new_head,*pt,*pc,*pp;
    pc=head->pN;
    pt=NULL;
    pp=NULL;
    while(pc)
    {
        pt=pc->pN;
        pc->pN=pp;
        pp=pc;
        pc=pt;
    } 
    *head={0,pp};
} 
链表1-6——链表反转

然后我们可以尝试运行一下

int main(){
    int ar[4]={1,2,3,4};
    List* l=create(ar,4);
    reverse(l);
    show_list(l);
}
链表1——实战

接下来我创建一个没有空表头的链表

#include <iostream>
using namespace std;

struct Lnode
{
  double data;
  Lnode* next;
};


void ShowList(Lnode* head)
{
  if(head){
    cout <<head->data <<endl;
    if(head->next)
      ShowList(head->next);         //递归调用
  }
}
链表2-1——创建
void AddToEnd(Lnode* pnew, Lnode*& head)
{
  if(!head)
  {
    head=pnew;
    pnew->next=NULL;
  }
  else
    AddToEnd(pnew, head->next);     //递归调用
}
链表2-2-1——addtoend的递归实现
void AddToEnd(Lnode* pnew,Lnode*& head)//此处一定不能省略&,*&代表引用指针 
{
    if(!head){
        head=pnew;
        cout<<head<<endl;
    }
    else{
        Lnode *p;
        for(p=head;p->next;p=p->next);
        p->next=pnew;
    }
    cout<<head<<"\t"<<endl;
    pnew->next=NULL;

}
链表2-2-2——addtoend的非递归调用
Lnode* GetNode()
{
    Lnode* item = new Lnode;
    item->next=NULL;
    item->data=0.0;
    return item;
}
链表2-3——创建节点
int main()
{
  Lnode* head=NULL;
  Lnode* temp;
  double d;
  cout <<"Data? ";
  cin >>d;
  while(d>0&&(temp=GetNode()))
  {      
    temp->data=d;
    AddToEnd(temp, head);
    cout <<"Data? ";
      cout<<head<<"\t"<<endl;
    cin >>d;
  }
  cout<<head<<"\t"<<endl;
  ShowList(head);
}
链表2——实战

我们可以看到2-2中我们用了指针引用

因为没有空表头的情况下, 我们的可能会更改这个链表的指针(从NULL改为pnew)

链表1-1中的创建函数也可以这么写:

void create(int *data,int len,List*&l)
{
    l = new List;
    *l={0,NULL};
    append(l,data,len);
}
链表1-1-1——创建,引用

那么主函数的更改如下:

int main(){
    int ar[4]={1,2,3,4};
    List* l;
    create(ar,4,l);
    reverse(l);
    show_list(l);
}
链表1——实战2.0

猜你喜欢

转载自www.cnblogs.com/applerun/p/12654429.html