線性表:順序表和鏈表六種基本操作:
-
InitList(&L) //構造一個空的線性表L
-
ListLength(L) //獲取線性表L的元素個數
-
GetNode(L, i) //獲取線性表L第i個元素
-
LocateNode(L, e) //查找線性表值爲e的元素的位置
-
ListInsert(L, i, &e) //在線性表L的第i個位置插入元素e
-
DeleteNode(L, i) //刪除線性表L的第i個元素
一、順序表
#define OK 1
#define ERROR -1
#define MAX_SIZE 100 //MAX_SIZE大小需根據具體情況而定,這裏假設是100
#typedef int Status;
#typedef int ElemType;
typedef struct sqlist{
ElemType Elem_array[MAX_SIZE];
int length;
}SqList;
1.1 初始化
Status Init_SqList(SqList *L)
{
L->Elem_array = (ElemType *)malloc(MAX_SIZE*sizeof(ElemType));
if(!L->Elem_array)
return ERROR;
else
{
L->length = 0;
return OK;
}
}
1.2 查找
int Locate_SqList(SqList *L, ElemType x)
{
int i=0;
while(i<L->length)
if(L_Elem_array[i] != x)
i++;
else
return ++i; //要查找的值在線性表L第++i個位置
if(i>L->length)
{
printf(“要刪除的數據元素不存在!\n”);
return ERROR;
}
}
1.3 插入
Status Insert_SqList(SqList *L, int i, ElemType e) //在順序表L中第i個位置插入元素e
{
int j;
if(i<0||i>L->length-1)
return ERROR;
if(L->length>=MAX_SIZE)
{
printf("線性表溢出!\n");
return ERROR;
}
for(j=L->length-1; j>=i-1; --j)
L->Elem_array[j+1] = L->Elem_array[j]; //i-1位置以後的所以結點後移
L->Elem_array[i-1] = e; //在i-1位置插入結點e
L->length++;
return OK;
}
1.4 刪除
ElemType Delete_SqList(SqList *L, int i)
{
int k;
ElemType x;
if(L->length == 0)
{
printf("線性表L爲空!\n");
return ERROR;
}
else if(i<1||i>L->length)
{
printf("要刪除的數據元素不存在!\n");
return ERROR;
}
else
{
x = L->Elem_array[i-1]; //保存結點的值
for(k=i; k<L->length; k++)
L->Elem_array[k-1] = L->Elem_array[k]; //i位置以後的所有結點前移
L->length--;
return x;
}
}
二、單鏈表
typedef struct Lnode{
ElemType data; //數據域,保存結點的值
struct Lnode *next; //指針域
}LNode; //結點類型
2.1 頭插入法建表
/*頭插入法創建單鏈表,鏈表的頭結點head作爲返回值*/
LNode *create_LinkList(void)
{
int data;
LNode *head, *p;
head = (LNode *)malloc(sizeof(LNode));
head->next = NULL; //創建單鏈表頭結點head
while(1)
{
scanf("%d", &data); //data值和類型可以根據具體情況得到
if(data == 32767) //32767定義爲判斷創建鏈表結束條件
break;
p = (LNode *)malloc(sizeof(LNode));
p->data = data; //數據域賦值
p->next = head->next;
head->next = p; //鉤鏈,新創建的結點總是作爲第一個結點
}
return head;
}
2.2 尾插入法建表
/*尾插入法創建單鏈表,鏈表的頭結點head作爲返回值*/
LNode *create_LinkList(void)
{
int data;
LNode *head, *p, *q;
head = p = (LNode *)malloc(sizeof(LNode));
p->next = NULL; //創建單鏈表頭結點head
while(1)
{
scanf("%d", &data); //data值和類型可以根據具體情況得到
if(data == 32767) //32767定義爲判斷創建鏈表結束條件
break;
q = (LNode *)malloc(sizeof(LNode));
q->data = data; //數據域賦值
q->next = p->next;
p->next = q;
p = q; //鉤鏈,新創建的結點總是作爲第一個結點
}
return head;
}
2.3 按序號查找
Elem_Type Get_Node(LNode *L, int i) //在單鏈表L中查找第i個結點
{
int j;
LNode *p;
p = L->next;
j = 1; //使p指向第一個結點
while(p!=NULL && j<i) //p爲NULL表示i太大;j>i表示i爲0;
{
p = p->next;
j++; //移動指針p,j計數
}
if(j!=i)
return -32768;
else
return p->data;
}
2.4 按值查找
LNode *Locate_Node(LNode *L, int key) //在單鏈表L中查找值爲key的結點
{
LNode *p = L->next;
while(p!=NULL && p->data != key)
p = p->next;
if(p->data == key)
return p;
else
{
printf("所要查找的結點不存在!\n");
return NULL;
}
}
2.5 插入
/*在以L爲頭結點的單鏈表的第i個位置插入值爲e的結點*/
void Insert_LNode(LNode *L, int i, ElemType e)
{
int j = 0;
LNode *p, *q;
p = L->next;
while(p!=NULL && j<i-1)
{
p = p->next;
j++;
}
if(j!=i-1)
printf("i太大或i爲0!\n");
else
{
q = (LNode *)malloc(sizeof(LNode));
q->data = e;
q->next = p->next;
p->next = q;
}
}
2.6 按序號刪除
/*刪除以L爲頭結點的單鏈表中的第i個結點*/
void Delete_LinkList(LNode *L, int i)
{
int j=1;
LNode *p = L, *q = L->next;
while(p->next!=NULL && j<i)
{
p = q;
q = q->next;
j++;
}
if(j!=i)
printf("i太大或i爲0!\n");
else
{
p->next = q->next;
free(q);
}
}
2.7 按值刪除
/*刪除以L爲頭結點的單鏈表中值爲key的第一個結點*/
void Delete_LinkList(LNode *L, int key)
{
LNode *p = L, *q = L->next;
while(q!=NULL && q->data!=key)
{
p = q;
q = q->next;
}
if(q->data == key)
{
p->next = q->next;
free(q);
}
else
printf("所要刪除的結點不存在!\n");
}
/*按值刪除值爲key的所有結點*/
void Delete_LinkList_Node(LNode *L, int key)
{
LNode *p = L, *q = L->next;
while(q!=NULL)
{
if(q->data==key)
{
p->next = q->next;
free(q);
q = p->next;
}
else
{
p = q;
q = q->next;
}
}
}
/*刪除以L爲頭結點的單鏈表中所有值相同的結點*/
void Delete_Node_value(LNode *L)
{
LNode *p = L->next, *q, *ptr;
while(p!=NULL) //檢查鏈表中所有結點
{
q = p;
ptr = p->next;
while(ptr != NULL) //檢查結點p的所有後繼結點ptr
{
if(ptr->data == p->data)
{
q->next = ptr->next;
free(ptr);
ptr = q->next;
}
else
{
q = ptr;
ptr = ptr->next;
}
}
p = p->next;
}
}
2.8 合併
/*合併以La,Lb爲頭結點的兩個有序單鏈表*/
LNode *Merge_LinkList(LNode *La, LNode *Lb)
{
LNode *Lc, *pa, *pb, *pc, *ptr;
Lc = La;
pc = La;
pa = La->next;
pb = Lb->next;
while(pa!=NULL &&pb!=NULL)
{
//將pa所指的結點合併,pa指向下一個結點
if(pa->data < pb->data)
{
pc->next = pa;
pc = pa;
pa = pa->next;
}
//將pb所指的結點合併,pb指向下一個結點
if(pa->data > pb->data)
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
//將pa所指的結點合併,pb所指的結點刪除
if(pa->data == pb->data)
{
pc->next = pa;
pc = pa;
pa = pa->next;
ptr = pb;
pb = pb->next;
free(ptr);
}
}
if(pa != NULL)
pc->next = pa;
else
pc->next = pb; //將剩餘的結點鏈上
free(Lb);
return Lc;
}
三、循環鏈表
判斷是否空鏈表: head->next == head;
判斷是否表尾結點: p->next == head;
四、雙向鏈表
typedef struct Dulnode{
ElemType data;
struct Dulnode *prior, *next;
}DulNode;
4.1 插入
- 插入時僅僅指出直接前驅結點,鉤鏈時必須注意先後次序是:“先右後左”。部分語句組如下:
S = (DulNode *)malloc(sizeof(DulNode)); S->data = e; S->next = p->next; p->next->prior = S; p->next = S; S->prior = p;
-
插入時同時指出直接前驅結點p和直接後繼結點q,鉤鏈時無須注意先後次序。部分語句組如下:
S = (DulNode *)malloc(sizeof(DulNode)); S->data = e; p->next = S; S->next = q; S->prior = p; q->prior = S;
4.2 刪除
設要刪除的結點爲p,刪除時可以不引人新的輔助指針變量,可以直接先斷鏈,再釋放結點。部分語句組如下:
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);