今天整理了一下创建链表的代码,我主要使用了尾插法,因为头插法插入的数据是倒叙的,所以我不常用,且原理和尾插法一样,所以这里只给出尾插法。
尾插法需要定义一个尾指针ptail,始终指向链表的尾端p,每次新插入结点时,都使用这个尾指针指向新插入的结点,即ptail->next=pnew,然后将尾指针更新为pnew,即ptail=p。如此循环。先给出一个没有头指针的创建方法(头指针即第一个结点),并打印:
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
Node * CreateNode(int n) //尾插法
{
Node *head = NULL, *pnew = NULL, *ptail = NULL; //创建表头、表尾和新插入结点并初始化
int num, i=1;
while(i <= n)
{
pnew = new Node;
cout << "输入第" << i << "个结点:" << endl;
cin>>num;
pnew->data = num;
pnew->next = NULL;
if(head == NULL)
head = pnew;
else
{
ptail->next = pnew;
}
ptail = pnew;
i++;
}
pnew = NULL;
delete pnew;
return head;
}
void PrintNode(Node *head, int n)
{
Node *p;
p = head;
for(int i = 0; i < n; i++)
{
cout << p->data << " ";
p = p->next;
}
cout<<endl;
}
int main()
{
int n; //结点个数
cout << "输入结点个数:" << endl;
cin>>n;
Node *head;
head = CreateNode(n);
PrintNode(head,n);
return 0;
}
输出:
有时候,我们需要创建含有头结点的链表,主要有如下两点好处(引自点击打开链接):
a、由于开始结点的位置被存放在头结点的指针域中,所以在链表的第一个位置上的操作就和在表的其它位置上的操作一致,无需进行特殊处理;
b、无论链表是否为空,其头指针是指向头结点在的,因此空表和非空表的处理也就统一了。
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
Node * CreateNode(int n) //尾插法
{
Node *head, *pnew = NULL, *ptail; //创建表头、表尾和新插入结点并初始化
head = new Node;
head->data = 0;
head->next = NULL;
ptail = head;
int num, i=1;
while(i <= n)
{
pnew = new Node;
cout << "输入第" << i << "个结点:" << endl;
cin>>num;
pnew->data = num;
pnew->next = NULL;
ptail->next = pnew;
ptail = pnew;
i++;
}
pnew = NULL;
delete pnew;
return head;
}
void PrintNode(Node *head, int n)
{
Node *p;
p = head-> next; //有头结点时这里要将p初始化为第一个节点!
for(int i = 0; i < n; i++)
{
cout << p->data << " ";
p = p->next;
}
cout<<endl;
}
int main()
{
int n; //结点个数
Node *head;
cout << "输入结点个数:" << endl;
cin>>n;
head = CreateNode(n);
PrintNode(head, n);
return 0;
}
从代码中发现有个需要注意的地方,即在打印链表时,包含头结点的方法需要将结点p初始化为 p = head-> next,否则会将头结点里存储的非链表中的有效值(我的代码中是0)打印出来。
之后会陆续更新链表的各种操作,有问题的话,欢迎大家指正!