您的位置:首页 > 理论基础 > 数据结构算法

数据结构之线性表(链式储存)

2018-02-19 18:20 204 查看

2线性表的链式储存:

由线性表的顺序储存可以得知,顺序储存结构有其自身的优点<查找特别快捷>,当然同时存在其自身的缺点<对于插入和删除时,需要移动大量的指针>,所以衍生了链式结构来弥补其措施。链式储存是采用动态储存的方法,其储存的单元不受限制,既可以是连续的储存的地址,也可以是非连续的储存地址,这样对于经常需要删除、插入的数据来说最为合适了,当然,这样对于每个数据的节点都需要一个指针域来指向下一个节点,来实现数据逻辑上的连续。

2.1单链表

链表的头结点用于储存链表的位置,而其最后一位数据的指针域为NULL,这样的链表称为单链表。其储存结构的描述如下:typdef struct Node
{ ElemTyple data;
 structNode * next;
}Node,*LinkList;
Ps;LinkList与Node *同为结构指针类型,通常前者用于表示说明指针变量,强调它是某个单链表的头指针变量,而后者则是表示单链表中结点的指针。

2.1.1单链表的基本运算:

1.初始化:IintList(LinkList  *L)
{
 *L=(LinkList)malloc(sizeof(Node));
 (*L)->next=NULL;
}
建立一个空的单链表,2.建立单链表:链表的初始化分为两种:头插法和尾插法。头插法:每次插入的结点都放在头结点的后面,因而形成的链表和插入的顺序相反。其代码如下:
void CreateFromHead(LinkList L) {  Node *s;  char c;  int flag+1;  while(fiag)  {   c=getchar();   If(c!=’$’){  S=(Node*)malloc(sizeof(Node));  s->data=c;  s->next=L->next;  L->next=s;}else flag=0;}}          //先申请一个新节点,将输入的值赋值给s的数据域,再将L原本指针域所指向的赋值给s的next。尾插法:void createFromTail(LinkList L)
{
  Node *r,*s;
  Int flag=1;
  r=L;
  while(flag)
  {
     c=getchar();
     if(c!=’$’)
     {
      s=(Node *)malloc(size
effc
of(Node));
      s->data=c;
      r->next=s;
      r=s;
     }
else
  {falg=0;
  r->next=NULL;
}
}
}
用尾插法知先申请一个指针空间赋值给s再将s赋值于尾指针r的next,当输入完成的时候,再将s的next赋值为NULL。查找:与顺序结构的一样,链表的查找也分为按序号查找和按值查找。按序号查找:与顺序表不同,链表不能按照一堆数组的序号来查找,只能通过指针借助next域来实现查找,实现代码如下:Node * Get(LinkList L,int i)
{
  Intj;
 Node *p;
  If(i<0)return NOLL;
  p=L;j=0;
 while((p->next!=NULl)&&(j<i))
  {p=p->next;
   j++;
  }
If(j==i) return;
 Elsereturn NULL;
}
由算法可知:先通过一个while循环来扫描所查找i的逻辑位置,直到查找到后采用一个判断语句判断是否查到该元素。按值查找:其算法与顺序表的相同,代码如下:Node *Locate(LinkList L,ElemTyple key)
{
  Node *p;
  P=L->next:
  while(p!=NULL)                //当表没有查找完
  if(p->data!=key)
p=p->next;
  else break:                  //找到时跳出循环
 returnp;
 }
求链表的长度; 链表不像顺序表,可以直观的看出其长度,需要指针遍历计数。具体代码自己实现。单链表的插入操作: 其主要算法思想分为3步: 查找->申请->插入挂链集体操作如下:
void InsList(LinkList L, int i, ElenTyple e)
{
Node *pre,*s; //pre为查找指针,需要不断移位,而s 为插入指针用于存插入的值。
Int k;
If (i<0) return ERROR;
pre=L;k=0; //从又开始,查找第i-1个节点。
while(pre!=NULL&&k<i-1)
{
Pre=pre->next;
K++;
}
if(!pre)
{ printf(“插入位置不合理”);
ReturnERRPR;
}
s=(Node *)malloc(sizeof(Node));
s->data=e;
s->next=pre->next;
pre->next=s;
return OK;
}

删除链表:算法主要分为两步:查找->删除代码大致和插入相同,只将后续的插入操作变成删除,并释放节点即可。合并列表:将两个有序的链表LA和LB合并为一个有序的链表LC。LinkList MergeLinkList(LinkList LA,LinkLIstLB){   Node *pa,*pb;               //建立两个指针分别指向LA和LB用于循环遍历。   LinkList LC;                  //r始终指向LC的表尾。   pa = LA->next;   pb =LB->next;   LC=LA;   LC->next=NULL;r=LC;While(pa!=NULL&&pb!=NULL){ If(pa->data<=pb->data) {r->next=pa;r=pa;pa=pa->next;}     //尾插法建立LCElse  {r->next=pb;r=pb;pb=pb->next;}}If(pa)r->next=pa;elser->next=pb;free(LA); free(LB);return(LC);}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: