4链表

数组可以当顺序表使用,这个不难。

此处讲解下链表。。。。

 

复习下

1.是线性表的一种存储形式

2.每个表元素对应链表的一个结点(含值域和链域)

3.值域(value field)用来存储表元素值

4.链域(link field)用来存储相邻结点的地址

5.表尾结点的链域值为空(NULL,即常数0)

6.用首指针(如,变量head)指向第一个结点

7.链表就是表头指针和一串相继链接的结点的总称

结点和指针的类型定义:

typedef   int  element_type;    //值域类型

typedef  struct  linkednode     //结点类型

  {  element_type  data;     //值域

     struct  linkednode  *next;   //链域

  }  snode, *ptr; //结点类型名snode和指针类型名ptr

ptr  head,p,q;   // 定义指针类型变量

类型struct  linkednode *  与类型ptr等价

都是指向snode的指针类型

 

注意:每一个结点都是一个结构,结点中保存数值、下一结点的地址。头指针千万不可以修改,否则整个链表都将找不到。

 

构建链表的通用算法:

步骤1)构造“空链表”

步骤2)读入第一个元素值

步骤3)当读入的元素值不是“输入结束标记”时  

               循环执行步骤4~7

步骤4)申请一个新结点

步骤5)将读入的元素值存入新结点的值域

步骤6)将新结点“插在”链表中

步骤7)读入“下一个”元素值,转步骤3

步骤8)构造完毕,返回首指针

 

遍历链表的通用算法

步骤1)使访问指针p指向第一个结点

步骤2)当链表没遍历完时,循环执行步骤3和4

步骤3)访问p->

步骤4)p=p->next;         //p滑向下一个结点

步骤5)遍历完毕,返回

 

链表的创建

每一个结点都是动态分配存储:

 p=(ptr)malloc(sizeof(snode));

含义:

产生一个结点——动态分配的变量

将结点的地址值转换成ptr类型,赋给指针变量p

若分配失败,返回NULL

    NULL是值为0的指针常量,无效地址

 

p->表示p所指向的结点

p->就是结点名(变量名)

p->data:结点的值域    等价于  (*p).data

p->next:结点的链域    等价于  (*p).next

 

c++:

一般格式      new  结点类型名;

语句  :

                    p=new  snode;

 等价于       p=newsnode();

也等价于    p=(ptr)malloc(sizeof(snode));

 

链表的插入

 

 

 

链表的删除

 

 

 

链表的遍历

q=head

while(q->next)

{

         q=q->next;

}

 

q为遍历指针,只要q的指针域存在,说明q中有数值,否则q=q->next,q指向下一个结点。

 

 

 

链表的种类:

分类方式:

(1)按结点产生方式

静态

动态

(2)按结点链域个数

单向链表(singly linked lists)

双向链表(doubly linked lists)

(3)按是否带附加结点

纯链表——不带附加结点

加头链表——带附加表头结点

加尾链表——带附加表尾结点

加头尾链表——既带头又带尾

注意:附加结点往往用作监督元结点(存储特殊值)

(4)按是否循环

循环链表(circularly  linked lists)

非循环链表

 

 

 

链表算法

向前插入法构造简单链表的算法

ptr  creatlinkedA( ) 

   {  ptr  head, p;   element_type  x ;  

    head=NULL;   //将表头指针置空 

    scanf("%d", &x);  //读入第一个元素 

    while (x!=End_elm)  //当读的不是结束标记时循环 

       {  p=new snode;  //申请一个存储结点 

          p->data=x;  //置结点的值域 

           p->next=head;  //插在表头处 

          head=p;   //表头指针指向新结点 

         scanf("%d", &x); //读入下一个元素 

           }

    return(head);  //返回表头指针 

}

构建1 2 3 0 的链表

   head=NULL;

    scanf("%d", &x); 

    while (x!=End_elm)

       {  p=new snode; 

          p->data=x; 

          p->next=head; 

          head=p;  

        scanf("%d", &x);

          }

     return(head); 

向后插入法构造加头链表的算法

ptr  creatlinkedB( ) 

   {  ptr  head, last,p;   element_type  x ;  

    head=last=new snode;   //构造空链表 

    scanf("%d", &x);  

    while (x!=End_elm)  

       {  p=new snode;  

          p->data=x;  

           last->next=p;  //插在表尾 

           last=p;   //修改尾指针 

          scanf("%d", &x); //读入下一个元素 

           }

   last->next=NULL;  

return(head);   

}

 

单向简单链表的输出算法

 void  outlinkA(ptr  p)  //p是起始指针

  {

  printf("链表中的结点序列为:\n");

  while(p!=NULL)

   { printf("%5d", p->data);

     p=p->next;

     }

  printf("\n");

  }

 

单向简单链表的查找算法

