链表操作

链表操作

这篇文章是上课实验的内容,包括顺序表,链表,以及链表的各种应用。

顺序表

顺序表的存储:

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;
}

你可能感兴趣的:(链表,线性表)