线性表篇

来源:互联网 发布:s25fl256s 单片机 编辑:程序博客网 时间:2024/06/14 04:22

<<------表示方法------>>

1. 线性表之顺序表示

方法一:动态分配

#define LIST_INIT_SIZE        100   //线性表存储空间的初始分配量

#define LISTINCREMENT     10     //线性表存储空间的分配增量

typedef struct

{

       ElemType *elem;     //存储空间基址

       int lenght;           //当前长度,即元素个数

       int listsize;           //当前分配的存储容量

}SqList;

方法二:静态分配

#define MaxSize   50

typedef struct

{

       ElemType data[MaxSize];   //存放顺序表元素

       int length;                 //存放顺序表长度

}SqList;

2. 线性表之链式表示

typedef struct LNode

{

       ElemType data;

       struct LNode *next;

}LNode, *LinkList;

3. 线性表之双向链表

typedef struct DuLNode

{

       ElemType data;

       struct DuLNode *prior;

       struct DuLNode *next;

}DuLNode, *DuLinkList;

 

<<------常见算法------>>

1.  设计一个高效算法,将顺序表的所有元素逆置,要求算法空间复杂度为O(1).

:扫描顺序表L的前半部分元素,对于元素L.data[i](0<=i<L.length/2),将其与后半部分对应元素L.data[L.length-i-1]进行交换。算法如下:

void reverse(SqList &L)

{

       int i;

       ElemType x;   //O(1)

       for(i=0; i<L.length/2; i++)

       {

              x = L.data[i];

              L.data[i] = L.data[L.length-i-1];

              L.data[L.length-i-1] = x;

       }

}

2.  设计一个高效算法,从顺序表中删除所有元素值为x的元素,要求空间复杂度为O(1).

:首先确定顺序表L中第一个值为x的元素的位置i,然后依次检查L.data[i+1]~L.data[L.length-1]中每一个元素L.data[j](i+1<=j<L.length),L.data[j]!=x,则将L.data[j]存入L.data[i]中,并令i1。最后顺序表长为i。算法如下:

void delall(SqList &L, ElemType x)

{

       int i=0, j;

       while(i<L.length && L.data[i] != x)  //查找第一个为x的元素

              i++;

       for(j=i+1; j<L.length; j++)

              if(L.data[j] != x)

              {

                     L.data[i] = L.data[j];

                     i++;

              }

              L.length = i;

}

3.  设计一个顺序表L,其元素为整形数据,设计一个算法将L中所有小于0的整数放在前半部分,大于等于0的整数放在后半部分。

:从L的两端查找,前端大于等于0的元素(位置i),后端找小于0的元素(位置j),然后交换两位置的元素。算法如下:

void move(SqList &L)

{

       ElemType temp;

       int i=0,j=L.length-1;

       while(i<j)

       {

              while(i<j && L.data[i]<0)

                     i++;                          //从前向后找大于等于的元素L.data[i]

              while(i<j && L.data[j]>=0)

                     j--;                           //从后向前找小于的元素L.data[j]

              if(i < j)                          //交换L.data[i]L.data[j]

              {

                     temp = L.data[i];

                     L.data[i] = L.data[j];

                     L.data[j] = temp;

              }

       }

}

4. 设计一个算法从顺序表中删除重复的元素,并使剩余元素间的相对次序保持不变。

:假设L.data[0]~L.data[j]中没有重复的元素。检测L.data[i](j<i<L.length),若L.data[i]L.data[0]~L.data[j]中任何一个元素都不相同,则将L.data[i]存入L.data[j+1]。算法如下:

void delsame(SqList &L)

{

       int i, j, k;

       if(L.length > 0)

       {

              j = 0;

              for(i=1; i<L.length; i++)

              {

                     k = 0;

                     while(k<=j && L.data[k] != L.data[i])

                            k++;

                     if(k > j)

                     {

                            j++;

                            L.data[j] = L.data[i];

                     }

              }

              L.length = j+1;

       }

}

5. 有序顺序表的归并算法

void Merge(SqList L1, SqList L2, SqList L3)

{

       int i=0, j=0, k=0;  //i扫描L1j扫描L2

       while(i<L1.length && j<L2.length)

       {

              if(L1.data[i] < L2.data[j])

              {

                     L3.data[k] = L1.data[i];

                     i++; k++;

              }

              else if(L1.data[i] > L2.data[j])

              {

                     L3.data[k] = L2.data[j];

                     j++; k++;

              }

              else    //L1.date[i] == L2.data[j]

              {

                     L3.data[k] = L1.data[i];

                     i++; j++; k++;

              }

       }

       while(i<L1.lenght)    //L1未扫描完,将余下的元素归并至L3

       {

              L3.data[k] = L1.data[i];

              i++; k++;

       }

       while(j<L1.lenght)    //L2未扫描完,将余下的元素归并至L3

       {

              L3.data[k] = L2.dataj];

              j++; k++;

       }

       L3.length = k;

}

6.  有序单链表的归并算法

void Merge(LinkList La, LinkList Lb, LinkList Lc)

{

       LinkList pa = La->next, pb = Lb->next, pc;   //pa扫描L1pb扫描L2

       Lc = pc = La;     //使Lc的头结点指向La头结点,pc指向Lc尾节点

       while(pa != NULL && pb = NULL)

       {

              if(pa->data < pb->data)

              {

                     pc->next = pa;

                     pc = pa;

                     pa = pa->next;

              }

              else if(pa->data > pb->data)

              {

                     pc->nex = pb;

                     pc = pb;

                     pb = pb->next;

              }

              else    // pa->data == pb->data

              {

                     pc->next = pa;

                     pc = pa;

                     pa = pa->next;

                     pb = pb->next;

              }

       }

       pc->next = pa ? pa : pb;   //将为扫描完的节点接入pc

       pc->next = NULL;

}

7. 有一个线性表,采用带头结点的单链表L存储,设计一个算法将其就地逆置。所谓就地就是指辅助空间为O(1).

:用p指针扫描原单链表,先将头结点Lnext设为NULL而变成一个空链表,然后将凭借点采用头插法插入到L中。算法如下:

void Reverse(LinkList &L)

{

       LinkList p = L->next, q;

       L->next = NULL;

       while(p != NULL)

       {

              q = p->next;

              p->next = L->next;   //p节点插入到新链表的前面

              L->next =  p;

              p = q;

       }

}

原创粉丝点击