鏈表操作

鏈表操作


這篇文章是上課實驗的內容,包括順序表,鏈表,以及鏈表的各種應用。

順序表

順序表的存儲:

typedef struct Sqlist
{
    ElemType *slist;
    int length;
    int listsize;
}Sqlist;

順序表的各種操作:

/*(2)---線性表的初始化*/
int InitList_sq(Sqlist *L)
{
    L->slist=(ElemType *)malloc(INIT_SIZE * sizeof(ElemType));
    if(!L->slist) return ERROR;
    L->length = 0;
    L->listsize=INIT_SIZE;
    return OK;
}
/*(3)---創建具有n個元素的順序表*/
int CreateList_sq(Sqlist *L,int n)
{
    for(int i=0;i<n;i++)
    {
        L->slist[i]=i;
        L->length++;
        if(L->length>=L->listsize)
        {
            L->slist=(ElemType*) realloc(L->slist,(L->listsize+INCREM)*sizeof(ElemType));
            if(!L->slist)  return ERROR;
            L->listsize+=INCREM;
        }
    }
    return OK;
}/*(4)---輸出順序表中的元素*/
/*(5)---在順序表的第i個位置之前插入新元素e*/
int ListInsert_sq(Sqlist *L,int i,ElemType e)
{
    int k;
    if(i<1 || i>L->length+1) return ERROR;
    if(L->length>=L->listsize)
    {
        L->slist=(ElemType*) realloc(L->slist,(L->listsize+INCREM)*sizeof(ElemType));
            if(!L->slist)  return ERROR;
            L->listsize+=INCREM;
    }
for(k=L->length-1;k>=i-1;k--)
        L->slist[k+1]=L->slist[k];
L->slist[i-1]=e;
L->length++;
return OK;
}
/*(6)---在順序表中刪除第i個元素,e返回刪除的元素*/
int ListDelete_sq(Sqlist *L,int i,ElemType *e)
{
    int j;
    if(i<1 || i>L->length)
        return ERROR;
    *e = L->slist[i];
    for(j=i;j<L->length;j++)
        L->slist[j-1] = L->slist[j];
    L->length --;
    return OK;
}/* ListDelete_sq */
/*(7)---在順序表中查找指定值元素,pos爲返回其位置序號*/
int ListLocate(Sqlist *L,ElemType e,int *pos)
{
    int i;
    for(i=0;i<L->length;i++)
        if(e==L->slist[i])
        {
            *pos = i;
            return OK;
        }
    return ERROR;
}/* ListLocate */

int PrintList_sq(Sqlist *L)
{
    int i=0;
    for(i=0;i<L->length;i++)
        printf("%d ",L->slist[i]);
    return OK;
}

鏈表

鏈表的存儲:

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

鏈表的各種操作:

/*帶頭結點單鏈表初始化*/
LNode *InitList(LinkList L)
{
L=(LNode *)malloc(sizeof(LNode));  /*申請一個頭結點*/
if (!L)  return ERROR;/*申請失敗*/
L->next=NULL;  /*頭結點的指針域置空*/
return L;
}

/*(1)---輸出帶頭結點單鏈表的所有元素*/
void PrintList(LinkList L)
{
    LinkList p = L->next;
    while(p){
        printf("%d ",p->data);
        p = p->next;
    }
}/*PrintList*/

/*(2)---在單鏈表的第i個位置插入元素e,若插入成功返回OK,插入失敗返回ERROR*/
int InsertElem(LinkList L,int i,ElemType e)
{
LinkList p = L, s;
    int j=0;
    while(p && j< i-1 ){
        p = p->next;
        j++;
    }
    if(!p || j>i-1)
            return ERROR;
    s = (LinkList)malloc(sizeof(LNode));
    if(!s)
            return ERROR;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
}/* InsertElem */
/*(3)---查找第i位置的元素,若存在返回OK並由e返回其值,若不存在返回ERROR*/
int GetElem(LinkList L,int i,ElemType *e)
{

   LinkList p = L;
   int j=0;
   while(p && j<i){
       p = p->next;
       j++;
   }
   if(!p || j>i)
        return ERROR;

   *e = p->data;
   return OK;
}/*GetElem*/

