数据结构之线性表

一、线性表

双链表删除元素

删除元素和 增加元素的大忌就是导致引用连断链

s->next = p->next;
s->prior = p;
p->next = s;
s->next->prior = s;

双链表删除元素

s->prior->next = s->next;
s->next->prior = s-prior;
free(s);//记住删除元素后要释放这个元素

静态链表节点类型定义

静态链表可以理解为数组

typedef struct{
    int data;
    int next;
}SLNode;

顺序表的插入删除

//建表
int sqList[maxSize]  = {1,2,3,...,n}
int length = n;

/* sqList是待插入的数组,length是数组大小,因为需要改变大小,所以这里是引用类型
 * p表示往哪里插,也就是位置,e表示元素	
 */
int insertElem(int sqList[],int &length,int p,int e){
    if(p<0||p>length){
        return 0;//插入位置不合理
    }
    //元素分别后移
    for(int i = length-1;i>p;--i){
        sqList[i+1] = sqList[i]
    }
    //插入数据,长度+1
    sqList[p] = e;
    ++length;
    return 1;//返回1表示插入成功
}
//与插入不同的参数是e,一般要拿到删除元素的值,所以需要引用值  
int deleteElem(int sqList,int &length,int p;int &e){
    if(p<0||p>length-1){
        return 0;
    }
    e = sqList[p];
    for(int i=p;i<length-1;++i){
        sqList[i] = sqList[i+1];
    }
    --length;
    return 1;
}
//尾插法
void createLinkListR(LNode *&head){
      head = (LNode *)malloc(sizeof(LNonde));
      head->next = NULL;
      LNode *p = NULL,*r = head;
      int n;
      std::cin>>n;//scanf("%d",&a)
      for(int i=0;i<n;++i){
          std::cin>>p->data;//scanf("%d",&(p->data));
          p->next = r->next;
          r->next = p;
          r = p;
      }
    
}

//头插法
void createLinkListH(LNode *&head){
    head = (LNode *)malloc(sizeof(LNode));
    head->next = NULL;
    LNode *p = NULL;
    int n;
    std::cin>>n;//scanf("%d",&n);
    for(int i=0;i<n;i++){
        p = (LNode *)malloc(sizeof(LNode));
        p->next = NULL;
        std::cin>>p->data;//scanf("%d",&(p->data));
        p->next = head->next;
        head->next = p;
    }
}
  • 真题解答

键盘输入n个英文字母,输入格式为 n、C1、C2、…、 Cn,其中n表示字母的个数。请编程以这些输入数据建立一个单链表,并要求将字母不重复的存入链表。

   void createLinkNoSameElem(LNode *&head){
       head  = (LNode *)malloc(sizeof(LNode));
       head->next = NULL;
       LNode *p;
       int n;
       char ch;
       std::cin>>n;
       for(int i=0;i<n;i++){
           std::cin>>ch;
           p = head->next;
           while(p!=NULL){
               //如果找到一个值,这个值相等,就要跳出循环
               if(p->data==ch)
                   break;
               //不相等就继续遍历
               p = p->next;
           }
           //遍历 如果找到相同的p!=NULL,如果没找到相同的,那么p就不为空
           if(p==NULL){
  			p = (LNode *)malloc(sizeof(LNode));
            p->data = ch;
            p->next = head->next;//这里说明是头插法
            head->next = p;
           }
           
       }
   }

