天天看點

資料結構之線性表一、線性表

一、線性表

雙連結清單删除元素

删除元素和 增加元素的大忌就是導緻引用連斷鍊
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;
}

           

繼續閱讀