数据结构-表-笔记


数据结构

Def

线性表是具有n个相同数据类型的有序序列,其中n为表长,当n=0时,称之为空表。

相关概念

前驱元

除第一个元素外,其他任何元素都有唯一前驱,即A[i-1]为A[i]的前驱元。

后驱元

除最后一个元素外,每个元素都有唯一后驱,即A[i+1]为A[i]的后驱元。

基本操作

初始化表,销毁表,插入元素,删除元素,按位查找,按值查找,输出表,表判空,求表长等操作。

顺序表

Def

用顺序存储的方式实现线性表的存储,把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。

相关操作

存储结构(数组)
struct Node{
	ElemType data[N];
	int length;
}SqList;
初始化表
void InitList( SqList &L ){
	for( int i = 0 ; i < N ; i++ ) data[i] = 0;
	L.length = 0;
}
插入元素
bool ListInsert( SqList &L, int pos, int num ){
    if( pos == 0 || pos > L.lenghth+1 || L.length >= MAXN ) return FALSE;
    
	for( int i = L.length() ; i >= pos ; i-- ){
        L.data[i] = L.data[pos-1];
    }
    L.data[pos-1] = num;
    L.length++;
    
    return TRUE;
}
删除元素并返回删除元素
bool DeteleList( SqList &L, int pos, int &e ){
    if( pos > L.length || pos == 0 ) return FALSE;
    e = data[pos-1];
    for( int i = pos-1 ; i <= L.length ; i++ ){
        data[pos] = data[pos];
    }
    L.length--;
    return TRUE;
}
按位查找
int GetElem( SqList L, int pos ){
    return data[pos-1];
}
按值查找
int LocateElem( SqList L, int num ){
    for( int i = 0 ; i < L.length ; i++ ){
        if( data[i] == num ) return i+1;
    }
    return 0;
}

链表

Def

链表由一系列不必再内存中相连的结构组成,每一个结构均含有元素和只想包含该元素后继元的结构的指针。

相关操作

单链表存储结构
typedef struct Node{
    Elemtype Element;
    struct Node *next;
}LNode,*LinkList;//LNode->强调是个结点,LinkList强调是个链表
初始化链表
//带头节点
bool InitList( LinkList &L){
	L = (LNode*)malloc(sizeof(LNode));
	if( L == NULL ) return FALSE;
	L->next = NULL;
	return TRUE;
}
/*
bool InitList( LinkList &L ){
	L = NULL;
	return TRUE;
}
*/

按位序插入

bool InertList( LinkList &L, int pos, int num ){
    if( pos < 1 ) return FALSE;
    LNode *p;
    int j = 0;
    p = L;
    while( p->next != NULL && j < pos-1 ){
        p = p->next;
        j++;
    }
    if( p == NULL )	return FALSE;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = num;
    s->next = p->next;
    p->next = s;
    return TRUE;
}
/*
不带头节点的按位序插入
bool InsertList( LinkList &L, int pos, int num ){
	if( pos == 0 ) return FALSE;
	if( pos == 1 ){
		LNode *s;
		s = (LNode *)malloc(sizeof(LNode));
		s->data = num;
		s->next = L;
		L = s;
		return TRUE;
	}
	LNode *p;
	p = L;
	int j = 0;
	while( p != NULL && j < pos-1 ) { p=p->next;j++; }
	if( p == NULL ) return TRUE;
	LNode *s = (LNode *)malloc(sizeof(LNode));
	s->data = num;
	s = p->next;
	p->next = s;
	return TRUE;
}
*/
按位序删除并返回值
bool ListDete( LinkList &L, int pos, int &e ){
	if( pos == 0 ) return FALSE;
    LNode *p;
    p = L;
   	int j = pos;
    while( p->next != NULL && j < pos-1 ){ p = p->next; j++; }
    if( p == NULL ) return FALSE;
    LNode *q = p->next;
    e = q->data;
    p->next = q->next;
    free(q);
    return TRUE;
}
指定结点后插
bool InertNextNode( LNode *p, ElemType e ){
    if( p == NULL ) return FALSE;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if( s == NULL ) return FALSE;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return TRUE;
}
指定节点前插(p变s,s变p)
bool InertPriorNode( LNode *p, LNode *s){
    if( p == NULL || s == NULL) return FALSE;
    s->next = p->next;
    p->next = s;
    ElemType temp = p->data;
    p->data = s->data;
    s->data = temp;
    return TRUE;
}
指定节点删除
bool DeleteNode( LNode *p ){
	if( p == NULL ) return FALSE;
    LNode *q = p->next;
    p->data = p->next->data;
    p->next = q->next;
    free(q);
    return TRUE;
}
按位查找O(n)
LNode *GetElem( LinkList &L, int pos ){
	if( pos < 0 ) return NULL;
	LNode *p;
	int j = 0;
	p = L;
	while( p != NULL && j < i ){
		p = p->next;
		j++;
	}
	return p;
}
按值查找O(n);
LNode *LocateElem( LinkList L, ElemType e ){
    LNode *p = L->next;
    while( p != NULL && p->data != e ){
        p = p->next;
    }
    return p;
}
求表长
int length( LinkList L ){
	int len = 0;
	LNode *p = L;
	while( p->next != NULL ){
		p = p->next;
		len++;
	}
	return len;
}
尾插法
LinkList List_TailInsert( LinkList &L ){
	int x;
    L = (LinkList)malloc(sizeof(LNode));
    LNode *s, *r = L;
    scanf("%d",&x);
    while( x != END ){
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        r = s;
        scanf("%d",&x);
    }//END 自定义终止
    r->next = NULL;//尾结点为空
    return L;
}
头插法
LinkList List_headInsert( LinkList &L ){
    LNode *s;
    int x;
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    scanf("%d",&x);
    while( x != END ){
        s = (LNode)malloc(sizeof(LNode));
        s->data = x;
        s->next = L->next;
        L->next = s;
        scanf("%d",&x);
    }
    return L;
}
//可以实现链表的逆置

双链表

优势

对比单链表,可以得知前后结点,存储密度更低。

相关操作

代码定义
Typedef struct DNode{
    ElemType data;
    struct DNode *prior, *next;
}DNode, *DLinkList;
初始化双链表
bool InitDLinkList( DLinkList &L ){
    L = (DNode *)malloc( sizeof(DNode));
    if( L == NULL ) return FALSE;
    L->prior = NULL; // 头结点永远指向NULL
    L->next = NULL;
    return TRUE;
}
插入
bool InsertNextDNode( DNode *p, DNode *s ){
    if( p == NULL && s == NULL ) return FALSE;
    s->next = p->next;
    if( p->next != NULL ) 
        	p->next->prior = s;
    s->prior = p;
    p->next = s;
    return TRUE;
}
删除后继节点
void DeleteNextDNode( DNode *p ){
    if( p == NULL ) return FALSE;
    DNode *q = p->next;
    if( q == NULL ) return FALSE;
    p->next = q->next;
    if( q->next != NULL ) 
        	q->next->prior = p;
   	free(q);
    return TRUE;
}
删除双链表
void DesrtoryList( DLinkList &L ){
    while( L->next != NULL ) DeleteNextDNode(L);
    free(L);//释放头结点
    L = NULL;//头指针指向空
}
遍历
//后向遍历
while( p != NULL ){
    p = p->next;
}
//前向遍历
while( p != NULL ){
    p = p->prior;
}
//前向遍历跳过头节点
while( p->prior != NULL ) p = p->prior;