ptr  searchA(ptr p,element_type x)

   { while(p!=NULL)

     { if(p->data==x)return  p;//找到x,返回p

       p=p->next; //暂时没找到,则继续向后找

        }

  return  NULL;     //查找不成功,返回空指针

     }

单向加尾链表的查找算法

ptr  searchB(ptr p,ptr last,element_type x)

  { last->data=x;     //设置监督元

    while(p->data!=x )p=p->next;//没找到,继续

    if(p!=last)return  p;  //查找成功

    return  NULL;         //查找不成功

     }

 

 

 

 

 

源代码:

// List.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

#include<stdio.h>

#include<stdlib.h>

#include<assert.h>

#define DATA 5

//节点数据类型

typedef struct Node

{

         int data;

         struct Node* next;

}Node;

//链表类型

typedef struct List

{

         Node* head;

}List;

//创建新节点

Node *CreaceNode(int data)

{

         Node *PtrNew=(Node*)malloc(sizeof(Node));

         PtrNew->data=data;

         PtrNew->next=NULL;

         return PtrNew;

};

//向头节点插入新节点

void PushHead(List *list,int data)

{

         Node* PtrNew1=CreaceNode(data);

         PtrNew1->next=list->head;

         list->head=PtrNew1;

};

//遍历链表

Node* Travel(List *list)

{

         Node *Ptr=list->head;

         if(Ptr!=NULL)

                   while(Ptr)

                   {

                            Ptr=Ptr->next;

                   };

         return Ptr;

};

//计算链表的长度

int Length(List *list)

{

         int iCount=0;

         Node *Ptr=list->head;

         if(Ptr!=NULL)

                   while(Ptr)

                   {

                            iCount++;

                            Ptr=Ptr->next;

                   };

         return iCount;

};

//输入链表的节点数据

void Show(List *list)

{

         printf("链表中的数据为:");

         int count=0;

         Node *findLength=list->head;

         if(findLength!=NULL)

                   while(findLength)

                   {

                            printf("%d    ",findLength->data);

                            findLength=findLength->next;

                            count++;

                   };

         printf("\n");

         printf("数据个数为:%d\n",count);

};

 

//查询链表中某一个数

Node* Find(List *list,int iPos)//传入要查找的位置

{

         Node* tempTtr=list->head;

         int iCurPos=0;//标记

         while(tempTtr->next!=NULL&&iCurPos<iPos)

         {

                   tempTtr=tempTtr->next;

                   iCurPos++;

         };

         if(tempTtr!=NULL&&iPos==iCurPos)

         {

                   //printf("你所查找位置的数据为:%d\n",*tempTtr);

                   return tempTtr;

         }

         else

                   {

                            printf("你要查找的位置超过了范围!\n");

                            return NULL ;

                   };

};

//删除某一个节点

int Delete(List *list,int ptr)

{

         if(ptr<1||ptr>Length(list))

                   {

                            printf("error\n");

                            return 0;

                   };

         Node *tempPtr;

         if(ptr>1)

         {

                   tempPtr=Find(list,ptr-1);//获取要删除的节点的上一节点

                   Node* nextPtr=tempPtr->next;//获取要删除节点的下一节点

                   tempPtr->next=nextPtr->next;//使删除节点的上一节点与下下节点相连接

                   delete nextPtr;//删除节点

         }

         else

                   {

                   tempPtr=list->head;

                   list->head=tempPtr->next;

                   delete tempPtr;

         };

         return 0;

};

//在某一节点前插入一个节点

int AddNode(List *list,int pos)

{

         Node* tempPtr=NULL;

         Node* temp=NULL;

         if(pos<=0||pos>Length(list)+1)

         {

                   printf("error");

                   return 0;

         }

         else

         {

                   if(pos>1)

                   {

                   tempPtr=Find(list,pos-1);//获取某一位置的前一节点

                   temp=tempPtr->next;//暂时存放新加节点的后一个节点

                   Node* newPtr=CreaceNode(5);//创建新节点

                   tempPtr->next=newPtr;//使上一节点与新节点相连接

                   newPtr->next=temp;//使新节点与后一节点相连接

                   }

                   else

                   {

                            Node* newPtr=CreaceNode(5);//创建新节点

                            temp=list->head->next;

                            newPtr->next=list->head;

                            list->head=temp;

                   };

 

         };

};

int main()

{

         List list;

         list.head=NULL;

         for(int i=1;i<=3;++i)

         {

                   PushHead(&list,i);

                   Show(&list);

         };

         Find(&list,3);

         Delete(&list,3);

         printf("\n");

         AddNode(&list,1);

         printf("\n");

         for(int i=1;i<=3;++i)

         {

                   PushHead(&list,i);

                   Show(&list);

         };

         getchar();

         return 0;

};

 

posted @ 2018-01-09 17:58  gd_沐辰  阅读(237)  评论(0编辑  收藏  举报