目錄
線性表
n個 具有相同特性的(同一數據對象) 數據元素的有限序列
(1)存在唯一的一個被稱爲“第一個”的數據元素
(2)存在唯一的一個被稱爲“最後一個”的數據元素
(3)除第一個之外,集合中的每個數據元素只有一個前驅
(4)除最後一個外,集合中每個數據元素只有一個後繼
概念
數據項【item】(記錄【record】):一個數據元素可以由若干數據項組成
文件【record】:含有大量記錄的線性表
直接前驅:a[i](直接前驅)領先與a[i+1]
直接後繼:a[i+1](直接後繼)
線性表長度:n,當n=0時,稱爲空表
ADT
ADT List{
數據對象:D={a(i)|a(i)∈ElemSet,i=1,2,...,n,n >= 0}
數據關係:R1={<a(i-1),a(i)>|a(i-1),a(i)∈D,i = 2,...,n}
基本操作:
InitList(&L)
操作結果:構造一個空的線性表L
DestroyList(&L)
初始條件:線性表L已存在
操作結果:銷燬線性表L
ClearList(&l)
初始條件:線性表L已存在
操作結果:將L重置爲空表
ListEmpty(L)
初始條件:線性表L已存在
操作結果:若L爲空表,則返回TRUE,否則返回FALSE
ListLength(L):
初始條件:線性表L已存在
操作結果:返回L中數據元素的個數
GetElem(L,i,&e)
初始條件:線性表L已存在,1<=i<=ListLength(L)
操作結果:用e返回L中第i個數據元素的值
LocateElem(L,e,compare())
初始條件:線性表L已存在,compare()是數據元素判定元素
操作結果:返回L中第1個與e滿足關係compare()的數據元素的位序,若這樣的數據元素不存在,
則返回值是0
PriorElem(L,cur_e,&pre_e)
初始條件:線性表L已存在
操作結果:若cur_e是L的數據元素,且不是第一個,則用pre_e作爲他的前驅,否則操作失敗,
pre_e無定義
NextElem(L,cur_e,&next_e)
初始條件:線性表L已存在
操作結果:若cur_e是L的數據元素,且不是最後一個,則用next_e作爲他的後繼,否則操作失
敗,next_e無定義
ListInsert(&L,i,e)
初始條件:線性表L已存在,1<=i<=ListLength(L)+1
操作結果:在L中第i個位置之前插入新的數據元素e,L的長度加1
ListDelete(&L,i,&e)
初始條件:線性表L已存在,1<=i<=ListLength(L)
操作結果:刪除第i個數據元素,並用e返回其值,L的長度減1
ListTraverse(L,visit())
初始條件:線性表L已存
操作結果:依次對L的每個數據元素調用函數visit()。一旦visit()失敗,操作失敗。
}ADT List
線性表的兩種存儲結構
順序存儲結構【順序映像】
線性表的順序表示
//線性表的順序表示和存儲結構
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# define LIST_INIT_SIZE 100//線性表存儲空間的初始分配量
# define LISTINCREMENT 10//線性表存儲空間的分配增量
# define ElemType int//定義數據類型
# define Status int
# define ERROR 0
# define OK 1
# define TRUE 1
# define FALSE 0
# define OVERFLOW -1
typedef struct
{
ElemType *Elem;
int Length;
int ListSize;
}SqList;
//構造一個空的線性表L
Status InitList(SqList *L)
{
L->Elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!*L->Elem)
{
printf("內存分配失敗!\n");
exit(OVERFLOW);
return ERROR;
}
L->Length = 0;
L->ListSize = LIST_INIT_SIZE;
printf("線性表構造成功!\n");
return OK;
}
//用數組給線性表賦值
Status ListAssign(SqList *L, ElemType *Array,int length)
{
int i = 0, j = 0;
while (j < length)
{
L->Elem[j++] = Array[i++];
}
L->Length = length;
return OK;
}
//重置爲空表
Status ClearList(SqList *L)
{
int i;
for (i = 0; i < L->Length; ++i)
L->Elem[i] = 0;
printf("重置成功!\n");
return OK;
}
//銷燬線性表L
Status DestroyList(SqList *L)
{
if (!L)
{
printf("線性表不存在!\n");
return ERROR;
}
while (!L->Elem)
free(L->Elem);
L->Length = 0;
L->ListSize = 0;
printf("刪除成功\n");
return OK;
}
//判斷線性表是否爲空
Status ListEmpty(SqList L)
{
if (L.Length == 0)
{
printf("線性表爲空表!\n");
return TRUE;
}
else
return FALSE;
}
//返回線性表長度
Status ListLength(SqList *L)
{
if (!L)
{
printf("線性表不存在!\n");
return ERROR;
}
return L->Length;
}
//插入:在L中第i個位置之前插入新的數據元素e,L的長度加1
Status ListInsert(SqList *L, int i, ElemType e)
{
//非法插入位置
if (i < 1 || i > L->Length + 1)
{
printf("插入位置非法!\n");
return ERROR;
}
//若滿,擴充數組長度
if (L->Length == L->ListSize)
{
ElemType *new_base = (ElemType *)realloc(L->Elem, (L->ListSize + LISTINCREMENT) * sizeof(Status));
if (!new_base)
{
printf("內存分配失敗!\n");
exit(OVERFLOW);
return ERROR;
}
L->Elem = new_base;
L->ListSize += LISTINCREMENT;
}
//特殊情況,插入位置在最後一個
if (i == L->Length + 1)
{
L->Elem[L->Length] = e;
}
else
{
ElemType *p = NULL;
ElemType *q = &L->Elem[i - 1];
for (p = &(L->Elem[L->Length - 1]); p >= q; --p)
{
*(p + 1) = *p;
}
*q = e;
}
L->Length++;
return OK;
}
//刪除 :刪除第i個數據元素,並用e返回其值,L的長度減1
Status ListDelete(SqList *L, int i, ElemType *e)
{
if (i < 1 || i > L->Length)
{
printf("非法下標!\n");
return ERROR;
}
int *p = &(L->Elem[i - 1]);
*e = *p;
int *q = L->Elem + L->Length - 1;
for (++p; p <= q; ++p)
*(p - 1) = *(p);
--L->Length;
return OK;
}
//訪問函數
Status visit(Status t)
{
printf("%d ", t);//由於宏定義的特殊性,修改Status值是,訪問函數的輸出控制符需要相應的修改
/*測試訪問失敗條件
if(t == 2)
return ERROR;
*/
return OK;
}
//遍歷
Status ListTraverse(SqList L, Status(*visit)(ElemType e))
{
if (!&L)
{
printf("線性鏈表不存在!\n");
return ERROR;
}
printf("遍歷數組:\n");
int i;
for (i = 0; i < L.Length; ++i)
{
if (!visit(L.Elem[i]))
{
printf("\nL.Elem[%d]訪問失敗!\n", i);
return ERROR;
}
}
return OK;
}
//獲取cur_e的直接前驅
//若cur_e是L的數據元素,且不是第一個,則用pre_e作爲他的前驅,否則操作失敗,pre_e無定義
Status PriorElem(SqList L, ElemType cur_e, ElemType *pre_e)
{
int i;
for (i = 0; i < L.Length; ++i)
{
if (L.Elem[i] == cur_e)
{
break;
}
}
if (i == 0)
{
printf("cur_e是第一個元素,沒有直接前驅!\n");
return ERROR;
}
if (i == L.Length)
{
printf("cur_e不存在\n");
return ERROR;
}
*pre_e = L.Elem[i - 1];
return OK;
}
//獲取cur_e的直接後繼
Status NextElem(SqList L, ElemType cur_e, ElemType *next_e)
{
int i;
for (i = 0; i < L.Length; ++i)
{
if (cur_e == L.Elem[i])
break;
}
if (i == L.Length)
{
printf("不存在直接後繼!\n");
return ERROR;
}
*next_e = L.Elem[i + 1];
return OK;
}
//用e返回L中第i個數據元素的值
Status GetElem(SqList L, int i, ElemType *e)
{
if (ListEmpty(L))
{
return ERROR;
}
if (i < 0 || i > L.Length)
{
printf("position error!\n");
return OVERFLOW;
}
*e = L.Elem[i - 1];
}
Status compare(ElemType a, ElemType b)
{
if (a == b)
return TRUE;
else
return FALSE;
}
//查找線性鏈表中第一個滿足compare關係的元素
Status LocateElem(SqList L, ElemType e, Status(*compare)(ElemType a, ElemType b))
{
int i;
for (i = 0; i < L.Length; ++i)
{
if (compare(e, L.Elem[i]))
{
return i + 1;
}
}
return FALSE;
}
//將所有在線性表Lb中但不在La中的數據元素插入到La中
void reunion(SqList *La, SqList Lb)
{
int La_len = ListLength(La);
int Lb_len = ListLength(&Lb);
int i, j;
ElemType e;
for (i = 0; i <= Lb_len; ++i)
{
GetElem(Lb, i, &e);
if (!LocateElem(*La, e, compare))
ListInsert(La, ++La_len, e);
}
}
//已知La,Lb中的數據元素按值非遞減排列
//歸併la,lb得到新的線性表Lc也滿足值非遞減
void MergeList(SqList La, SqList Lb, SqList *Lc)
{
InitList(Lc);
int i = 1, j = 1;
int k = 0;
int La_len = ListLength(&La), Lb_len = ListLength(&Lb);
ElemType ai, bj;
while ((i <= La_len) && (j <= Lb_len))
{
GetElem(La, i, &ai);
GetElem(Lb, i, &bj);
if (ai <= bj)
{
ListInsert(Lc, ++k, ai);
++i;
}
else
{
ListInsert(Lc, ++k, bj);
++j;
}
}
while (i <= La_len)
{
GetElem(La, i++, &ai);
ListInsert(Lc, ++k, ai);
}
while (j <= Lb_len)
{
GetElem(Lb, j++, &
bj);
ListInsert(Lc, ++k, ai);
}
}
void MergeList_Sq(SqList La, SqList Lb, SqList *Lc)
{
ElemType *pa = La.Elem, *pb = Lb.Elem;
Lc->ListSize = Lc->Length = La.Length + Lb.Length;
Lc->Elem = (ElemType *)malloc(Lc->ListSize * sizeof(ElemType));
ElemType *pc = Lc->Elem;
if (!Lc->Elem)
exit(OVERFLOW);
ElemType *pa_last = La.Elem + La.Length - 1;
ElemType *pb_last = Lb.Elem + Lb.Length - 1;
//歸併
while (pa <= pa_last && pb <= pb_last)
{
if (*pa <= *pb)
*pc++ = *pa++;
else
*pc++ = *pb++;
}
//插入剩餘元素
while (pa <= pa_last)
*pc++ = *pa++;
while (pb <= pb_last)
*pc++ = *pb++;
}
int main()
{
SqList list;
InitList(&list);
ElemType m, pre_m, next_m, tmp;
ElemType arr[5] = { 1,2,3,4,5 };
ListAssign(&list, arr,5);
ListTraverse(list, visit);
/*
GetElem(list, 4, &tmp);
printf("獲取到的第四個元素是:%d\n",tmp);
printf("\n第一個與2滿足compare關係的是:%d\n",LocateElem(list, 2, compare));
PriorElem(list,2,&pre_m);
printf("%d\n",pre_m);
NextElem(list,2,&next_m);
printf("%d\n",next_m);
GetElem(list,3,&tmp);
printf("%d\n",tmp);
//printf("%d\n",next_m);
//printf("%d\n",pre_m);
ListDelete(&list,4,&m);
printf("\n刪除的元素是:%d\n",m);
ListTraverse(list,visit);
*/
return 0;
}
鏈式存儲結構
用一組任意的存儲單元存儲線性表的數據元素
結點:包含數據域和指針域
指針域中存儲的信息稱作指針或鏈
頭指針:指向頭結點的位置
頭節點:鏈表的第一個節點之前附設一個結點,稱爲頭結點。若線性表爲空表,頭結點的指針域指爲“空”
單鏈表ADT
typedef struct LNode{//節點類型
ElemType data;
struct LNode *next;
}*Line,*Position;
typedef struct{
Link head,tail;
int len;
}LinkList;
Status MakeNode(Link &p,ElemType e);
//分配p指向的值爲e的結點,並返回OK;若分配失敗,則返回ERROR
void FreeNode(Link &p)
//釋放p所指的結點
Status InitList(Link &L)
//構造一個空的線性鏈表
Status DestoryList(Link &L)
//銷燬線性鏈表L,L不再存在
Status ClearList(LinkList &L);
//將線性鏈表L重置爲空表,並釋放原鏈表的結點空間
Status InsFirst(Link h,Link s)
//h指向線性鏈表的頭結點,將s所指的結插入到第一個加點之前
Status DelFirst(Link h,Link &q)
//h指向線性鏈表的頭結點,刪除鏈表中的第一個結點並以q返回
Status Append(LinkList &L,Link s)
//將指針s所指(彼此以指針想鏈)的一串結點鏈接在線性鏈表的L的最後一個結點
//之後,並改變鏈表的尾指針並指向新的尾結點
Status Remove(LinkLits &L,Link &q)
//刪除線性鏈表L中的尾結點並以Q返回,改變鏈表L的尾指針,指向新的尾結點
Status InsBefore(LinkList &L,Link &p,Link s)
//已知p指向線性鏈表L中的第一個結點,將S所指向的結點插入在p所指的結點之前,並修改指針P指向新插入的結點
Status InsAfter(LinkList &L,Link &p,Link s)
//已知p指向線性鏈表L中的第一個結點,將S所指向的結點插入在p所指的結點之後,並修改指針P指向新插入的結點
Status SetCurElem(Link &p,ElemType e)
//已知p指向鏈表中的一個結點,用e更新p所指結點中數據元素的值
ElemType GetCurElem(Link p)
//已知p指向線性鏈表中的第一個結點,返回p所指結點中數據元素的值
Status ListEmpty(LinkList L)
//若線性鏈表爲空表,返回TRUE,否則返回FALSE
int LinkLength(LinkList L)
//返回線性鏈表L中頭結點的元素個數
Position GetHead(LinkList L)
//返回線性鏈表L中頭結點的位置
Posioton GetLast(LinkList L)
//返回線性鏈表L中的最後一個結點的位置
Position PriorPos(LinkList L,Link p)
//已知p指向線性鏈表L中的一個結點,返回p所指的結點的直接前驅的位置,
//若無前驅,返回null
Poition NextPos(LinkList L,Link p)
//已知p指向線性鏈表L中的第一個結點,返回p所指向的直接後繼的位置
//若無後繼,則返回null
Status LocatePos(LinkList L,int i,Link &p)
//返回P指示線性鏈表L中的第i個結點的位置並返回OK,i值不合法時,返回ERROR
Status LocateElem(LinkList L,ElemType e,Status (*campare)(ElemType,ElemType))
//返回線性鏈表L中第一個與e滿足函數compare()判定關係的元素的位置
//若不存在這樣的元素,返回null
Status ListTraverse(LinkList L,Status(*visit)())
//依次對L的每個元素調用函數visit()。一旦visit()調用失敗,則操作失敗
// 線性鏈表.cpp : 定義控制檯應用程序的入口點。
# include <stdio.h>
# include<stdlib.h>
# include<string.h>
# define LIST_INIT_SIZE 100//線性表存儲空間的初始分配量
# define LISTINCREMENT 10//線性表存儲空間的分配增量
# define ElemType int//定義數據類型
# define Status int
# define ERROR 0
# define OK 1
# define TRUE 1
# define FALSE 0
# define OVERFLOW -1
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList,*Position,*pNode;
//創建節點
Status MakeNode(LinkList *Node, ElemType e)
{
*Node = (LinkList)malloc(1 * sizeof(LNode));
if (!Node)
{
//內存分配失敗!
exit(OVERFLOW);
}
(*Node)->data = e;
return OK;
}
//刪除Node所指向的節點
Status FreeNode(pNode p)
{
free(p);
return OK;
}
//初始化線性鏈表
Status InitList(LinkList *L)
{
*L = (LinkList)malloc(1 * sizeof(LNode));
if (!(*L))
return ERROR;
return OK;
}
//重置線性鏈表
Status ClearList(LinkList *L,ElemType e)
{
if (!(*L))
{
printf("線性鏈表爲空!");
return ERROR;
}
LinkList p, q;
p = *L;
while (p)
{
p->data = e;
p = p->next;
}
return OK;
}
//返回頭結點指針
Position GetHead(LinkList L)
{
if (!L)
{
printf("鏈表不存在!\n");
return ERROR;
}
return L->next;
}
//返回尾結點位置
Position GetLast(LinkList L)
{
if (!L)
{
printf("鏈表不存在!\n");
return ERROR;
}
Position p = NULL;
for (p = L->next; p && p->next; p = p->next);
return p;
}
//在h所指向的頭結點之前插入s所指向的節點
Status InsFirst(LinkList *L, pNode s)
{
Position Head = GetHead(*L);
s->next = Head;
(*L)->next = s;
/*1 10 2 3
s->next = Head->next;
Head->next = s;*/
return OK;
}
//刪除h指向的頭結點,節點位置返回到q指針
Status DelFirst(LinkList *L, pNode *q)
{
Position Head = GetHead(*L);
(*L)->next = Head->next;
*q = Head;
pNode p = (pNode)malloc(1 * sizeof(LNode));
*p = *Head;
FreeNode(p);
return OK;
}
//將指針s所指的一串節點鏈接在L的最後
Status Append(LinkList *L, pNode s)
{
Position Tail = GetLast(*L);
Tail->next = s->next;
return OK;
}
//刪除尾節點,並以q返回
Status Remove(LinkList *L, LNode *q)
{
if (!L)
{
printf("鏈表不存在!\n");
return ERROR;
}
Position Tail = GetLast(*L);
pNode p = *L;
while (p && p->next != Tail)
{
p = p->next;
}
p->next = NULL;
*q = *Tail;
FreeNode(Tail);
return OK;
}
//已知p指向鏈表中的一個節點,將s所指向的節點插入在p所指節點之前
Status InsBefore(LinkList *L, pNode p, pNode s)
{
pNode q = (*L)->next;
while (q && q->next != p)
{
q = q->next;
}
s = q->next;
q->next = s;
return OK;
}
//已知P指向鏈表中的一個節點,將s指向的節點插入在所指節點之後
Status InsAfter(LinkList *L, pNode p, pNode s)
{
s->next = p->next;
p->next = s;
return OK;
}
//銷燬線性鏈表
Status DestoryList(LinkList *L)
{
if (!(*L))
return ERROR;
LinkList p, q;
p = (*L)->next;
while (p)
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL;
return OK;
}
//逆位序輸入n個元素的值,建立帶頭節點的單鏈線性表(帶頭結點)
Status CreateList_n(LinkList *L, int n)
{
int i;
LinkList p;
*L = (LinkList)malloc( 1 * sizeof(LNode));
if (!L)
{
printf("內存分配失敗!\n");
exit(OVERFLOW);
}
(*L)->next = NULL;
printf("輸入鏈表數據:\n");
while(n--)
{
p = (LinkList)malloc(1 * sizeof(LNode));
if (!p)
{
printf("內存分配失敗!\n");
exit(OVERFLOW);
}
scanf_s("%d",&p->data);
p->next = (*L)->next;
(*L)->next = p;
}
return OK;
}
//正位序創建線性單鏈表(帶頭結點)
Status CreateList_p(LinkList *L, int n)
{
//L是鏈表的頭指針
LinkList p = NULL, q = NULL;
InitList(L);
if (!L)
{
exit(OVERFLOW);
}
(*L)->next = NULL;
q = *L;//指向當前節點
ElemType e;
for (int i = n; i>0; i--)
{
scanf_s("%d",&e);
MakeNode(&p, e);
q->next = p;//若變爲q = p則爲無頭結點的鏈表
q = q->next;
}
p->next = NULL;
return OK;
}
//返回鏈表長度
int ListLength(LinkList L)
{
int sum = 0;
LinkList p = L->next;
while (p)
{
sum++;
p = p->next;
}
return sum;
}
//獲取第i個節點數字的值,賦給e
Status 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;
}
//單鏈表插入
Status ListInsert(LinkList *L, int i, ElemType e)
{
LinkList p = *L;
int j = 0;
while (p && j < i - 1)
{
p = p->next;
j++;
}
if (!p || j > i - 1)
return ERROR;
LinkList s = (LinkList)malloc(1 * sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
//單鏈表刪除
Status ListDelete(LinkList *L, int i, ElemType *e)
{
LinkList p = *L;
int j = 0;
while (p->next && j < i - 1)
{
p = p->next;
++j;
}
if (!(p->next) || j > i - 1)
return ERROR;
LinkList q = (LinkList)malloc(1 * sizeof(LNode));
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
//用e更新節點所指向的節點的數值,一直p是線性鏈表中的一個結點
Status SetCurElem(LNode *p, ElemType e)
{
p->data = e;
return OK;
}
//大於等於關係
Status compare(ElemType a, ElemType b)
{
if (a >= b)
return OK;
else
return ERROR;
}
//返回鏈表中L中第一個與e滿足compare關係的元素的位置
Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType a, ElemType b))
{
Position p = L->next;
while (p)
{
if (compare(p->data, e))
break;
p = p->next;
}
if (p == NULL)
return NULL;
return p;
}
//返回 P指向的鏈表中第i個位置的節點,並返回OK,如果i值不合法,返回ERROR
Status LocatePos(LinkList L, int i, LNode *p)
{
if (i >= ListLength(L) || i == 0)
{
printf("超出合理返回!\n");
return ERROR;
}
int j = 0;
LNode* q = L->next;
while (j < i)
{
q = q->next;
j++;
}
*p = *q;
return OK;
}
//已知p指向線性表中的一個結點,返回前驅結點
Position PriorPos(LinkList L, pNode p)
{
Position Head = GetHead(L);
if (p == Head)
{
printf("沒有前驅!\n");
return NULL;
}
pNode q = Head;
while (q->next != p)
{
q = q->next;
}
return q;
}
//已知p指向鏈表的一個節點,返回p所指向的直接後繼的位置
Position NextPos(LinkList L, pNode p)
{
Position Tail = GetLast(L);
if (p == Tail)
{
printf("直接後繼不存在!\n");
return NULL;
}
return p->next;
}
//判斷數組是否爲空
Status ListEmpty(LinkList L)
{
if (ListLength(L) == 0)
{
return OK;
}
return ERROR;
}
//訪問函數
Status visit(ElemType e)
{
printf("%d ",e);
return OK;
}
//遍歷鏈表,訪問visit函數
Status ListTraverse(LinkList L,Status(*visit)(ElemType e))
{
if (!L)
{
printf("鏈表不存在!\n");
return ERROR;
}
if (ListEmpty(L))
{
printf("空鏈表!\n");
return ERROR;
}
LinkList p = L->next;
while (p)
{
if (!visit(p->data))
{
return ERROR;
}
p = p->next;
}
printf("\n");
return OK;
}
//輸出某個確定節點的值
Status ShowData(LinkList L,int i)
{
if (i <= 0)
return FALSE;
int j;
for (j = 0; j < i; ++j)
{
L = L->next;
}
printf("%d ",L->data);
return OK;
}
//兩個鏈表去重合成
void MergeList(LinkList *La, LinkList *Lb, LinkList *Lc)
{
//已知單鏈線性表La,Lb的元素按值非遞減的順序排列
//歸併La和Lb得到新的單鏈線性表Lc,Lc的元素也按照值遞減的順序排列
LinkList pa = (*La)->next;
LinkList pb = (*Lb)->next;
Lc = La;
LinkList pc = *La;
while (pa && pb)
{
if (pa->data <= pb->data)
{
pc->next = pa;
pc = pa;
pa = pc->next;
}
else
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
pc->next = pa ? pa : pb;
free(Lb);
}
int main()
{
LinkList List = NULL;
int i,m,len;
/*
LinkList list = NULL;
CreateList_n(&list, 3);
printf("逆序輸出鏈表:\n");
for(i = 0;i < 3;++i)
ShowData(list, i+1);
*/
printf("輸入鏈表長度\n");
scanf_s("%d",&len);
printf("輸入線性鏈表的值:\n");
CreateList_p(&List,len);
printf("遍歷鏈表:\n");
ListTraverse(List,visit);
/*
Position next = NextPos(List,GetHead(List));
printf("首節點的直接後繼是:\n");
printf("%d\n",next->data);
Position pre = PriorPos(List, GetLast(List));
printf("尾結點的前驅是:\n");
printf("%d\n",pre->data);
LNode tail;
Remove(&List, &tail);
printf("刪除的元素是:%d",tail.data);
printf("\n");
printf("遍歷鏈表:\n");
ListTraverse(List, visit);
LinkList s = NULL;
printf("輸入新增鏈長度:\n");
scanf_s("%d",&len);
printf("新增的鏈是:\n");
CreateList_p(&s, len);
Append(&List, s);
printf("遍歷鏈表:\n");
ListTraverse(List, visit);
LNode anew;
anew.data = 10;
anew.next = NULL;
InsFirst(&List, &anew);
printf("遍歷鏈表:\n");
ListTraverse(List, visit);
pNode del;
DelFirst(&List, &del);
printf("遍歷鏈表:\n");
ListTraverse(List, visit);
Position tail = GetLast(List);
printf("尾節點的值爲:%d\n",tail->data);
LNode p;
LocatePos(List, 2, &p);
printf("第2位數據是:\n%d",p.data);
ElemType pos_data;
printf("輸入判斷數據:\n");
scanf_s("%d", &pos_data);
Position pos = LocateElem(List, pos_data, compare);
if (pos)
printf("%d\n", pos->data);
else
printf("數據不存在\n");
printf("順序輸出鏈表:\n");
for (i = 0; i < len; ++i)
ShowData(List, i + 1);
printf("\n鏈表長度:%d",ListLength(List));
ClearList(&List, 0);
printf("\n清空數組:\n");
for (i = 0; i < 3; ++i)
ShowData(List, i + 1);
ListDelete(&List, 2, &m);
printf("\n刪除的元素是:%d\n",m);
printf("刪除後鏈表:\n");
for (i = 0; i < 2; ++i)
ShowData(List, i + 1);
GetElem(List,2,&m);
printf("%d\n",m);
ListInsert(&List, 2, 2);
printf("\n插入後鏈表:\n");
for (i = 0; i < 4; ++i)
ShowData(List, i + 1);
*/
return 0;
}
靜態鏈表
用數組代替值代表指針域
# include <stdio.h>
# include<string.h>
# include<stdlib.h>
# define OK 1
# define FALSE 0
# define OVERFLOW -1
# define Status int
# define ElemType int
# define ERROR -1
# define MAXSIZE 1000 //鏈表的最大長度
typedef struct
{
ElemType data;
int cur;
}component,SLinkList[MAXSIZE];
//將一維數組space各分量鏈成一個備用鏈表,space[0].cur作爲頭指針
//"0"表示空指針
void InitSpace(SLinkList space)
{
int i;
for (i = 0; i < MAXSIZE - 1; ++i)
space[i].cur = i + 1;
space[MAXSIZE - 1].cur = 0;
}
//從備用鏈表中取第一個空閒節點,返回下標
int Malloc(SLinkList space)
{
int i = space[0].cur;
if (space[0].cur)
{
space[0].cur = space[i].cur;
}
return i;
}
//將下標爲k的空閒節點回收到備用鏈表中
void Free(SLinkList space,int k)
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
//求鏈表 的長度
int ListLength(SLinkList space)
{
int amount = 0,i = 0;
while (space[i].cur)
{
i = space[i].cur;
++amount;
}
return amount;
}
//插入
Status ListInsert(SLinkList L, int i, ElemType e)
{
int j,k,l;
k = MAXSIZE - 1;//L[k].cur = 1
if (i < 1 || i > ListLength(L) + 1)
return ERROR;
j = Malloc(L);
if (j)
{
L[j].data = e;
for (l = 1; l <= i - 1; ++l)
{
k = L[k].cur;//1->i-1
}
L[j].cur = L[k].cur;
L[k].cur = j;
return OK;
}
else
return ERROR;
}
//刪除並賦值
Status ListDelete(SLinkList L, int i, ElemType *e)
{
int j, k;
if (i < 1 || i > ListLength(L))
return ERROR;
k = MAXSIZE - 1;
for (j = 1; j <= i - 1; ++j)
{
k = L[k].cur;//0->i-1
}
j = L[k].cur;
L[k].cur = L[j].cur;
*e = L[j].data;
Free(L, j);
return OK;
}
//遍歷輸出
void ListPrint(SLinkList L)
{
int i = L[MAXSIZE - 1].cur;//指向第一個
while (i != 0)
{
printf("%d ", L[i].data);
i = L[i].cur;
}
printf("\n");
}
//
int LocateElem(SLinkList L, ElemType e)
{
int i = L[0].cur;
while (i && L[i].data != e)
{
i = L[i].cur;
}
return i;
}
void difference(SLinkList L, int *S)
{
InitSpace(L);
*S = Malloc(L);//S指向結果鏈表的頭節點
int *r = S;//尾指針:指向鏈表尾部
int m, n,i,j,b,k;
scanf_s("%d%d",&m,&n);//m,n分別表示兩個集合的數量
//輸入第一個集合的元素
for (j = 1; j <= m; ++j)
{
i = Malloc(L);//分配節點
scanf_s("%d",L[i].data);
L[*r].cur = i;//將i連接到鏈表
*r = i;//將尾指針指向i
}
L[*r].cur = 0;//尾部設爲空
for (j = 1; j <= n; ++j)//輸入第二個集合的n個元素
{
scanf_s("%d", &b);
int *p = S;//p指向頭指針;只是爲了存在時候使用,與k同步
k = L[*S].cur;//k從頭結點開始遍歷
while (k != L[*r].cur && L[*S].data != b)//遍歷條件:未到達節點尾部;元素是否存在於鏈表中
{
*p = k;
k = L[k].cur;
}
//若不存在與鏈表中,插入
if (k == L[*r].cur)
{
i = Malloc(L);
L[i].data = b;
L[i].cur = L[*r].cur;
L[*r].cur = i;
}
else//若存在,將該元素刪除
{
L[*p].cur = L[k].cur;
Free(L, k);
if (*r == k)
r = p;//若刪除的是r所指節點,則需修改尾指針
}
}
}
int main()
{
SLinkList list;
ElemType m;
InitSpace(list);
ListPrint(list);
int i;
for (i = 0; i <= 3; ++i)
{
ListInsert(list,i,i*10);
}
ListPrint(list);
printf("%d\n",LocateElem(list,20));
for (i = 1; i <= 3; ++i)
{
ListDelete(list, 1, &m);
printf("刪除元素:%d\n",m);
}
return 0;
}
循環鏈表
循環鏈表的結構和單鏈表結構一樣
單鏈表尾結點的指針由空指針改爲指向頭結點,就使整個單鏈表形成一個環,
這種頭尾相接的單鏈表稱爲循環單鏈表,簡稱循環鏈表。表中最後一個結點的指針域指向頭結點,整個鏈表形成一個環
# include<stdio.h>
# include<string.h>
# include<stdlib.h>
# define OK 1
# define ERROR 0
# define TRUE 1
# define FALSE 0
# define END 0
# define OVERFLOW -1
# define ElemType int
# define Status int
typedef struct CLinkNode
{
ElemType data;
struct CLinkNode *next;
}CLinkNode,*CLinkList;
//初始化循環鏈表
Status InitCLinkList(CLinkList *list)
{
if (list == NULL)
return ERROR;
int data;
CLinkNode *target = NULL;//尋找尾結點位置
CLinkNode *head_node = NULL;//存儲頭結點位置
printf("輸入鏈表的值,0表示結束初始化:\n");
while (1)
{
scanf_s("%d", &data);
//判斷是否爲初始化結束標誌
if (data == 0)
break;
//判斷list是否爲空鏈表
//若爲空,創建頭指針指向的頭結點
//不爲空,找到尾結點,插入到 尾結點之後,並將其指向頭節點
if (*list == NULL)
{
//創建頭指針
CLinkNode *head = (CLinkNode *)malloc(1 * sizeof(CLinkNode));
if (head == NULL)
{
printf("內存分配失敗!\n");
exit(OVERFLOW);
}
*list = head;
//創建頭結點
CLinkNode *node = (CLinkNode *)malloc(1 * sizeof(CLinkNode));
if (node == NULL)
{
printf("內存分配失敗!\n");
exit(OVERFLOW);
}
node->data = data;
node->next = head;//頭結點指向頭指針
head->next = node;//頭指針指向頭節點
}
else
{
//找到尾結點位置,插入到尾結點之後
for (target = (*list)->next; target->next != *list; target = target->next);
head_node = target->next;
CLinkNode *node = (CLinkNode*)malloc(1 * sizeof(CLinkNode));
if (!node)
{
printf("內存分配失敗!\n");
exit(OVERFLOW);
}
node->data = data;
node->next = head_node;
target->next = node;
}
}
return OK;
}
//訪問函數
void visit(ElemType e)
{
printf("%d ",e);
}
//遍歷鏈表
Status TraverseCLinkList(CLinkList list, void(*visit)(ElemType e))
{
if (list == NULL)
{
printf("鏈表不存在!\n");
exit(OVERFLOW);
}
CLinkNode *target = NULL;
for (target = list->next; target->next != list; target = target->next)
{
visit(target->data);
}
visit(target->data);
printf("\n");
return OK;
}
//獲取鏈表長度
Status LengthCLinkList(CLinkList list)
{
int len = 0;
CLinkNode *target = NULL;
for (target = list->next; target != list; target = target->next)
{
len++;
}
return len;
}
//在指定位置插入節點
Status InsertCLinkList(CLinkList *list, int i, ElemType e)
{
if (i < 1 || i - 1 > LengthCLinkList(*list))
{
printf("輸入位置不合法!\n");
return ERROR;
}
int j = 1;
CLinkNode *target = NULL;
//尋找插入位置的前一個節點
for (target = (*list)->next; j < i-1 && target != (*list); target = target->next,++j);
CLinkNode *node = (CLinkNode *)malloc(1 * sizeof(CLinkNode));
if (!node)
{
printf("內存分配失敗!\n");
exit(OVERFLOW);
}
node->data = e;
node->next = target->next;
target->next = node;
return OK;
}
//刪除指定位置的節點
Status DeleteCLinkList(CLinkList list, int i, ElemType *e)
{
if (!list)
{
printf("鏈表不存在!\n");
return ERROR;
}
if (i < 0 || i > LengthCLinkList(list))
{
printf("輸入位置不合法\n");
return ERROR;
}
CLinkNode *target = NULL;
int j = 1;
//找到刪除節點的前一個位置
for (target = list->next; j < i-1 && target != list; target = target->next, ++j);
CLinkNode *del_node = target->next;
*e = del_node->data;
target->next = del_node->next;
free(del_node);//不能直接釋放指向鏈表中節點的指針,只能釋放指向節點的指針
return OK;
}
//compare()函數
bool compare(ElemType a, ElemType b)
{
return a ==b;
}
//獲取鏈表中與e滿足compare關係的第一個節點的位置【索引】
Status LocateElem(CLinkList list, int e, bool(*compare)(ElemType a, ElemType b))
{
if (!list)
{
printf("鏈表不存在!\n");
return ERROR;
}
int i = 0;
CLinkNode *target = NULL;
for (target = list->next; target->next != list; target = target->next)
{
i++;
if (compare(e, target->data))
break;
}
if (i == 0)
{
printf("%d在鏈表中不存在\n",e);
return ERROR;
}
return i;
}
//獲取第i個節點爲的數據
Status LocatePos(CLinkList list, Status i,ElemType *e)
{
if (!list)
{
printf("線性鏈表不存在\n");
return ERROR;
}
if (i < 1 || i > LengthCLinkList(list))
{
printf("輸入位置不合法\n");
return ERROR;
}
int j = 1;
CLinkNode *target = NULL;
//尋找節點位置
for (target = list->next; j < i && target->next != list; target = target->next,j++);
*e = target->data;
return OK;
}
int main()
{
CLinkList list = NULL;
InitCLinkList(&list);
printf("遍歷鏈表元素:\n");
TraverseCLinkList(list, visit);
/*
ElemType data;
LocatePos(list, 2, &data);
printf("第二個節點的數據是:%d\n",data);
int data;
scanf_s("%d",&data);
printf("%d的位置是:%d\n",data,LocateElem(list,data,compare));
//printf("鏈表長度爲:%d\n",LengthCLinkList(list));
int pos, data;
printf("輸入插入位置:\n");
scanf_s("%d",&pos);
printf("輸入插入數據:\n");
scanf_s("%d",&data);
InsertCLinkList(&list, pos, data);
printf("遍歷鏈表元素:\n");
TraverseCLinkList(list, visit);
printf("輸入刪除位置:\n");
scanf_s("%d", &pos);
DeleteCLinkList(list, pos, &data);
printf("刪除元素是:%d\n",data);
printf("遍歷鏈表元素:\n");
TraverseCLinkList(list, visit);
*/
return 0;
}
雙向鏈表
兩個指針,一個指向前驅,一個指向後繼
# include<stdio.h>
# include<string.h>
# include<stdlib.h>
# define OK 1
# define ERROR 0
# define TRUE 1
# define FALSE 0
# define END 0
# define OVERFLOW -1
# define ElemType int
# define Status int
typedef struct DuLNode
{
ElemType data;
struct DuLNode *prior, *next;
}DuLNode,*DuLinkList;
Status InitDuLinkList(DuLinkList *list)
{
DuLNode *head = (DuLNode *)malloc(1 * sizeof(DuLNode));
if (!head)
{
printf("內存分配失敗!\n");
return ERROR;
}
*list = head;
ElemType data;
DuLNode *target = head;
target->prior = NULL;
target->next = NULL;
printf("輸入鏈表數據,0表示輸入結束\n");
while (1)
{
scanf_s("%d",&data);
if (data == 0)
break;
DuLNode *node = (DuLNode *)malloc(1 * sizeof(DuLNode));
node->data = data;
node->next = NULL;
node->prior = target;
target->next = node;
target = node;
}
return OK;
}
//訪問函數
void visit(ElemType e)
{
printf("%d", e);
}
//遍歷鏈表
Status TraverseDuLinkList(DuLinkList list, void(*visit)(ElemType e))
{
if (!list)
{
printf("鏈表不存在!\n");
exit(OVERFLOW);
}
DuLNode *target = list->next;
for (; target != NULL; target = target->next)
{
visit(target->data);
if(target->next != NULL)
printf("<-->");
}
printf("\n");
return OK;
}
//頭插法
Status InsertDuLinkListHead(DuLinkList *list,ElemType e)
{
DuLNode *node = (DuLNode *)malloc(1 * sizeof(DuLNode));
node->data = e;
node->next = (*list)->next;
node->prior = *list;
(*list)->next = node;
return OK;
}
//尾插法
Status InsertDuLinkListTail(DuLinkList *list, ElemType e)
{
DuLNode *node = (DuLNode *)malloc(1 * sizeof(DuLNode));
node->data = e;
node->next = NULL;
DuLNode* target = (*list)->next;
while (target->next)
{
target = target->next;
}
target->next = node;
node->prior = target;
return OK;
}
//插入節點
Status InsertDuLinkList(DuLinkList *list, int i, ElemType e)
{
if (!(*list))
{
printf("鏈表不存在!\n");
return ERROR;
}
DuLNode *target = (*list)->next;
int j = 1;
while (j < i - 1)
{
target = target->next;
}
DuLNode *node = (DuLNode *)malloc(1 * sizeof(DuLNode));
if (!node)
{
printf("內存分配失敗!\n");
return ERROR;
}
node->data = e;
node->next = target->next;
node->prior = target;
target->next = node;
return OK;
}
//刪除節點
Status DeleteDuLinkList(DuLinkList *list, int i , ElemType *e)
{
if (!(*list))
{
printf("鏈表不存在!\n");
return ERROR;
}
DuLNode *target = (*list)->next;
int j = 1;
while (j < i - 1)
{
target = target->next;
j++;
}
DuLNode *del_node = target->next;
*e = del_node->data;
target->next = del_node->next;
del_node->next->prior = target;
free(del_node);
return OK;
}
//長度函數
Status LengthDuLinkList(DuLinkList list)
{
int len = 0;
DuLNode *target = list->next;
while (target)
{
len++;
target = target->next;
}
return len;
}
bool compare(ElemType a, ElemType b)
{
return a == b;
}
//獲取鏈表中與e滿足compare關係的第一個節點的位置【索引】
Status LocateElem(DuLinkList list, int e, bool(*compare)(ElemType a, ElemType b))
{
if (!list)
{
printf("鏈表不存在!\n");
return ERROR;
}
int i = 0;
DuLNode *target = NULL;
for (target = list->next; target->next != list; target = target->next)
{
i++;
if (compare(e, target->data))
break;
}
if (i == 0)
{
printf("%d在鏈表中不存在\n", e);
return ERROR;
}
return i;
}
//獲取第i個節點爲的數據
Status LocatePos(DuLinkList list, Status i, ElemType *e)
{
if (!list)
{
printf("線性鏈表不存在\n");
return ERROR;
}
if (i < 1 || i > LengthDuLinkList(list))
{
printf("輸入位置不合法\n");
return ERROR;
}
int j = 1;
DuLNode *target = NULL;
//尋找節點位置
for (target = list->next; j < i && target->next != list; target = target->next, j++);
*e = target->data;
return OK;
}
int main()
{
DuLinkList list;
ElemType data;
InitDuLinkList(&list);
printf("遍歷鏈表\n");
TraverseDuLinkList(list, visit);
printf("鏈表長度是:%d\n", LengthDuLinkList(list));
LocateElem(list, 2, compare);
/*
InsertDuLinkList(&list, 2, 4);
printf("遍歷鏈表\n");
TraverseDuLinkList(list, visit);
DeleteDuLinkList(&list, 2, &data);
printf("遍歷鏈表\n");
TraverseDuLinkList(list, visit);
*/
return 0;
}