赞
踩
学习了这么久的数据结构,终于把链表吃透啦,下面是我整理的四种创建单链表的的方法
以及一些非常容易犯的错误,让我们一起来看看吧~
目录
单链表一共有两种,一个是带头结点的单链表,还有一个是不带头结点的单链表
总的来说,带头结点的单链表相对于不带头结点的单链表来说,更加方便对链表基本操作的实现
(带头结点的单链表操作起来更方便,所以很多时候我们都是用带头结点的单链表)
单链表的初始化,我们分不带头结点和带头结点两种情况
不带头结点的单链表,说明头指针指向了第一个有效的结点
- PNode Init_1_Node(){
- PNode head;
- head=NULL; //因为不带头结点,所以我们只要让头结点为空
- return head;
- }
带头结点的单链表,头指针要指向头结点(头结点不存放数值,可将头结点理解为无效结点)
- PNode Init_2_Node(){
- PNode head;
- head=(PNode)malloc(sizeof(Node)); //申请一个头结点
- head->next=NULL; //头结点指针域指向空
- return head;
- }
单链表的创建,我们分不带头结点和带头结点来介绍,具体再分为头插法和尾插法两种方法
头插法嘛,顾名思义,每次都在链表的前面插入,这样最先输入的结点最后输出,最后输入的结点最先输出。例如你输入的是1,2,3。那么打印出来的将是3,2,1。
- void Creat_1_Node(PNode *head){ //不带头结点我们用头指针的地址来保存单链表
- int i,n;
- printf("(头插法)请输入不带头结点的链表结点个数:");
- scanf("%d",&n); //输入不带头结点单链表的结点个数
- for(i=1;i<=n;i++){
- PNode Pnew=(PNode)malloc(sizeof(Node)); //创建一个新的结点
- Pnew->next=NULL; //指针域指向空
- printf("第%d个结点的元素为:",n+1-i);
- scanf("%d",&Pnew->data);
- if(*head==NULL){ //判断头指针是否指向空
- *head=Pnew; //如果是则让头指针指向第一个有效结点
- }else{ //当头指针指向非空时
- Pnew->next=*head; //将新的结点插入到头指针所指结点的前面
- *head=Pnew; //头指针指向新插入的结点
- }
- } //例如你输入 1 2 3
- } //实际上链表是 3 2 1 这是因为你是在前面插入了新的结点
尾插法呢就比较好理解了,每次都在链表的最后插入一个新的结点就好了,这个是按顺序的,输入什么最后就输出什么。例如输入1,2,3。输出将是1,2,3。
- void Creat_2_Node(PNode *head){
- PNode Last; //尾插法的话,我们要有一个时刻指向尾结点的指针
- int i,n;
- printf("(尾插法)请输入不带头节点的链表结点个数:");
- scanf("%d",&n);
- for(i=1;i<=n;i++){
- PNode Pnew=(PNode)malloc(sizeof(Node));
- Pnew->next=NULL;
- printf("第%d个结点的元素为:",i);
- scanf("%d",&Pnew->data);
- if(*head==NULL){ //判断头指针是否指向空,这是必要的
- *head=Pnew; //头指针指向第一个有效结点
- Last=Pnew; //因为此时只有一个结点,所以Last指向这个结点就好
- }else{ //当头指针指向不是空的时候
- Last->next=Pnew; //尾结点指针域指向新插入的结点
- Last=Pnew; //将新结点赋给尾结点(插入的结点变成新的尾结点)
- }
- }
- }
带头结点的单链表使用头插法创建时,一定要注意 Pnew->next=p->next 和 p->next=Pnew 两行代码不能颠倒!Pnew->next=p->next 的意思是将p后面的所有结点都接到了要插入的新结点的后面,p->next=Pnew 的意思是将新结点接到p(头结点)的后面。如果将两行代码颠倒了,那么头结点后面的所有结点将丢失,这样无论你创建多大的链表,其实最后都只有两个结点(一个是头结点,没什么用,还有一个就是你输入的最后一个数据),其他的结点都丢失了
- void Creat_3_Node(PNode head){
- PNode p=head; //将head赋给p,p是头结点,不保存数据,为无效结点
- int i,n;
- printf("(头插法)请输入带头节点的链表结点个数:");
- scanf("%d",&n);
- for(i=1;i<=n;i++){
- PNode Pnew=(PNode)malloc(sizeof(Node)); //创建新的结点
- Pnew->next=NULL; //指针域指向空
- printf("第%d个结点的元素为:",n+1-i);
- scanf("%d",&Pnew->data);
- Pnew->next=p->next; //这里注意一定要先把p后面的所有结点接到Pnew后面
- p->next=Pnew; //再执行把Pnew连接到p后面
- }
- }
尾插法就不需要担心数据丢失的问题了,因为是在尾结点后面插入(尾结点后面没有其他结点)
- void Creat_4_Node(PNode head){
- PNode p=head;
- PNode Last; //需要一个时刻指向尾结点的指针
- Last=p;
- int i,n;
- printf("(尾插法)请输入带头节点的链表结点个数:");
- scanf("%d",&n);
- for(i=1;i<=n;i++){
- PNode Pnew=(PNode)malloc(sizeof(Node));
- Pnew->next=NULL;
- printf("第%d个结点的元素为:",i);
- scanf("%d",&Pnew->data);
- Last->next=Pnew; //尾结点指针域指向要插入的结点
- Last=Pnew; //新插入的结点成为新的尾结点
- }
- }
这里分为不带头结点和带头结点两种情况,需要分别打印
- void Print_1_Node(PNode head){
- PNode p=head; //不带头结点,p就是第一个有效元素
- printf("新的链表为:");
- while(p!=NULL){ //采用循环挨个打印
- printf("%d ",p->data);
- p=p->next;
- }
- printf("\n");
- }
- void Print_2_Node(PNode head){
- PNode p=head->next; //带头结点,p应该为第一个有效结点
- printf("新的链表为:");
- while(p!=NULL){
- printf("%d ",p->data); //打印
- p=p->next;
- }
- printf("\n");
- }
- #include<stdio.h>
- #include<malloc.h>
- typedef struct Node{
- int data;
- struct Node * next;
- }Node,*PNode;
- PNode Init_1_Node(){
- PNode head;
- head=NULL;
- return head;
- }
- PNode Init_2_Node(){
- PNode head;
- head=(PNode)malloc(sizeof(Node));
- head->next=NULL;
- return head;
- }
- void Creat_1_Node(PNode *head){
- int i,n;
- printf("(头插法)请输入不带头节点的链表结点个数:");
- scanf("%d",&n);
- for(i=1;i<=n;i++){
- PNode Pnew=(PNode)malloc(sizeof(Node));
- Pnew->next=NULL;
- printf("第%d个结点的元素为:",n+1-i);
- scanf("%d",&Pnew->data);
- if(*head==NULL){
- *head=Pnew;
- }else{
- Pnew->next=*head;
- *head=Pnew;
- }
- }
- }
- void Creat_2_Node(PNode *head){
- PNode Last;
- int i,n;
- printf("(尾插法)请输入不带头节点的链表结点个数:");
- scanf("%d",&n);
- for(i=1;i<=n;i++){
- PNode Pnew=(PNode)malloc(sizeof(Node));
- Pnew->next=NULL;
- printf("第%d个结点的元素为:",i);
- scanf("%d",&Pnew->data);
- if(*head==NULL){
- *head=Pnew;
- Last=Pnew;
- }else{
- Last->next=Pnew;
- Last=Pnew;
- }
- }
- }
- void Creat_3_Node(PNode head){
- PNode p=head;
- int i,n;
- printf("(头插法)请输入带头节点的链表结点个数:");
- scanf("%d",&n);
- for(i=1;i<=n;i++){
- PNode Pnew=(PNode)malloc(sizeof(Node));
- Pnew->next=NULL;
- printf("第%d个结点的元素为:",n+1-i);
- scanf("%d",&Pnew->data);
- Pnew->next=p->next;
- p->next=Pnew;
- }
- }
- void Creat_4_Node(PNode head){
- PNode p=head;
- PNode Last;
- Last=p;
- int i,n;
- printf("(尾插法)请输入带头节点的链表结点个数:");
- scanf("%d",&n);
- for(i=1;i<=n;i++){
- PNode Pnew=(PNode)malloc(sizeof(Node));
- Pnew->next=NULL;
- printf("第%d个结点的元素为:",i);
- scanf("%d",&Pnew->data);
- Last->next=Pnew;
- Last=Pnew;
- }
- }
- void Print_1_Node(PNode head){
- PNode p=head;
- printf("新的链表为:");
- while(p!=NULL){
- printf("%d ",p->data);
- p=p->next;
- }
- printf("\n");
- }
- void Print_2_Node(PNode head){
- PNode p=head->next;
- printf("新的链表为:");
- while(p!=NULL){
- printf("%d ",p->data);
- p=p->next;
- }
- printf("\n");
- }
- int main(){
- PNode H1,H2,H3,H4;
- H1=Init_1_Node();
- Creat_1_Node(&H1);
- Print_1_Node(H1);
- H2=Init_1_Node();
- Creat_2_Node(&H2);
- Print_1_Node(H2);
- H3=Init_2_Node();
- Creat_3_Node(H3);
- Print_2_Node(H3);
- H4=Init_2_Node();
- Creat_4_Node(H4);
- Print_2_Node(H4);
- return 0;
- }
综上所述,我们一共有四种创建单链表的方法,其实头插法基本不用,我们用的最多的是尾插法创建带头结点的单链表。
在创建单链表的时候,要注意几个问题:
1.一定要初始化单链表,不管是带头结点还是不带头结点的单链表,不然会出现输入一半程序终结的情况(暂时不知道是什么情况)
2.创建不带头结点的单链表,要用到指针的指针,否则没法保存地址。
3.创建不带头结点的单链表,一定要先判断头指针是否指向空
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。