/*(4)---刪除第i位置的元素,成功返回OK,並由e返回其值,若不成功返回ERROR,注意刪除的結點必須釋放其所佔空間*/
int DeleteElem(LinkList L,int i,ElemType *e)
{
   LinkList p = L, s;
   int j=0;
   while(p && j<i-1){
       p = p->next;
       j++;
   }
   if(!p || j>i-1)
        return ERROR;



    s = p->next;
    p->next = s->next;
    *e = s->data;
    free(s);
return OK;
}/* DeleteElem */
/*(5)---創建具有n個結點的單鏈表,創建成功返回其頭指針*/
LinkList CreateList(int n)
{
LinkList L = NULL, s;
    int e,i;
    L = InitList(L);

    for(i=0;i<n;i++){
        printf("input e=");
        scanf("%d",&e);
        InsertElem(L,i+1,e);
    }
    return L;
}/*CreateList*/

/*釋放鏈表及其空間*/
void DestroyLinkList(LinkList L)
{
LNode *p=L,*q;
while(p)
{
q=p->next;
free(p);
p=q;
}
}/* DestroyLinkList */

接下來提到了幾個應用。

約瑟夫環

約瑟夫環是經典的循環鏈表的應用。

用整數序列1,2,3,…,n表示順序坐在圓桌周圍的人,並採用循環鏈表作爲存儲結構。任意位置k開始計數,計到m讓此位置的人出局,重複上述過程,直至只剩下最後一個人。依次輸出每個出局的人的序號。
提示:用一個無頭結點的循環單鏈表來實現n個元素的存儲。exp2_3.c部分代碼如下:

#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1

typedef  int ElemType; /*定義表元素的類型*/
typedef struct LNode   /*線性表的單鏈表存儲*/
{
ElemType data;
struct LNode *next;
} LNode,*LinkList;

/*(1)---創建具有n個結點的無頭結點的單向循環鏈表,返回其頭指針*/
LinkList CreateList(int n)
{
    int i;
    LinkList head = (LinkList)malloc(sizeof(struct LNode));

    LinkList s=head,p;

    for(i=1;i<=n;i++)
    {
        p = (LinkList)malloc(sizeof(struct LNode));
        p->data = i;
        s->next = p;
        s = p;
    }
    p->next = head->next;
    return head->next;
}/*CreateList*/

/*(2)---輸出無頭結點循環單鏈表的所有元素*/
void PrintList(LinkList L)
{
    LinkList p=L;
    while(p){
        printf("%d ",p->data);
        p = p->next;
    }
}/*PrintList*/

/*(3)---約瑟夫問題計算,依次輸出出局的元素的序號*/
void JOSEPHUS(int n,int k,int m,LinkList L)
{
    L = CreateList(n);
    int i;

    LinkList p = L,tmp;
    while(p->data!=k)
        p = p->next;

    while(p->next!=p)
    {
        for(i=0;i<m-1;i++)
        {
            tmp = p;
            p = p->next;
        }
        printf("%d ",p->data);
        tmp->next = p->next;
        free(p);
        p = tmp->next;
    }
    printf("%d",p->data);
    free(p);
}/*JOSEPHUS*/
int main()
{
    int n,m,k;
    LinkList L=NULL;/*定義指向單鏈表的指針*/
    while(scanf("%d%d%d",&n,&k,&m)==3) /*n個元素從k位置開始每m個報數*/
        JOSEPHUS(n,k,m,L);
    return 0;
}

刪除重複結點的鏈表

LinkList del(LinkList L)
{
    LinkList p=L->next,q,r;

    while(p)
    {
        q = p;
        while(q->next)
        {
            if(q->next->data==p->data)
            {
                r = q->next;
                q->next = r->next;
                free(r);
            }
            else
                q = q->next;
        }
        p = p->next;
    }
    return L;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章