因为操作的需要现在重新学习了数据结构相关知识,故以此文来总结一下线性表的操作和基本知识 (很多函数linux内核已经设置了errno)
声明:因个人能力有限,本文仅是个人的学习记录笔记,有错误之处还望指出
1.线性表的定义
2.线性表的逻辑特性
线性表只有一个表头元素和表尾元素,表头元素没有前驱,表尾元素没有后继,其余元素都只有一个直接前驱和一个直接后继。
3.线性表的存储结构
线性表的存储结构有顺序存储和链式存储两种,即顺序表和链表。
顺序表的特性:
链表的特性:
1.顺序表的结构体定义
#define MAXSIZE 100; //定义顺序表的元素个数
typedef struct {
int data[MAXSIZE]; //存放顺序表的数组
int length; //定义顺序表长度(元素个数)
}Sqlist;
2.单链表的节点定义
typedef struct LNode{
int data;
struct LNode *next;
}LNode;
3.双链表的节点定义
typedef struct DLNode{
int data; //数据域
struct DLNode *next; //指向前驱结点的指针
struct DLNode *prior; //指向后继结点的指针
}DLNode;
重点:结点是内存中一片由用户分配的存储空间,只有一个地址来表示它的存在,没有显示的名称。所以在分配链表结点空间的时候,同时定义一个指针,用来存储这片空间的地址,并且用这个指针名称来作为结点名称。
4.顺序表的操作
int findElem(Sqlist L,int e){
int i;
for(i = 0; i < L.length;i++){
if(L.data[i] == e)
break;
else
return -1;
}
return i;
}
//因为此次要插入数据,故采用引用型
/*
*@先找到要插入的位置,然后将插入位置以后的数据后移,放入数据,并将表长加一
*/
int insertElem(Sqlist &L,int p,int e){
int i;
//判断插入位置是否有效
if(p<0||p>L.length||L.length == MAXSIZE)
return 0;
for(i=L.length-1;i>=p;--i)
L.data[i+1]=L.data[i];
e=L.data[p];
++(L.length); //表长+1
return 1;
}
//因为此次要删除数据,故采用引用型
/*
*@先找到要删除的位置,然后将删除位置以后的数据前移,并将表长减一
*/
//for循环的限制条件length具体怎么求,要将末尾的结果待人最后一次计算,确定
int deleteElem(Sqlist &L,int p,int &e){
int i;
//判断插入位置是否有效
if(p<0||p>L.length-1)
return 0;
e=L.data[p];
for(i=p;i<=L.length-1;++i)
L.data[1]=L.data[i+1];
e=L.data[p];
--(L.length); //表长-1
return 1;
}
5.单链表的操作
//将元素值单调递增的链表A,B连接成有序递增的链表C
void merge(LNode *&C,LNode *A,LNode *B){
LNode *p = A->next; //指向第一个数据结点
LNode *q = B->next;
LNode *r; //r始终指向C的终端结点
C = A; //用A的头来做C的头
C->next = NULL;
free(B); //B的头结点已经无用,释放内存
r = C; //r指向c此时既是头结点也是终端结点
while(p!=NULL && q!=NULL){ //当p,q都不为空的时候开始比较,小的放入c中
if(p->data >= q->data){
r->next = q;
q = q -> next; //尾插法的思想
r = r ->next;
}else{
r->next = p;
p = p -> next;
r = r -> next;
}
}
r->next = NULL;
//当还有结点未成功连接上时
if(p != NULL)
r->next = p;
if(q != NULL)
r->next = q;
}
void createList(LNode *&C,int A[],int n){
LNode *s,*r; //新建两个结点,r始终指向终端结点,s用来指向新申请的结点
int i;
C=(LNode *)malloc(sizeof(LNode));
C->next = NULL;
r = C; //r指向头节点,此时的头结点就是终端结点
for(i = 0 ; i < n ; ++i){
s=(LNode *)malloc(sizeof(LNode));
s->data=a[i];
r->next = s;
r= r->next;
}
r->next=NULL;
}
void merge(LNode *&C,LNode *A,LNode *B){
LNode *p =A->next;
LNode *q =B->next;
LNode *r;
C=A;
C->next = NULL;
r = C;
free(B);
while(p != NULL && q != NULL){
if(p->data >= q-> data){ //头插法
r = p;
r->next = C->next;
C->next = r;
}else{
r = q;
r->next = C->next;
C->next = r;
}
}
//两个链表的元素个数不一样的时候,将其他元素加入链表
while(p!=NULL){
r=p;
p=p->next;
r->next = C->next;
}
while(q!=NULL){
r=q;
q=q->next;
r->next = C->next;
}
}
int findAnddelete(LNode *C,int x){
LNode *q,*p;
p=c;
while(p->next !=NULL ){
if(p->next->data == x)
break;
p=p->next;
}
//查找部分结束
if(p->next==NULL)
return 0;
else{
q=p->next;
p->next=p->next->next;
free(q);
}
return 1;
}
6.双链表的操作
void createDlistR(DLnode *L,int a[],int n){
DLnode *s,*r;
int i;
L=(DLnode *)malloc(sizeof(DLnode));
L->prior=NULL;
L->next=NULL;
r=L; //和单链表一样,r始终指向终端结点(开头结点也是尾结点)
for(i=0; i < n ; ++i){
s=(DLnode *)malloc(sizeof(DLnode)); //创建新的结点
s->data=a[i]; //把s查到r的尾部,并r指向s
r->next = s;
s-prior = r;
r=s;
}
r->next = NULL; //链表结尾
}
//在双链表中查找第一个值为x的结点,成功返回结点,失败返回NULL
DLnode *findNode(DLnode *c,int x){
DLnode q=c;
while(q->next != NULL){
if(q->data == x)
break;
q=q->next;
}
return q; //如果找到则返回结点q,没找到q的内容也为NULL,将返回值统一
}
//在双链表中插入结点
//s为要插入的节点
s->next = p->next;
s->prior = p;
p->next = s;
s->next->prior = s;
//在双链表中删除结点
//q为要删除的结点
q=p->next;
p->next=q->next;
q->next->prior = p;
free(q); //释放内存
关于我:一个就要进入互联网,经历社会毒打的99小伙
下一站(javascript)
下一站(html)