鏈表操作
這篇文章是上課實驗的內容,包括順序表,鏈表,以及鏈表的各種應用。
順序表
順序表的存儲:
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;
}