逆置问题

  • 顺序表的逆置

    for(int i = left,j = right;i<j;++i,--j){
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    
  • 链表的逆置

    while(p->next != q){
    	t = p->next;
    	p->next = t->next;
    	t->next = q->next;
    	q->next = t;    
    }
    
    
  • 真题解答

    1. 将一段长度为n的数组的前端k(k<n)个元素逆序后移动到数组后段,要求原数组中的元素不丢失;
    void reverse(int a[], int left,int right,int k){
        int temp;
        //当k大于表长的一半,就需要设置i<left-k
        for(int i = left,j=right;i<left-k&&i<j;++i,--j){
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }
    
    1. 将一段长度为n的数组的前端k(k<n)个元素保持原序移动到数组后段,要求原数组中的元素不丢失;
    void moveToEnd(int a[],int n,int k){
        reverse(a,0,k-1,k);
        reverse(a,0,n-1,k);
    }
    
    

    3),将数组中的元素(X0, X1…Xn-1),经过移动后变为(Xp,Xp+1,X)

    void moveP(int a[],int n,int p){
      reverse(a,0,p-1,p);
      reverse(a,p,p-1,n-p);
      reverse(a,0,n-1,n)
    }
    
    

取最值问题

  • 顺序表取最值
int max = a[0];
int maxIdx = 0;
for(int i=0;i<n;++i){
    if(max<a[i]){
        max = a[i];
        maxIdex = i;
    }
}
//当然取最小值同理,这里就不写了 

  • 链表取最值

    LNode *p,*q;
    int min = head->next->data;
    q = p = head->next;
    while(p!=NULL){
        if(min>p->data){
            min = p->data;
            q  = p;
        }
        p = p->next;
    }
    
    //双链表的最值问题
    void maxFirst(DLNode *head){
        DLNode *p = head->rlink,*q =p;
        int max = p->data;
        while(p!=NULL){
            if(max<p->data){
                max = p->data;
                q = p;
            }
            p = p->rlink;
        }
        //删除找到的节点
        DLNode *l = q->llink;//左节点
        *r = q->rlink;//右节点
        l->rlink = r;//左节点指向右节点
        if(r!=NULL)//双链表,当最后一个节点的值为null的时候,就不需要将右边指向左边了
            r->llink =l;
        //插入操作,也就是插入到头结点之后
        q->llink = head;
        q->rlink = head->next;
        head->rlink = q;
        q->rlink->llink = q;
        
    }
    
    

归并操作(顺序表)

void mergearray(int a [],int m,int b[],int n,int c[]){
    int i = 0,j = 0;
    int k = 0;
    while(i<m&&j<n){
        if(a[i]<b[j]){
              c[k++] = a[i++];//c[k] = a[i];k++;i++;
        }else{
              c[k++] = b[j++];//c[k] = b[j];k++;j++;
        }
    }
    while(i<m){
        c[k++] = a[i++];
    }
    while(j<n){
        c[k++] = b[j++];
    }
}

归并操作(链表)

void merge(LNode *A, LNode *B, LNode *&C){
    LNode *p = A->next;
    LNode *q = B->next;
    LNode *r;
    C = A ;
    C->next = NULL;
    free(B);
    r = C;
    while(p != NULL && q !=NULL){
        if(p->data <= q->data){
            r->next = p;
            r = r->next;
        }else{
            r->next = q;
            r = r->next;
        }
    }
    if(p!=NULL) r->next = p;
    if(q!=NULL) r->next = q;
}
//如果是想逆序,倒着插入 就可以了

//归并操作实现一条逆序序列的代码
void mergeR(LNode *A, LNode *B,LNode *&C){
    LNode *p = A->next;
    LNode *q = B->next;
    LNode *s;
    C = A;
    free(B);
    while(p!=NULL&&q!=NULL){
        if(p->data <= q->data){
            s = p;
            p = p->next;
            s ->next = C->next;
            C->next = s;
        }else{//p->data >= q->data
            s = q;
            q = q->next;
            s->next = C->next;
            C->next = s;
        }
    }
    while(p!=NULL){
        s = q;
        q = q->next;
        s->next = C->next;
        C->next = s;
    }
    while(q!=NULL){
        s = p;
        p = p->next;
        s->next = C->next;
        C->next = s;
    }
    
}

划分

这里需要提一点就是,在线性表的划分当中经常会出现枢轴这类的问题,也就是谁在枢轴的坐标都是小于枢轴的,枢轴的右边都是大于数轴的,但是具体得看题目怎么说了

void partition(int arr[], int n){
    int temp;
    int i = 0;
    int j = n-1;
    while(i<j){
        while(i<j&&arr[j]>==temp) --j;
        if(i<j){
            arr[i] = arr[j];
        	++i; 
        }
        while(i<j&&arr[i]<temp) --i;
        if(i<j){
            arr[j] = arr[i];
            --j;
        }
      }
    arr[i] = temp;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值