Real-Ying

2_线性表之链式存储

存储结构

通过“链”建立数据元素间的逻辑关系,使物理位置上不相邻的元素逻辑上也能相邻,操作不需要移动元素,只需修改指针。

1.单链

                                    

 表示方法

typedef struct LNode{
        ElemType data;   //数据域
        struct LNode *next;   //指针域
} LNode,*LinkList

 

基本操作1:建立

头插法

实现步骤:从创建头结点开始,生成新结点,将读取到的数据放到新结点的数据域中,然后将新结点插入到头结点之后,读取顺序与生成顺序相反

       

{ s = (LNode*)malloc(sizeof(LNode));
   s—>data=x;
   s—>next=L—>next;     //将L—>next(初值Null)所指赋给s—>next
   L—>next = s; 
   scanf("%d",&x); }

*指针所代表的是指向

尾插法

生成顺序与读取顺序相同

      

s—>data=x;
r—>next=s;      //r所指向
r = s;

 

基本操作2:查找

按位

LNode *GetElem(LinkList L,int i){
         int j=1;     //计数,初始为1
         LNode *p=L—>Next;
         if(i==0)     //若i等于0,返回头结点
              return L;
         if(i<1)       //若i无效,返回Null
              return Null;
         while(p&&j<i){
                p=p—>next;
                j++; }
         return p; }

*单链表长度不包含头结点

按值

LNode *LocateElem(LinkList L,ElemType e){
         LNode *p=L—>Next;
         while(p!=Null&&p—>data!=e){
                p=p—>Next;
         return p; }

*操作时先检验操作合法性,再执行操作

 

基本操作3:插入

       

1.p=GetElem(L,i-1);   //查找插入位置前驱结点
2.s—>next=p—>next;    //步骤1
3.p—>next=s;          //步骤2

 

基本操作4:删除

按位  

实现步骤:将单链表第i个结点删除,先检查合法性,然后找出第i-1它的前驱结点,便可删除i结点,复杂度O(n)

         

p=GetElem(L,i-1);         //查找删除位置的前驱结点
q=p—>next;                 //令q指向被删除结点
p—>next=q—>next;    //断开
free(q);

删给定结点*p

实现步骤:将其后继结点赋予给定结点,再删除后继,复杂度O(1)

q=p—>next;               
p—>next=q—>next—>data;     //和后继结点交换数据域 
p—>next=q—>next;
free(q);

 

 

2.双链表

双链表节点中有两个指针prior和next,查找与单链表相同,插入和删除有较大不同

        

表示方法:

typedef struct DNode{
             ElemType data;                        //数据域
             struct DNode *prior,*next;      //前驱、后驱指针
}DNode,*DLinkList

 

基本操作1:插入

      

1.s—>next=p—>next;     //建立后继与s联系
2.p—>next—>prior=s;    //P的下个结点的前驱指向
3.s—>prior=p;                //建立与前驱结点联系
4.p—>next=s;                //P的上个结点的后继指向

*方法不唯一,但1.2.必须在4.前面

 

基本操作2:删除

       

p—>next=q—>next;    //步骤1.
q—>next—>prior=p;    //步骤2.
free(q);

 

3.循环链表

只需在终端结点和头结点建立联系即可,判断P走到表尾的条件是P—>next=head

 

 

算法1:递归删除无头结点单链表所有某值

void Del_x_3(LinkList,&L,ElemType x){
       LNode *p;                        //p指向待删除结点
       if(L==NULL)                      //递归终止条件
            return;                         
       if(L—>data==x){                  //若L所指结点值为x,删除*L指向
            p=L;                           
            L—>next;                    //并让L指向下一结点
            free(p);
            Del_x_3(L,x); }             //跳回函数本体
       else 
             Del_x_3(L—>data,x) }

 

算法2:删除带头结点单链表所有某值

void Del_x_4(LinkList &L,ElemType x){
       LNode *p=L—>next,*pre=L,*q;   //置*P和*pre初始值
       while(p!=NULL){
              if(p—>data==x){
                   q=p;         //q指向该结点
                   p=p—>next;   //通过操作删除该结点
                   pre—>next=p;
                   free(q); }
              else{             //不等,pre和p同时后移
                   pre=p;
                   p=p—>next; }}}

 

算法3:从尾到头递归遍历带头结点单链表

用栈的思想递归实现,也可以逆置改变方向后从头到尾遍历

void Reverse_Print(LinkList L){
       if(L—>next!=NULL){
           Reverse_Print(L—>next); }     //递归
       print(L—>next); }             //整体输出函数

 

算法4:删除带头结点单链表最值

void Del_Min(LinkList &L){
       LNode *pre=L,*p=pre—>next;  //p为扫描指针,pre为p的前驱
       LNode *minpre=pre,*minp=p;   //边扫描边比较,将较小者存入minp和premin,将前驱考虑进来是为了便于删除一个结点
       while(p!=NULL) {
              if(p—>data<minp—>data){
                    minp=p;
                    minpre=pre; }
              p=p—>next;  //继续扫描下一个结点
              pre=p; }
              minpre—>next=minp—>next;   //删除最小值
              free(minp);
              return L; }

 

算法5:带头结点单链表就地逆置

LinkList Reverse_1(LinkList &L){
       LNode *p,*r;       //p是扫描指针,r暂存p后继
       p=L—>next;         //从头结点开始
       L—>next=NULL;      //先将头结点指针域置NULL
       while(p!=NULL){
              r=p—>next;  // 暂存p的后继防止断链
              p—>next=L—>next;    //以下循环头插法,这里是插入后继
              L—>next=p;          //插入前驱
              p=r; }              //扫描下一个
       return L; }

 

算法6:无序——>有序

使带头结点的单链表有序递增

void Sort(LinkList &L){
       LNode *p=L—>next,*pre;
       LNode *r=p—>next;      //r防止断链
       

 

posted on 2017-08-12 17:12  Real-Ying  阅读(324)  评论(0编辑  收藏  举报

导航