天天看點

鍊式存儲(單連結清單)實作線性表的查找,插入,删除,求并集以及整表删除

#include <stdio.h>
#include <stdlib.h>
#define ERROR 0
#define OVERFLOW -1
#define OK 1
typedef int ElemType;
typedef int Status;

typedef struct Node{
	ElemType data;
	struct Node* next;
}LNode,*LinkList;

//頭插法建立單連結清單
Status CreateListHead_L(LinkList *List,int n){
    (*List)=(LinkList)malloc(sizeof(LNode));
    if(!(*List)){
        return OVERFLOW;
    }
    (*List)->next=NULL;
    LinkList p;
    for(int i=0;i<n;i++){
        p=(LinkList)malloc(sizeof(LNode));
        p->data=i;
        p->next=(*List)->next;
        (*List)->next=p;
    }
    return OK;
}

//尾插法建立單連結清單
Status CreateListTail_L(LinkList *List,int n){
    (*List)=(LinkList)malloc(sizeof(LNode));
    if(!(*List)){
        exit(OVERFLOW);
    }
    (*List)->next=NULL;
    LinkList p,tail;
    tail=(*List);
    for(int i=0;i<n;i++){
        p=(LinkList)malloc(sizeof(LNode));
        p->data=i;
        p->next=tail->next;
        tail->next=p;
        tail=p;
    }
    return OK;
}

//獲得連結清單第i個元素
//算法思路:
/*
    1. 聲明一個節點p指向第一個節點,用于周遊連結清單
    2. 定義一個計時器j從1開始,j<i時,周遊連結清單,j++
    3. 查找成功:p!=NULL&&j=i
    4. 查找失敗:p==NULL||j>i
 */
Status GetElem(LinkList List,int i,ElemType *e){
    int j=1;    //j為計數器
    LinkList p;
    p=List->next;   //p指向連結清單第1個節點
    while (p&&j<i) {
        p=p->next;
        j++;
    }
    if(!p||j>i){
        return ERROR;
    }
    *e=p->data;
    return OK;
}

//向單連結清單中插入一個元素
Status InsertList_L(LinkList *List,ElemType e,int i){
    LinkList p;
    p=*List;
    int j=0;
    while (p&&j<i-1) {
        p=p->next;
        j++;
    }
    if(!p||j>i-1){
        printf("插入位置有錯\n");
        return ERROR;
        //插入位置有錯
    }
    LinkList s;
    s=(LinkList)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    return OK;
}

//删除元素
Status DeleteList_L(LinkList *List,int i,ElemType *e){
    LinkList p;
    p=(*List);
    int j=0;
    while (p->next&&j<i-1) {
        p=p->next;
        j++;
    }
    if(!(p->next)||j>i-1){
        printf("出錯了");
        return ERROR;
    }
    LinkList q;
    q=p->next;
    *e=q->data;
    p->next=q->next;
    free(q);
    return OK;
}

LinkList Search(LinkList List,ElemType e){
    LinkList p;
    p=List->next;
    while (p) {
        if(p->data==e){
            break;
        }
        p=p->next;
    }
    return p;
}

//求并集
void MergeList(LinkList La,LinkList Lb,LinkList *Lc){
    LinkList pa=La->next;
    LinkList pb=Lb->next;
    LinkList pc;
    (*Lc)=pc=La;
    while (pa&&pb) {
        if(pa->data<=pb->data){
            pc->next=pa;
            pc=pa;
            pa=pa->next;
        }else{
            pc->next=pb;
            pc=pb;
            pb=pb->next;
        }
    }
    pc->next=pa?pa:pb;
    free(Lb);
}

//整表删除
Status ClearList(LinkList *List){
	LinkList p,q;
	p=(*List)->next;
	while(p){
		q=p->next;
		free(p);
		p=q;
	}
	(*List)->next=NULL;
	return OK;
}

//列印連結清單元素
void PrintList(LinkList List){
    LinkList p;
    p=List->next;
    while (p) {
        printf("%d\n",p->data);
        p=p->next;
    }
}

int main() {
    LinkList List;
    CreateListHead_L(&List, 8);
    int temp;
    GetElem(List, 3, &temp);
    printf("%d\n",temp);
    InsertList_L(&List, 10, 9);
    PrintList(List);
    int e;
    DeleteList_L(&List, 9, &e);
    PrintList(List);
    LinkList La,Lb,Lc;
    CreateListTail_L(&La, 8);
    CreateListTail_L(&Lb, 8);
    MergeList(La, Lb, &Lc);
    PrintList(Lc);
    return 0;
}
           

這裡的求并集要求原先兩個集合裡的元素按從小到大排好

繼續閱讀