線性表-數組+單鏈表+靜態鏈表+循環鏈表+循環鏈表

目錄

線性表

概念

ADT 

線性表的兩種存儲結構 

順序存儲結構【順序映像】

 鏈式存儲結構


線性表

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

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章